2010-11-21 5 views
8

Je souhaite implémenter une fonctionnalité qui permet à l'utilisateur de rogner un fichier audio (.caf) qu'il a précédemment enregistré. La partie enregistrement fonctionne déjà, mais comment puis-je ajouter une fonction de recadrage similaire à celle de l'application Voicememos. Y a-t-il un api pour les utilisations d'Apple tondeuse audio? Toute aide serait formidable ...Ajuster l'audio avec iOS

Répondre

20

Comment utiliser l'AVFoundation? Importez le fichier audio dans un AVAsset (composition, etc), puis vous pouvez l'exporter - définir l'heure préférée + durée - dans un fichier.

J'ai écrit il y a quelque temps une fonction de stock qui exporte un actif dans un fichier, vous pouvez également spécifier un audiomix. Comme ci-dessous, il exporte tout le fichier, mais vous pouvez ajouter un NSTimeRange à exporter.timeRange et voilà. Je n'ai pas testé cela mais je devrais travailler (?). Une autre alternative pourrait être d'ajuster les plages de temps lors de la création des pistes AVAsset +. Bien sûr, l'exportateur ne gère que m4a (AAC). Désolé si ce n'était pas ce que vous vouliez.

-(void)exportAsset:(AVAsset*)asset toFile:(NSString*)filename overwrite:(BOOL)overwrite withMix:(AVAudioMix*)mix { 
//NSArray* availablePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset]; 

AVAssetExportSession* exporter = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A]; 

if (exporter == nil) { 
    DLog(@"Failed creating exporter!"); 
    return; 
} 

DLog(@"Created exporter! %@", exporter); 

// Set output file type 
DLog(@"Supported file types: %@", exporter.supportedFileTypes); 
for (NSString* filetype in exporter.supportedFileTypes) { 
    if ([filetype isEqualToString:AVFileTypeAppleM4A]) { 
     exporter.outputFileType = AVFileTypeAppleM4A; 
     break; 
    } 
} 
if (exporter.outputFileType == nil) { 
    DLog(@"Needed output file type not found? (%@)", AVFileTypeAppleM4A); 
    return; 
} 

// Set outputURL 
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString* parentDir = [NSString stringWithFormat:@"%@/", [paths objectAtIndex:0]]; 

NSString* outPath = [NSString stringWithFormat:@"%@%@", parentDir, filename]; 

NSFileManager* manager = [NSFileManager defaultManager]; 
if ([manager fileExistsAtPath:outPath]) { 
    DLog(@"%@ already exists!", outPath); 
    if (!overwrite) { 
     DLog(@"Not overwriting, uh oh!"); 
     return; 
    } 
    else { 
     // Overwrite 
     DLog(@"Overwrite! (delete first)"); 
     NSError* error = nil; 
     if (![manager removeItemAtPath:outPath error:&error]) { 
      DLog(@"Failed removing %@, error: %@", outPath, error.description); 
      return; 
     } 
     else { 
      DLog(@"Removed %@", outPath); 
     } 
    } 
} 

NSURL* const outUrl = [NSURL fileURLWithPath:outPath]; 
exporter.outputURL = outUrl; 
// Specify a time range in case only part of file should be exported 
//exporter.timeRange = 

if (mix != nil) 
    exporter.audioMix = mix; // important 

DLog(@"Starting export! (%@)", exporter.outputURL); 
[exporter exportAsynchronouslyWithCompletionHandler:^(void) { 
    // Export ended for some reason. Check in status 
    NSString* message; 
    switch (exporter.status) { 
     case AVAssetExportSessionStatusFailed: 
      message = [NSString stringWithFormat:@"Export failed. Error: %@", exporter.error.description]; 
      DLog(@"%@", message); 
      [self showAlert:message]; 
      break; 
     case AVAssetExportSessionStatusCompleted: { 
      /*if (playfileWhenExportFinished) { 
      DLog(@"playfileWhenExportFinished!"); 
      [self playfileAfterExport:exporter.outputURL]; 
      playfileWhenExportFinished = NO; 
      }*/ 
      message = [NSString stringWithFormat:@"Export completed: %@", filename]; 
      DLog(@"%@", message); 
      [self showAlert:message]; 
      break; 
     } 
     case AVAssetExportSessionStatusCancelled: 
      message = [NSString stringWithFormat:@"Export cancelled!"]; 
      DLog(@"%@", message); 
      [self showAlert:message]; 
      break; 
     default: 
      DLog(@"Export unhandled status: %d", exporter.status); 
      break; 
    }  
}]; 
} 
+3

