使用 AVMutableComposition 组合视频和音频
Posted
技术标签:
【中文标题】使用 AVMutableComposition 组合视频和音频【英文标题】:Composing video and audio using AVMutableComposition 【发布时间】:2013-01-09 22:55:44 【问题描述】:我有一个奇怪的问题。在我的应用程序中,我使用下面的代码组合了多个音频和视频文件。一旦我将生成的视频从设备下载到计算机并使用 Quick Time 播放,生成的视频似乎工作正常,但每当我尝试使用 UIWebView 或 AVPLayer 播放新合成的视频时,我只能看到合并视频文件的第一部分。
此外,当我尝试使用 MPMoviePlayerController 播放时,它会挂在“正在加载”中。
我可以听到所有乐曲的音频。为了清楚起见,我有两个数组: 1-带有音频文件路径的音频片段[song1,song2,song3]; 2-带有视频文件路径的moviePieces [movie1,movie2,movie3]; 合并这些文件后,我只能看到movie1,但可以听到song1 + song2 + song3。 附言歌曲和电影的长度不同(差异小于 0.2 秒)。 任何帮助将不胜感激。 先感谢您, 亚努斯
-(void)putFilesTogether
AVMutableComposition *mixComposition = [AVMutableComposition composition];
AVMutableCompositionTrack *videoCompositionTrack =[[AVMutableCompositionTrack alloc]init];
AVMutableCompositionTrack *audioCompositionTrack =[[AVMutableCompositionTrack alloc]init];
NSLog(@" movie %@ audio %@ ", moviePieces, audioPieces);
NSError * error;
for(int i=0;i<moviePieces.count;i++)
NSFileManager * fm = [NSFileManager defaultManager];
NSString * movieFilePath;
NSString * audioFilePath;
movieFilePath = [moviePieces objectAtIndex:i];
audioFilePath = [audioPieces objectAtIndex:i];
if(![fm fileExistsAtPath:movieFilePath])
NSLog(@"Movie doesn't exist %@ ",movieFilePath);
else
NSLog(@"Movie exist %@ ",movieFilePath);
if(![fm fileExistsAtPath:audioFilePath])
NSLog(@"Audio doesn't exist %@ ",audioFilePath);
else
NSLog(@"Audio exists %@ ",audioFilePath);
NSURL *videoUrl = [NSURL fileURLWithPath:movieFilePath];
NSURL *audioUrl = [NSURL fileURLWithPath:audioFilePath];
AVURLAsset *videoasset = [[AVURLAsset alloc]initWithURL:videoUrl options:nil];
AVAssetTrack *videoAssetTrack= [[videoasset tracksWithMediaType:AVMediaTypeVideo] lastObject];
AVURLAsset *audioasset = [[AVURLAsset alloc]initWithURL:audioUrl options:nil];
AVAssetTrack *audioAssetTrack= [[audioasset tracksWithMediaType:AVMediaTypeAudio] lastObject];
videoCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
audioCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime tempTime = mixComposition.duration;
[audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioasset.duration) ofTrack:audioAssetTrack atTime:tempTime error:&error];
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoasset.duration) ofTrack:videoAssetTrack atTime:tempTime error:&error];
if(error)
NSLog(@"Ups. Something went wrong! %@", [error debugDescription]);
NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0];
NSString *caldate = [now description];
float ran = arc4random()%1000;
NSString * pathToSave = [NSString stringWithFormat:@"Output%@%f.mp4",caldate,ran];
pathToSave =[DOCUMENTS_FOLDER stringByAppendingPathComponent:pathToSave];
NSURL *movieUrl = [NSURL fileURLWithPath:pathToSave];
AVAssetExportSession *exporter =[[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetPassthrough];
exporter.outputFileType=AVFileTypeQuickTimeMovie;
exporter.outputURL=movieUrl;
exporter.shouldOptimizeForNetworkUse=YES;
CMTimeValue val = mixComposition.duration.value;
CMTime start=CMTimeMake(0, 600);
CMTime duration=CMTimeMake(val, 600);
CMTimeRange range=CMTimeRangeMake(start, duration);
exporter.timeRange=range;
[exporter exportAsynchronouslyWithCompletionHandler:^
switch ([exporter status])
case AVAssetExportSessionStatusFailed:
NSLog(@"Export failed: %@ %@", [[exporter error] localizedDescription],[[exporter error]debugDescription]);
NSString * message = @"Movie wasn't created. Try again later.";
[self performSelectorOnMainThread:@selector(dismissMe:) withObject:message waitUntilDone:NO];
break;
case AVAssetExportSessionStatusCancelled: NSLog(@"Export canceled");
NSString * message1 = @"Movie wasn't created. Try again later.";
[self performSelectorOnMainThread:@selector(dismissMe:) withObject:message1 waitUntilDone:NO];
break;
case AVAssetExportSessionStatusCompleted:
NSString * message = @"Movie was successfully created.";
CMTime duration = mixComposition.duration;
[self saveData:duration ofPath:pathToSave];
[self cleanFiles];
[self performSelectorOnMainThread:@selector(dismissMe:) withObject:message waitUntilDone:NO];
];
【问题讨论】:
我只合并一个音频/视频文件。问题是,我的视频文件为 40 秒,音频文件为 28 秒。所以剩下的 12 (40-28) 秒 – 我想在音频文件中从 0 秒开始重复它。我该怎么做?有直接的方法吗? 【参考方案1】:问题出在:
videoCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
audioCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
它们需要移到 for 循环体之外。
【讨论】:
以上是关于使用 AVMutableComposition 组合视频和音频的主要内容,如果未能解决你的问题,请参考以下文章
使用 AVPlayer 音频播放 AVMutableComposition 会不同步
使用 AVMutableComposition 组合视频和音频
使用 AVMutableComposition 导出镜像视频会导致调整大小问题
AVFoundation - 视频没有在 AVplayer 的 AVMutablecomposition 中播放