AVMutableComposition - 连接的视频资产在第一个资产后停止

AVMutableComposition - concatenated video assets stops after first asset

我正在使用以下代码连接多个 AVURLAssets:

AVMutableComposition * movie = [AVMutableComposition composition];

CMTime offset = kCMTimeZero;

for (AVURLAsset * asset in assets) {
    AVMutableCompositionTrack *compositionVideoTrack = [movie addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *compositionAudioTrack = [movie addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

    AVAssetTrack *assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
    AVAssetTrack *assetAudioTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;

    CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
    NSError * error = nil;

    if (![compositionVideoTrack insertTimeRange: timeRange ofTrack: assetVideoTrack atTime: offset error: &error]) {
        NSLog(@"Error adding video track - %@", error);
    }
    if (![compositionAudioTrack insertTimeRange: timeRange ofTrack: assetAudioTrack atTime: offset error: &error]) {
        NSLog(@"Error adding audio track - %@", error);
    }

    offset = CMTimeAdd(offset, asset.duration);
}

生成的合成一直播放到所有原始资产的组合持续时间,音频播放正确,但只有第一个资产的视频播放,然后在其最后一帧暂停。

对我做错了什么有什么想法吗?

原始资产的顺序无关紧要 - 第一个视频和所有音频播放。

您需要使用 AVVideoCompositionInstructions 的实例创建一个 AVVideoComposition。看看这个 sample code.

您可能感兴趣的代码具有以下性质:

AVMutableVideoCompositionLayerInstruction *videoCompositionLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:mutableVideoTrack];
[self.layerInstructions addObject:videoCompositionLayerInstruction];
        AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
        passThroughInstruction.timeRange = trackTimeRange;
        passThroughInstruction.layerInstructions = @[videoCompositionLayerInstruction];
[self.compositionInstructions addObject:passThroughInstruction];

好吧,那是我的错误。我会把 addMutableTrackWithMediaType: 放在 里面 for 循环。傻我。固定如下,效果很好!

我会把它留在这里以防其他人遇到同样的问题。

AVMutableComposition * movie = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [movie addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *compositionAudioTrack = [movie addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

CMTime offset = kCMTimeZero;

for (AVURLAsset * asset in assets) {

    AVAssetTrack *assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
    AVAssetTrack *assetAudioTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;

    CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
    NSError * error = nil;

    if (![compositionVideoTrack insertTimeRange: timeRange ofTrack: assetVideoTrack atTime: offset error: &error]) {
        NSLog(@"Error adding video track - %@", error);
    }
    if (![compositionAudioTrack insertTimeRange: timeRange ofTrack: assetAudioTrack atTime: offset error: &error]) {
        NSLog(@"Error adding audio track - %@", error);
    }

    offset = CMTimeAdd(offset, asset.duration);
}