Mais cette approche ne permet que le son à enregistrer dans le m4a format, ce si l'on aime couper un mp3 ou un fichier caf et garder le fo rmat? – tommys

+1

Trim mp3 fonctionne aussi, ouput stocké au format m4a Après 2 ans, vous me sauvez encore la vie :) –

1

La réponse ci-dessus de @Jonny est correcte. Voici que j'ajoute l'utilisation de AudioMixer pour ajouter l'effet de fondu pendant le découpage audio.

Sortie:. Support audio coupé à 20 secondes avec 10 secondes fondu en L'assiette étant mis en place dans l'extrait de code a lieu à 30 secondes marque de l'actif et donc la durée de la piste devrait être à moins 50 secondes.

- (BOOL)exportAssettoFilePath:(NSString *)filePath { 


NSString *inputFilePath = <inputFilePath>; 

NSURL *videoToTrimURL = [NSURL fileURLWithPath:inputFilePath]; 
AVAsset *avAsset = [AVAsset assetWithURL:videoToTrimURL]; 

// we need the audio asset to be at least 50 seconds long for this snippet 
CMTime assetTime = [avAsset duration]; 
Float64 duration = CMTimeGetSeconds(assetTime); 
if (duration < 50.0) return NO; 

// get the first audio track 
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio]; 
if ([tracks count] == 0) return NO; 

AVAssetTrack *track = [tracks objectAtIndex:0]; 

// create the export session 
// no need for a retain here, the session will be retained by the 
// completion handler since it is referenced there 
AVAssetExportSession *exportSession = [AVAssetExportSession 
             exportSessionWithAsset:avAsset 
             presetName:AVAssetExportPresetAppleM4A]; 
if (nil == exportSession) return NO; 

// create trim time range - 20 seconds starting from 30 seconds into the asset 
CMTime startTime = CMTimeMake(30, 1); 
CMTime stopTime = CMTimeMake(50, 1); 
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime); 

// create fade in time range - 10 seconds starting at the beginning of trimmed asset 
CMTime startFadeInTime = startTime; 
CMTime endFadeInTime = CMTimeMake(40, 1); 
CMTimeRange fadeInTimeRange = CMTimeRangeFromTimeToTime(startFadeInTime, 
                 endFadeInTime); 

// setup audio mix 
AVMutableAudioMix *exportAudioMix = [AVMutableAudioMix audioMix]; 
AVMutableAudioMixInputParameters *exportAudioMixInputParameters = 
[AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track]; 

[exportAudioMixInputParameters setVolumeRampFromStartVolume:0.0 toEndVolume:1.0 
                timeRange:fadeInTimeRange]; 
exportAudioMix.inputParameters = [NSArray 
            arrayWithObject:exportAudioMixInputParameters]; 

// configure export session output with all our parameters 
exportSession.outputURL = [NSURL fileURLWithPath:filePath]; // output path 
exportSession.outputFileType = AVFileTypeAppleM4A; // output file type 
exportSession.timeRange = exportTimeRange; // trim time range 
//exportSession.audioMix = exportAudioMix; // fade in audio mix 

// perform the export 
[exportSession exportAsynchronouslyWithCompletionHandler:^{ 

    if (AVAssetExportSessionStatusCompleted == exportSession.status) { 
     NSLog(@"AVAssetExportSessionStatusCompleted"); 
    } else if (AVAssetExportSessionStatusFailed == exportSession.status) { 
     // a failure may happen because of an event out of your control 
     // for example, an interruption like a phone call comming in 
     // make sure and handle this case appropriately 
     NSLog(@"AVAssetExportSessionStatusFailed"); 
    } else { 
     NSLog(@"Export Session Status: %ld", (long)exportSession.status); 
    } 
}]; 

return YES;} 

Merci

Pour plus de détails:

https://developer.apple.com/library/ios/qa/qa1730/_index.html