iOS 视频中片段反复播放特效实现

思路

使用AVMutableComposition组合拼接出想要的分段组合方式,
反复播放通常要处理三个分段,1.重复之前的直接播放段 2.反复段 3.反复段之后的直接播放段.

逻辑比较简单 直接上代码

- (void)videoSectionReplay {
    //测试数据
    CMTimeRange replayTimeRange = CMTimeRangeMake(CMTimeMakeWithSeconds(3, 600), CMTimeMakeWithSeconds(3, 600));
    NSUInteger replayCount = 3;
    
    //测试资源
    NSString *filePath4 = [[NSBundle mainBundle] pathForResource:@"timeMerge" ofType:@"MP4"];
    AVAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:filePath4] options:@{}];
    AVAssetTrack *videoTrack = asset.videoTrack;
    AVAssetTrack *audioTrack = asset.audioTrack;
    
    //要重复的时间段 在视频轨道中就没有 无法继续处理直接返回
    if (!CMTimeRangeContainsTimeRange(videoTrack.timeRange, replayTimeRange)) {
        return;
    }
    
    //组合对象
    AVMutableComposition *mutableComposition = [AVMutableComposition composition];
    AVMutableCompositionTrack *videoCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *audioCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    CMTime videoInsertOffset = kCMTimeZero;
    CMTime audioInsertOffset = kCMTimeZero;
    
    //如果有正常播放的前段 插入正常播放的前段
    if (CMTIME_COMPARE_INLINE(replayTimeRange.start, !=, kCMTimeZero)) {
        CMTime duration = CMTimeSubtract(replayTimeRange.start, videoTrack.timeRange.start);
        CMTimeRange prePassThroughTimeRange = CMTimeRangeMake(videoTrack.timeRange.start, duration);
        
        [videoCompositionTrack insertTimeRange:prePassThroughTimeRange ofTrack:videoTrack atTime:videoInsertOffset error:nil];
        [audioCompositionTrack insertTimeRange:prePassThroughTimeRange ofTrack:audioTrack atTime:audioInsertOffset error:nil];
        
        videoInsertOffset = videoCompositionTrack.timeRange.duration;
        audioInsertOffset = audioCompositionTrack.timeRange.duration;
    }
    
    //插入反复播放的片段
    for (NSUInteger i=0; i<replayCount; i++) {
        [videoCompositionTrack insertTimeRange:replayTimeRange ofTrack:videoTrack atTime:videoInsertOffset error:nil];
        [audioCompositionTrack insertTimeRange:replayTimeRange ofTrack:audioTrack atTime:audioInsertOffset error:nil];
        
        videoInsertOffset = videoCompositionTrack.timeRange.duration;
        audioInsertOffset = audioCompositionTrack.timeRange.duration;
    }
    
    //如果后面还有需要直接播放的片段 插入后面的直接播放的段
    CMTime replayEndTime = CMTimeAdd(replayTimeRange.start, replayTimeRange.duration);
    if (CMTIME_COMPARE_INLINE(videoTrack.timeRange.duration, >, replayEndTime)) {
        CMTime duration = CMTimeSubtract(videoTrack.timeRange.duration, replayEndTime);
        CMTimeRange backTimeRange = CMTimeRangeMake(replayEndTime, duration);
        
        [videoCompositionTrack insertTimeRange:backTimeRange ofTrack:videoTrack atTime:videoInsertOffset error:nil];
        [audioCompositionTrack insertTimeRange:backTimeRange ofTrack:audioTrack atTime:audioInsertOffset error:nil];
        
        videoInsertOffset = videoCompositionTrack.timeRange.duration;
        audioInsertOffset = audioCompositionTrack.timeRange.duration;
    }
    
    combineResultTestViewController *vc = [[combineResultTestViewController alloc] initWithAsset:mutableComposition];
    [self.navigationController pushViewController:vc animated:YES];
}

还用到了一个简单的扩展

@implementation AVAsset (AHSVAsset)

- (AVAssetTrack *)videoTrack {
    AVAssetTrack *videoTrack = [self tracksWithMediaType:AVMediaTypeVideo].firstObject;
    return videoTrack;
}

- (AVAssetTrack *)audioTrack {
    AVAssetTrack *audioTrack = [self tracksWithMediaType:AVMediaTypeAudio].firstObject;
    return audioTrack;
}
@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容