今天和大家一起分享关于音轨合成的坑(套路!全TM是套路!走一步套一路)
理论部分:
我们需要用到AVURLAsset
来初始化文件,然后用AVMutableComposition
和AVMutableCompositionTrack
来插入音轨,最后用AVAssetExportSession
来输出文件
先说音频和音频的合成
首先创建一个AVMutableComposition对象
AVMutableComposition *compostion = [AVMutableComposition composition];
然后通过下面的方法,得到一个AVMutableCompositionTrack对象
AVMutableCompositionTrack *video = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0];
这里的mediaType传入的是文件类型,因为我们即将插入的文件类型是音频,这里要选择AVMediaTypeAudio,支持的类型见下图
接下里就是插入了,有insert和inserts两种插入方式,我们先选择第一种
[video insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[videoAsset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:kCMTimeZero error:nil];
同样的步骤,我们再次插入另一条音轨
AVMutableCompositionTrack *audio = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0]; [audio insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) ofTrack:[audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:kCMTimeZero error:nil];
这样我们就把两条音轨都混合到一起了,接下来就是把它输出成文件,这时候我们需要创建一个Session
AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:compostion presetName:AVAssetExportPresetAppleM4A];
其中presetName
这个参数非常坑人,必须文件的后缀和这里设定的格式相互呼应才行,否则文件无法创建,格式也是五花板门,有兴趣的小伙伴可以自己试试~
有一些设置需要给出,否者输出时程序会crash掉
1.首先是输出路径,切记切记这里的后缀一定要和上面选择的呼应,比如我写的格式为
AVAssetExportPresetAppleM4A
那么我的文件后缀就需要为.m4a,如果用.MP3这种的话是无法正确生成出文件的,有可能会出现空文件的存在.一定要注意!!!
2.则是输出文件类型,这个更是个坑,一不留神就崩了,也是和上面的设置有关,需要给出一个输出类型,根据所选的不同,支持的类型也不同,可以通过
[session supportedFileTypes]
查询,然后根据需要填写对应的类型.(这里一定要先查询,否则很容易因为不支持而crash掉)
3.是否优化,属于可选,但是一般都选择YES
session.outputURL = [NSURL fileURLWithPath:outPutFilePath];
session.outputFileType = @"com.apple.m4a-audio";
session.shouldOptimizeForNetworkUse = YES;
设置完以上之后,我们只需要执行
"[session exportAsynchronouslyWithCompletionHandler:^{
if ([[NSFileManager defaultManager] fileExistsAtPath:outPutFilePath])
{
// 调用播放方法
[self playAudio:[NSURL fileURLWithPath:outPutFilePath]];
}
else
{
NSLog(@"输出错误");
}
}];"
就可以输出了.个人推荐在里面做个判断,因为无论合成失败或者成功,都会调用block内的方法,但是如果失败则不会生成文件.可以通过这个来判是否合成成功.
插入多个
苹果还提供了一个inserts
的函数,我们来试试是否可以批量插入
CMTimeRange range = CMTimeRangeMake(kCMTimeZero, videoAsset.duration);
[video insertTimeRanges:@[[NSValue valueWithCMTimeRange:range],[NSValue valueWithCMTimeRange:range]] ofTracks:@[[videoAsset tracksWithMediaType:AVMediaTypeAudio].firstObject,[audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject] atTime:kCMTimeZero error:nil];
运行!结果是依然还是一条音轨,原来这是个批量添加到尾部音轨的函数,即当A音轨播放完后,B音轨接着A后面无缝添加,而不是同时添加音轨.
音频和视频
大体上和上面一样,我们只需要注意改几个参数就好了
AVMutableCompositionTrack *video = [compostion addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:0];
[video insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:kCMTimeZero error:nil];
因为是视频,所以原来的Audio要全部改成Video
AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:compostion presetName:AVAssetExportPresetMediumQuality];
这里的presetName
和outputFileType
都要换成一个视频格式,注意不同的presetName
会产生不同的outputFileType
一定要填写相对应的支持类型,否则会直接crash!
文章参考资料
http://blog.csdn.net/linzhiji/article/details/6736704
http://www.jianshu.com/p/9f83af9dbbef
写在最后
如果有什么遗漏或者错误欢迎指正,共同进步!
附上Demo地址:https://github.com/WeiTChen/multitrackerDemo
原创作品,转载请注明出处