直播JC专题Ios开发学习

AVFoundation详细解析(一)视频合并与混音

2016-06-29  本文已影响2650人  落影loyinglin

回顾

在上一篇GPUImage详细解析(八)视频合并混音介绍了如何使用GPUImage进行视频的合并,以及混音。这次使用AVFoundation框架来实现这个功能。

概念

效果

视频效果如下,音频效果可运行demo

核心思路

分别加载多个AVURLAsset,用GCD保证异步加载完成后回调,调用Editor类配置轨道信息、视频操作指令和音频指令参数。


具体细节

流程图如下


a、配置轨道信息

思考1:demo中是如何计算小于一半,为何要小于一半?

思考2:当多个视频在同一个音轨插入多个信息,如何保证不重叠?

    // 确保最后合并后的视频,变换长度不会超过最小长度的一半
    CMTime transitionDuration = self.transitionDuration;
    for (i = 0; i < clipsCount; i++ ) {
        NSValue *clipTimeRange = [self.clipTimeRanges objectAtIndex:i];
        if (clipTimeRange) {
            CMTime halfClipDuration = [clipTimeRange CMTimeRangeValue].duration;
            halfClipDuration.timescale *= 2;
            transitionDuration = CMTimeMinimum(transitionDuration, halfClipDuration);
        }
    }
    AVMutableCompositionTrack *compositionVideoTracks[2];
    AVMutableCompositionTrack *compositionAudioTracks[2];
    compositionVideoTracks[0] = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; // 添加视频轨道0
    compositionVideoTracks[1] = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; // 添加视频轨道1
    compositionAudioTracks[0] = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; // 添加音频轨道0
    compositionAudioTracks[1] = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; // 添加音频轨道1

b、配置视频操作指令

        AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; // 新建指令
        passThroughInstruction.timeRange = passThroughTimeRanges[i]; // 直接播放
        AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[alternatingIndex]]; // 视频轨道操作指令
        
        passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer];
        [instructions addObject:passThroughInstruction]; // 添加到指令集合
        
        if (i+1 < clipsCount) { // 不是最后一个
            AVMutableVideoCompositionInstruction *transitionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; // 新建指令
            transitionInstruction.timeRange = transitionTimeRanges[i]; // 变换时间
            AVMutableVideoCompositionLayerInstruction *fromLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[alternatingIndex]]; // 视频轨道操作指令
            AVMutableVideoCompositionLayerInstruction *toLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[1-alternatingIndex]]; // 新的轨道指令
            // 1 dao 0
            [fromLayer setOpacityRampFromStartOpacity:1.0 toEndOpacity:0.0 timeRange:transitionTimeRanges[i]];
            // 目的轨道,从0到1
            [toLayer setOpacityRampFromStartOpacity:0.0 toEndOpacity:1.0 timeRange:transitionTimeRanges[i]];
            
            transitionInstruction.layerInstructions = [NSArray arrayWithObjects:toLayer, fromLayer, nil];
            [instructions addObject:transitionInstruction];
        }

c、配置音频轨道参数

AVMutableAudioMixInputParameters *trackMix1 = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:compositionAudioTracks[alternatingIndex]]; // 音轨0的参数
[trackMix1 setVolumeRampFromStartVolume:1.0 toEndVolume:0.0 timeRange:transitionTimeRanges[i]]; // 音轨0,变换期间音量从1.0到0.0
[trackMixArray addObject:trackMix1];
AVMutableAudioMixInputParameters *trackMix2 = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:compositionAudioTracks[1 - alternatingIndex]]; // 音轨1的参数
[trackMix2 setVolumeRampFromStartVolume:0.0 toEndVolume:1.0 timeRange:transitionTimeRanges[i]]; // 变换期间音量从0.0到1.0           
[trackMixArray addObject:trackMix2];

总结

AVPlayer通过KVO监听rate属性,status属性,用notification来监听播放完成;
AVPlayer和AVPlayerItem的使用不复杂,解析集中在SimpleEditor类如何配置轨道信息和音视频操作指令。
代码地址可以点这里

思考

思考1

通过timescale*2,再用CMTimeMinimum;处于中间的视频要经历两次变换,故而变换的长度不能大于最小视频长度的一半;

思考2

音轨插入的函数有开始点和持续时间,只要保证区间不重叠,音频就不会重叠;

上一篇 下一篇

猜你喜欢

热点阅读