AVFoundationを使った動画(.mp4/.mov)と音声(.mp3)の合成エラー
動画ファイル(.mov/.mp4)に.音声(.mp3)をミックスしようと考えており、以下のようなコードで作成しましたが、うまくいきませんでした。動画を書き出してフォトライブラリに保存するところまでは確認済ですが、以下のようにミックスしたものをフォトライブラリに保存しようとするとうまくいきません。
具体的な結果としては、"writeVideoAtPathToSavedPhotosAlbum: completionBlock:^"のassetURLとerrorが両方nilになってしまいます。おそらくうまくミックスしたものがフォトライブラリに保存された場合はこれらの変数がnilになることはないと思いますが、私のコードのミス、またはうまく保存する方法が分かる方はぜひご教示願います。
+ (void)saveMixedMovieInPhotoLibrary {
NSString *videoPath = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp/movie.mov"];
NSURL *exportURL = [NSURL fileURLWithPath:videoPath];
NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"];
NSURL *soundURL = [NSURL fileURLWithPath:soundPath];
AVMutableComposition *composition = [[AVMutableComposition alloc]init];
AVURLAsset *video = [[AVURLAsset alloc]initWithURL:exportURL options:nil];
AVAsset *audioAsset = [AVAsset assetWithURL:soundURL];
// Merge movie and audio
AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, video.duration)
ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *composedTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[composedTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, video.duration)
ofTrack:[[video tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
atTime:kCMTimeZero error:nil];
NSLog(@"%f", CMTimeGetSeconds(video.duration));
// Export
AVAssetExportSession *assetExport = [[AVAssetExportSession alloc] initWithAsset:[AVAsset assetWithURL:exportURL] presetName:AVAssetExportPresetHighestQuality];
if ([[NSFileManager defaultManager] fileExistsAtPath:videoPath]) {
[[NSFileManager defaultManager] removeItemAtPath:videoPath error:nil];
}
assetExport.outputFileType = @"com.apple.quicktime-movie";
assetExport.outputURL = exportURL;
assetExport.shouldOptimizeForNetworkUse = YES;
[assetExport exportAsynchronouslyWithCompletionHandler:^(void) {
NSLog(@"EXPORT STATUS == %@", assetExport.outputURL);
// Save to Library
ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
[assetLibrary writeVideoAtPathToSavedPhotosAlbum:exportURL
completionBlock:^(NSURL *assetURL, NSError *assetError) {
if (assetError) {
NSLog(@"export error!!!!");
}else {
BOOL isDirectory;
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:assetURL.absoluteString isDirectory: &isDirectory]) {
[manager removeItemAtPath:assetURL.absoluteString error:nil];
NSLog(@"AssetURL is Already Exist.");
}else {
NSLog(@"AssetURL == %@", assetURL);
NSLog(@"Class == %@", [assetURL class]);
}
}
}];
}];
}