无法使用AVMutableVideoComposition进行渲染

时间:2015-03-04 10:31:27

标签: ios objective-c video avplayer avvideocomposition

我有3个视频,我使用AVMutableComposition进行排序,然后使用AVPlayer播放视频,并使用AVPlayerItemVdeoOutput抓取帧。视频序列如下:

[Logo Video - n seconds][Main video - m seconds][Logo Video - l seconds]

代码如下所示:

    // Build the composition.
    pComposition            = [AVMutableComposition composition];

    // Fill in the assets that make up the composition
    AVMutableCompositionTrack* pCompositionVideoTrack   = [pComposition addMutableTrackWithMediaType: AVMediaTypeVideo preferredTrackID: 1];
    AVMutableCompositionTrack* pCompositionAudioTrack   = [pComposition addMutableTrackWithMediaType: AVMediaTypeAudio preferredTrackID: 2];

    CMTime          time            = kCMTimeZero;
    CMTimeRange     keyTimeRange    = kCMTimeRangeZero;
    for( AVAsset* pAssetsAsset in pAssets )
    {
        AVAssetTrack*   pAssetsAssetVideoTrack  = [pAssetsAsset tracksWithMediaType: AVMediaTypeVideo].firstObject;
        AVAssetTrack*   pAssetsAssetAudioTrack  = [pAssetsAsset tracksWithMediaType: AVMediaTypeAudio].firstObject;

        CMTimeRange     timeRange               = CMTimeRangeMake( kCMTimeZero, pAssetsAsset.duration );

        NSError*        pVideoError             = nil;
        NSError*        pAudioError             = nil;

        if ( pAssetsAssetVideoTrack )
        {
            [pCompositionVideoTrack insertTimeRange: timeRange ofTrack: pAssetsAssetVideoTrack atTime: time error: &pVideoError];
        }
        if ( pAssetsAssetAudioTrack )
        {
            [pCompositionAudioTrack insertTimeRange: timeRange ofTrack: pAssetsAssetAudioTrack atTime: time error: &pAudioError];
        }

        if ( pAssetsAsset == pKeyAsset )
        {
            keyTimeRange    = CMTimeRangeMake( time, timeRange.duration );
        }

        NSLog( @"%@", [pVideoError description] );
        NSLog( @"%@", [pAudioError description] );

        time        = CMTimeAdd( time, pAssetsAsset.duration );
    }

徽标视频是静音的,只显示我的徽标。我手动创建这些视频,所以一切都很完美。然而,“主要视频”可能以错误的方向结束。为了解决这个问题,AVMutableVideoComposition看起来是完美的前进方式。所以我设置了一个简单的视频合成,它执行一个简单的setTransform,如下所示:

pAsset = pComposition;         pPlayerItem = [AVPlayerItem playerItemWithAsset:pAsset];         pPlayer = [AVPlayer playerWithPlayerItem:pPlayerItem];

    NSArray*        pPlayerTracks   = [pAsset tracksWithMediaType: AVMediaTypeVideo];
    AVAssetTrack*   pPlayerTrack    = pPlayerTracks[0];

    pVideoCompositionLayerInstruction               = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstruction];
    [pVideoCompositionLayerInstruction setTransform: [[pKeyAsset tracksWithMediaType: AVMediaTypeVideo].firstObject preferredTransform] atTime: kCMTimeZero];

    pVideoCompositionInstruction                    = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    pVideoCompositionInstruction.backgroundColor    = [[UIColor blackColor] CGColor];
    pVideoCompositionInstruction.timeRange          = keyTimeRange;
    pVideoCompositionInstruction.layerInstructions  = @[ pVideoCompositionLayerInstruction ];

    pVideoComposition                               = [AVMutableVideoComposition videoComposition];
    pVideoComposition.renderSize                    = [[pKeyAsset tracksWithMediaType: AVMediaTypeVideo].firstObject naturalSize];
    pVideoComposition.frameDuration                 = [[pKeyAsset tracksWithMediaType: AVMediaTypeVideo].firstObject minFrameDuration];
    pVideoComposition.instructions                  = @[ pVideoCompositionInstruction ];

    pPlayerItem.videoComposition    = pVideoComposition;

然而,当我来播放视频序列时,我没有返回任何输出。 AVPlayerItemVideoOutput hasNewPixelBufferForItemTime始终返回NO。如果我注释掉上面代码中的最后一行(即设置videoComposition),那么一切都像以前一样工作(视频方向错误)。有人知道我做错了什么吗?任何想法都非常感激!

1 个答案:

答案 0 :(得分:2)

此处的问题是,如果您的徽标视频的持续时间非零,则keyTimeRange可能无法在零时间开始。 pVideoCompositionInstruction将从keyTimeRange.start开始,而不是kCMTimeZero(当AVMutableComposition将启动时),这违反了AVVideoCompositionInstructions的规则

"对于数组中的第一条指令,timeRange.start必须小于或等于将尝试播放或其他处理的最早时间(通常为kCMTimeZero)",根据{{ 3}}

要解决此问题,请将pVideoComposition.instructions设置为包含三个AVMutableVideoCompositionInstruction个对象的数组,每个对象根据每个AVAsset的变换都有自己的AVMutableVideoCompositionLayerInstruction。三条指令中每条指令的时间范围应该是这些资产在合成轨道中出现的时间。确保它们完全对齐。