今天和大家一起分享關(guān)于音軌合成的坑(套路!全TM是套路!走一步套一路)
理論部分:
我們需要用到AVURLAsset
來初始化文件,然后用AVMutableComposition
和AVMutableCompositionTrack
來插入音軌,最后用AVAssetExportSession
來輸出文件
先說音頻和音頻的合成
首先創(chuàng)建一個(gè)AVMutableComposition對(duì)象
AVMutableComposition *compostion = [AVMutableComposition composition];
然后通過下面的方法,得到一個(gè)AVMutableCompositionTrack對(duì)象
AVMutableCompositionTrack *video = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0];
這里的mediaType傳入的是文件類型,因?yàn)槲覀兗磳⒉迦氲奈募愋褪且纛l,這里要選擇AVMediaTypeAudio,支持的類型見下圖
接下里就是插入了,有insert和inserts兩種插入方式,我們先選擇第一種
[video insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[videoAsset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:kCMTimeZero error:nil];
同樣的步驟,我們?cè)俅尾迦肓硪粭l音軌
AVMutableCompositionTrack *audio = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0]; [audio insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) ofTrack:[audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:kCMTimeZero error:nil];
這樣我們就把兩條音軌都混合到一起了,接下來就是把它輸出成文件,這時(shí)候我們需要?jiǎng)?chuàng)建一個(gè)Session
AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:compostion presetName:AVAssetExportPresetAppleM4A];
其中presetName
這個(gè)參數(shù)非惩叶郏坑人,必須文件的后綴和這里設(shè)定的格式相互呼應(yīng)才行,否則文件無法創(chuàng)建,格式也是五花板門,有興趣的小伙伴可以自己試試~
有一些設(shè)置需要給出,否者輸出時(shí)程序會(huì)crash掉
1.首先是輸出路徑,切記切記這里的后綴一定要和上面選擇的呼應(yīng),比如我寫的格式為
AVAssetExportPresetAppleM4A
那么我的文件后綴就需要為.m4a,如果用.MP3這種的話是無法正確生成出文件的,有可能會(huì)出現(xiàn)空文件的存在.一定要注意!!!2.則是輸出文件類型,這個(gè)更是個(gè)坑,一不留神就崩了,也是和上面的設(shè)置有關(guān),需要給出一個(gè)輸出類型,根據(jù)所選的不同,支持的類型也不同,可以通過
[session supportedFileTypes]
查詢,然后根據(jù)需要填寫對(duì)應(yīng)的類型.(這里一定要先查詢,否則很容易因?yàn)椴恢С侄鴆rash掉)3.是否優(yōu)化,屬于可選,但是一般都選擇YES
session.outputURL = [NSURL fileURLWithPath:outPutFilePath];
session.outputFileType = @"com.apple.m4a-audio";
session.shouldOptimizeForNetworkUse = YES;
設(shè)置完以上之后,我們只需要執(zhí)行
"[session exportAsynchronouslyWithCompletionHandler:^{
if ([[NSFileManager defaultManager] fileExistsAtPath:outPutFilePath])
{
// 調(diào)用播放方法
[self playAudio:[NSURL fileURLWithPath:outPutFilePath]];
}
else
{
NSLog(@"輸出錯(cuò)誤");
}
}];"
就可以輸出了.個(gè)人推薦在里面做個(gè)判斷,因?yàn)闊o論合成失敗或者成功,都會(huì)調(diào)用block內(nèi)的方法,但是如果失敗則不會(huì)生成文件.可以通過這個(gè)來判是否合成成功.
插入多個(gè)
蘋果還提供了一個(gè)inserts
的函數(shù),我們來試試是否可以批量插入
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];
運(yùn)行!結(jié)果是依然還是一條音軌,原來這是個(gè)批量添加到尾部音軌的函數(shù),即當(dāng)A音軌播放完后,B音軌接著A后面無縫添加,而不是同時(shí)添加音軌.
音頻和視頻
大體上和上面一樣,我們只需要注意改幾個(gè)參數(shù)就好了
AVMutableCompositionTrack *video = [compostion addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:0];
[video insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:kCMTimeZero error:nil];
因?yàn)槭且曨l,所以原來的Audio要全部改成Video
AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:compostion presetName:AVAssetExportPresetMediumQuality];
這里的presetName
和outputFileType
都要換成一個(gè)視頻格式,注意不同的presetName
會(huì)產(chǎn)生不同的outputFileType
一定要填寫相對(duì)應(yīng)的支持類型,否則會(huì)直接crash!
文章參考資料
http://blog.csdn.net/linzhiji/article/details/6736704
http://www.reibang.com/p/9f83af9dbbef
寫在最后
如果有什么遺漏或者錯(cuò)誤歡迎指正,共同進(jìn)步!
附上Demo地址:https://github.com/WeiTChen/multitrackerDemo
原創(chuàng)作品,轉(zhuǎn)載請(qǐng)注明出處