Recortar audio con iOS

Quiero implementar una característica que le permita al usuario recortar un archivo de audio (.caf) que grabó perceptivamente. La parte de grabación ya funciona, pero ¿cómo puedo agregar una función de recorte similar a la de la aplicación Voicememos? ¿Hay una API para la recortadora de audio que Apple usa? Cualquier ayuda sería genial …

¿Qué hay de usar la fundación AVFoundation? Importe el archivo de audio en un AVAsset (composición, etc.), luego puede exportarlo (estableciendo el tiempo preferido + duración) a un archivo.

Hace un tiempo escribí una función de stock que exporta un activo a un archivo, también puedes especificar una audiomix. Como a continuación, exporta todo el archivo, pero puede agregar un NSTimeRange a exporter.timeRange y listo. Aunque no lo he probado, pero debería funcionar (?). Otra alternativa podría ser ajustar los intervalos de tiempo al crear las pistas AVAsset +. Por supuesto, el exportador solo maneja m4a (AAC). Lo siento si esto no era lo que querías.

-(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; } }]; } 

La respuesta anterior de @Jonny es correcta. Aquí estoy agregando el uso de AudioMixer para agregar el efecto Fade-In mientras se recorta el audio.

Salida: activo de audio recortado a 20 segundos con un desvanecimiento de 10 segundos. El ajuste que se configura en el fragmento de código tiene lugar en la marca de 30 segundos del activo y, por lo tanto, la duración de la pista debe ser de al menos 50 segundos.

 - (BOOL)exportAssettoFilePath:(NSString *)filePath { NSString *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;} 

Gracias

Para más detalles :

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