I'm trying to merge some audio files (picked via MPMediaPickerController), but the export always fails with error code -12780.
When I try to play my composition with an AVPlayer object, it plays correctly. Just the export fails.
What am I doing wrong?
This is my code:
AVAssetExportSession *exportSession;
AVPlayer *player;
- (void)mergeAudiofiles {
// self.mediaItems is an NSArray of MPMediaItems
if (self.mediaItems.count == 0) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"No Tracks selected."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
return;
}
// Configure audio session
NSError *sessionError;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryAudioProcessing error:nil];
[session setActive:YES error:&sessionError];
if (sessionError) NSLog(@"Session-Error: %@", sessionError.localizedDescription);
// Create composition
AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime position = kCMTimeZero;
for (MPMediaItem *item in self.mediaItems) {
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
AVAsset *asset = [AVAsset assetWithURL:assetURL];
CMTimeRange duration = CMTimeRangeMake(kCMTimeZero, asset.duration);
// duration = CMTimeRangeMake(kCMTimeZero, CMTimeMake(5, 1)); // For player test
NSError *error;
[track insertTimeRange:duration ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] lastObject] atTime:position error:&error];
if (error) NSLog(@"ERROR! :(");
position = CMTimeAdd(position, duration.duration);
}
// Path to output file
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSURL *exportUrl = [NSURL URLWithString:[documentsDirectory stringByAppendingPathComponent:@"export.m4a"]];
NSLog(@"Export URL = %@", exportUrl.description);
// Playing works!
// """"""""""""""
// AVPlayerItem *pitem = [[AVPlayerItem alloc] initWithAsset:composition];
// player = [[AVPlayer alloc] initWithPlayerItem:pitem];
// [player play];
//
// return;
// Export
exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
exportSession.outputURL = exportUrl;
exportSession.outputFileType = AVFileTypeAppleM4A;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch (exportSession.status) {
case AVAssetExportSessionStatusFailed:
NSLog(@"Export failed -> Reason: %@, User Info: %@",
exportSession.error.localizedDescription,
exportSession.error.userInfo.description);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"Export cancelled");
break;
case AVAssetExportSessionStatusCompleted:
NSLog(@"Export finished");
break;
default:
break;
}
}];
}
Need to change your export URL to:
NSURL *exportUrl = [NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:@"export.m4a"]];
You must use fileURLWithPath when referring to file paths. I got hung up by this too until I read this: AVAssetExportSession outputfile