原理理解:
一个视频文件包含了 、 两种类型的资源,我们在给视频添加音频时,其实就是把原视频的音频和视频提取出来,混合新的音频后合成导出。步骤如下:
- 获取视频文件的videoTrack;
- 获取视频文件的audioTrack;
- 获取要添加的音频文件的audioTrack;
- 添加、合成、导出。
在音视频合成中,主要是用到了来进行资源的整合。
代码如下:
- 创建composition
// 创建可变的音视频组合
AVMutableComposition *comosition = [AVMutableComposition composition];
- 提取视频文件的轨道
// 视频资源,self.videoUrl 为视频的资源路径
AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:self.videoUrl options:nil];
// 视频时间范围
CMTimeRange videoTimeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration);
// 给composition添加视频轨道
AVMutableCompositionTrack *videoTrack = [comosition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
// 获取视频资源中的视频轨道
AVAssetTrack *videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject];
// 把从视频资源中获取到的视频轨道加入到可变轨道videoTrack中
//timeRange表示时间段,track是视频资源中的轨道,atTime表示开始时间
[videoTrack insertTimeRange:videoTimeRange ofTrack:videoAssetTrack atTime:kCMTimeZero error:nil];
//视频原音的音频处理
//给composition添加音频轨道
AVMutableCompositionTrack *originalAudioTrack = [comosition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
// 获取视频资源中的音频轨道
AVAssetTrack *originalAudioAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];
// 将获取到的音频轨道加入到可变音频轨道originalAudioTrack中
[originalAudioTrack insertTimeRange:videoTimeRange ofTrack:originalAudioAssetTrack atTime:kCMTimeZero error:nil];
- 提取音频文件的轨道
// 获取音频资源,self.fileUrl为要添加到视频中的音频资源路径
AVURLAsset *audioAsset = [[AVURLAsset alloc] initWithURL:self.fileUrl options:nil];
//时间段,这里需要考虑音频时长大于视频时长的情况
CMTimeRange audioTimeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);
// 给composition添加可变音频轨道
AVMutableCompositionTrack *audioTrack = [comosition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
// 获取音频资源中的音频轨道
AVAssetTrack *audioAssetTrack = [[audioAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];
// 加入
[audioTrack insertTimeRange:audioTimeRange ofTrack:audioAssetTrack atTime:CMTimeMakeWithSeconds(model.startTime, self.player.currentTime.timescale) error:nil];
- 音量调节
//调节音量
AVMutableAudioMix *videoAudioMixTools = [AVMutableAudioMix audioMix];
NSMutableArray * params = [[NSMutableArray alloc] initWithCapacity:0];
//音乐轨道
AVMutableAudioMixInputParameters *musicAudioParam = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:audioTrack];
//设置音轨音量,可以设置渐变,设置为1.0就是全音量
[musicAudioParam setVolumeRampFromStartVolume:self.volume toEndVolume:self.volume timeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration)];
[musicAudioParam setTrackID:audioTrack.trackID];
[params addObject:musicAudioParam];
//视频原音轨道
AVMutableAudioMixInputParameters *originalAudioParam = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:originalAudioTrack];
//设置音轨音量,可以设置渐变,设置为1.0就是全音量
[originalAudioParam setVolumeRampFromStartVolume:1-self.volume toEndVolume:1-self.volume timeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)];
[originalAudioParam setTrackID:originalAudioTrack.trackID];
[params addObject:originalAudioParam];
videoAudioMixTools.inputParameters = [NSArray arrayWithArray:params];
- 输出
// 创建一个输出
AVAssetExportSession *assetExport = [[AVAssetExportSession alloc] initWithAsset:comosition presetName:AVAssetExportPresetMediumQuality];
// 输出类型
assetExport.outputFileType = AVFileTypeQuickTimeMovie;
// 输出地址 outputFileUrl为沙盒地址
assetExport.outputURL = outputFileUrl;
// 优化
assetExport.shouldOptimizeForNetworkUse = YES;
//音量
assetExport.audioMix = videoAudioMixTools;
// 合成完毕
[assetExport exportAsynchronouslyWithCompletionHandler:^{
// 回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
//do something
});
}];
这是给视频添加音频,如果是给视频拼接一段视频,也是同理可得了。