iOS音轨合成(音频与音频|iOS音轨合成(音频与音频,音频与视频)

今天和大家一起分享关于音轨合成的坑(套路!全TM是套路!走一步套一路) 理论部分: 我们需要用到AVURLAsset来初始化文件,然后用AVMutableCompositionAVMutableCompositionTrack来插入音轨,最后用AVAssetExportSession来输出文件
先说音频和音频的合成 首先创建一个AVMutableComposition对象
AVMutableComposition *compostion = [AVMutableComposition composition];
然后通过下面的方法,得到一个AVMutableCompositionTrack对象
AVMutableCompositionTrack *video = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0];
这里的mediaType传入的是文件类型,因为我们即将插入的文件类型是音频,这里要选择AVMediaTypeAudio,支持的类型见下图

iOS音轨合成(音频与音频|iOS音轨合成(音频与音频,音频与视频)
文章图片
可选类型
接下里就是插入了,有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这个参数非常坑人,必须文件的后缀和这里设定的格式相互呼应才行,否则文件无法创建,格式也是五花板门,有兴趣的小伙伴可以自己试试~

iOS音轨合成(音频与音频|iOS音轨合成(音频与音频,音频与视频)
文章图片
各种输出格式
有一些设置需要给出,否者输出时程序会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];
这里的presetNameoutputFileType都要换成一个视频格式,注意不同的presetName会产生不同的outputFileType一定要填写相对应的支持类型,否则会直接crash!

iOS音轨合成(音频与音频|iOS音轨合成(音频与音频,音频与视频)
文章图片
必须是其中的类型 【iOS音轨合成(音频与音频|iOS音轨合成(音频与音频,音频与视频)】
文章参考资料 http://blog.csdn.net/linzhiji/article/details/6736704
http://www.jianshu.com/p/9f83af9dbbef
写在最后 如果有什么遗漏或者错误欢迎指正,共同进步!
附上Demo地址:https://github.com/WeiTChen/multitrackerDemo
原创作品,转载请注明出处

    推荐阅读