場(chǎng)景
把多條mp3音頻合并為一條保存并進(jìn)行播放
解決方案
- 首先把全部音頻路徑生成為一個(gè)數(shù)組:
NSMutableArray * fileUrlArr = @[].mutableCopy;
[mp3NameArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *mp3Name = [NSString stringWithFormat:@"%@",obj];
// mp3路徑
NSString *audioFileURL = [[NSBundle mainBundle] pathForResource:mp3Name ofType:@"mp3"];
[fileUrlArr addObject:audioFileURL];
}];
- 通過(guò)以下方法合并音頻,保存在一個(gè)隨機(jī)文件中,因?yàn)槲募绻汛嬖诨蛘呶募夸泴?xiě)入失敗,會(huì)出現(xiàn)【AVAssetExportSessionStatusFailed】錯(cuò)誤碼
///合并音頻
- (void) mergeAVAssetWithSourceURLs:(NSArray *)sourceURLsArr completed:(void (^)(NSString * outputFileUrlStr)) completed{
//創(chuàng)建音頻軌道,并獲取多個(gè)音頻素材的軌道
AVMutableComposition *composition = [AVMutableComposition composition];
//音頻插入的開(kāi)始時(shí)間,用于記錄每次添加音頻文件的開(kāi)始時(shí)間
__block CMTime beginTime = kCMTimeZero;
[sourceURLsArr enumerateObjectsUsingBlock:^(id _Nonnull audioFileURL, NSUInteger idx, BOOL * _Nonnull stop) {
//獲取音頻素材
AVURLAsset *audioAsset1 = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:audioFileURL]];
//音頻軌道
AVMutableCompositionTrack *audioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0];
//獲取音頻素材軌道
AVAssetTrack *audioAssetTrack1 = [[audioAsset1 tracksWithMediaType:AVMediaTypeAudio] firstObject];
//音頻合并- 插入音軌文件
[audioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset1.duration) ofTrack:audioAssetTrack1 atTime:beginTime error:nil];
// 記錄尾部時(shí)間
beginTime = CMTimeAdd(beginTime, audioAsset1.duration);
}];
//導(dǎo)出合并后的音頻文件
//音頻文件目前只找到支持m4a 類(lèi)型的
AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
NSDateFormatter *formater = [[NSDateFormatter alloc] init];
[formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
NSString * timeFromDateStr = [formater stringFromDate:[NSDate date]];
NSString *outPutFilePath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/sound-%@.mp4", timeFromDateStr];
// 音頻文件輸出
session.outputURL = [NSURL fileURLWithPath:outPutFilePath];
session.outputFileType = AVFileTypeAppleM4A; //與上述的`present`相對(duì)應(yīng)
session.shouldOptimizeForNetworkUse = YES; //優(yōu)化網(wǎng)絡(luò)
[session exportAsynchronouslyWithCompletionHandler:^{
if (session.status == AVAssetExportSessionStatusCompleted) {
NSLog(@"合并成功----%@", outPutFilePath);
if (completed) {
completed(outPutFilePath);
}
} else {
// 其他情況, 具體請(qǐng)看這里`AVAssetExportSessionStatus`.
NSLog(@"合并失敗----%ld", (long)session.status);
if (completed) {
completed(nil);
}
}
}];
}
- 輸出合并音頻
// 合并音頻文件生成新的音頻
[self mergeAVAssetWithSourceURLs:musicArr completed:^(NSString *outputFileUrlStr) {
if (!outputFileUrlStr) {
NSLog(@"聲音生成失敗!");
return;
}
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:outputFileUrlStr] error:nil];
[self.audioPlayer play];
}];
參考:
https://www.cxyzjd.com/article/ismilesky/52780349
http://m.itdecent.cn/p/3e357e3129b8
http://www.cocoachina.com/articles/17624