正如可以用AVVideoComposition实现视频的混合一样,也可以用AVAudioMix实现音频的混合,用法也跟AVVideoComposition很相似,
Demo见https://github.com/Phelthas/TEST_XMLCommon
首先创建一个AVMutableComposition,将需要混音的视频或者音频轨道添加进去
AVAssetTrack *videoTrack = [videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
AVAssetTrack *audioTrack1 = [videoAsset tracksWithMediaType:AVMediaTypeAudio].firstObject;
AVAssetTrack *audioTrack2 = [audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject;
AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoCompositionTrack insertTimeRange:videoTimeRange ofTrack:videoTrack atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *audioCompositionTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioCompositionTrack1 insertTimeRange:videoTimeRange ofTrack:audioTrack1 atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *audioCompositionTrack2 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioCompositionTrack2 insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) ofTrack:audioTrack2 atTime:kCMTimeZero error:nil];
self.composition = composition;
然后创建AVMutableAudioMix,创建对应音轨的AVMutableAudioMixInputParameters
并设置音量,赋值给AVMutableAudioMix的inputParameters即可。
注意这里最好用添加到composition中的AVMutableCompositionTrack来初始化AVMutableAudioMixInputParameters
,否则还需要手动设置trackID。(每个track的trackID必须不一样)
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
// 注意:这里必须要用audioCompositionTrack1而不能用audioTrack1,否则会因为trackId不一致而不生效
AVMutableAudioMixInputParameters *inputParameters1 = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:audioCompositionTrack1];
[inputParameters1 setVolume:1 atTime:kCMTimeZero];
AVMutableAudioMixInputParameters *inputParameters2 = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:audioCompositionTrack2];
[inputParameters2 setVolume:0.5 atTime:kCMTimeZero];
audioMix.inputParameters = @[inputParameters1, inputParameters2];
self.audioMix = audioMix;
最后将audioMix赋值给playerItem即可
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
playerItem.audioMix = audioMix;
self.playerItem = playerItem;
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
self.player = player;
[player play];
完成~
如果需要实时修改混音的音量(比如用slider分别控制音轨的音量),需要每次都重新生成AVAudioMix才行,且里面的inputParameters也需要重新生成或者mutableCopy,直接修改原来的音量再赋值是不行的
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
AVMutableAudioMixInputParameters *parameters1 = [[self.audioMix.inputParameters objectAtIndex:0] mutableCopy];
[parameters1 setVolume:self.slider1.value atTime:kCMTimeZero];
AVMutableAudioMixInputParameters *parameters2 = [[self.audioMix.inputParameters objectAtIndex:1] mutableCopy];
[parameters2 setVolume:self.slider2.value atTime:kCMTimeZero];
audioMix.inputParameters = @[parameters1, parameters2];
self.playerItem.audioMix = audioMix;
导出时只需要将AudioMix赋值给exportSession即可,其他完全一样
注意:导出后多个音轨会合并成一个
NSString *userCacheDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSString *outputURLString = [NSString stringWithFormat:@"%@/audioMixOutput.mp4", userCacheDirectory];
NSLog(outputURLString);
[kLXMFileManager removeItemAtPath:outputURLString error:nil];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:self.composition presetName:AVAssetExportPresetHighestQuality];
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.outputURL = [NSURL fileURLWithPath:outputURLString];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.audioMix = self.audioMix;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSLog(@"export success");
} else {
NSLog(@"export failed: %@", exportSession.error);
}
}];
网友评论