不使用 AVMutableVideoComposition 进行渲染
No rendering with AVMutableVideoComposition
我有 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 );
}
标志视频是无声的,只显示我的标志。我手动创建这些视频,所以这里的一切都很完美。然而 "Main Video" 可能以错误的方向结束。为了解决这个问题,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
总是 returns NO
。如果我注释掉上面代码中的最后一行(即设置 videoComposition),那么一切都会像以前一样工作(视频方向错误)。有人知道我做错了什么吗?非常感谢任何想法!
这里的问题是,如果您的徽标视频的时长非零,keyTimeRange
可能不会从零开始。 pVideoCompositionInstruction
将从 keyTimeRange.start
开始,而不是 kCMTimeZero(当 AVMutableComposition 开始时),这违反了 AVVideoCompositionInstructions
的规则
"For the first instruction in the array, timeRange.start must be less than or equal to the earliest time for which playback or other processing will be attempted (typically kCMTimeZero)",根据the docs
为了解决这个问题,将 pVideoComposition.instructions
设置为一个包含三个 AVMutableVideoCompositionInstruction
对象的数组,根据每个 AVAsset 的转换,每个对象都有自己的 AVMutableVideoCompositionLayerInstruction
。三个指令中的每一个的时间范围应该是这些资产出现在合成轨道中的时间。确保它们完全对齐。
我有 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 );
}
标志视频是无声的,只显示我的标志。我手动创建这些视频,所以这里的一切都很完美。然而 "Main Video" 可能以错误的方向结束。为了解决这个问题,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
总是 returns NO
。如果我注释掉上面代码中的最后一行(即设置 videoComposition),那么一切都会像以前一样工作(视频方向错误)。有人知道我做错了什么吗?非常感谢任何想法!
这里的问题是,如果您的徽标视频的时长非零,keyTimeRange
可能不会从零开始。 pVideoCompositionInstruction
将从 keyTimeRange.start
开始,而不是 kCMTimeZero(当 AVMutableComposition 开始时),这违反了 AVVideoCompositionInstructions
"For the first instruction in the array, timeRange.start must be less than or equal to the earliest time for which playback or other processing will be attempted (typically kCMTimeZero)",根据the docs
为了解决这个问题,将 pVideoComposition.instructions
设置为一个包含三个 AVMutableVideoCompositionInstruction
对象的数组,根据每个 AVAsset 的转换,每个对象都有自己的 AVMutableVideoCompositionLayerInstruction
。三个指令中的每一个的时间范围应该是这些资产出现在合成轨道中的时间。确保它们完全对齐。