iOS开发–AVFoundation视频合成(添加背景音乐)

前言

图片[1]-iOS开发–AVFoundation视频合成(添加背景音乐)-一一网
当下音视频处理的技术的重要性不言而喻, FFmpeg的强大不可撼动, 但是, 确实难啃. 由简递难, 我们来看看苹果原生的API如何做到对视频素材进行处理的.

AVFoundation既可以对视频进行播放, 同时也可以对视频素材进行处理, 此类合成共分为两章:

1、简单视频合成
2、视频与音频的合成

正文

知识点

1.AVMutableComposition 合成工具

2.AVMutableCompositionTrack 合成工具中的轨道

3.AVAsset 视频素材的载体

4.AVAssetTrack 素材轨道

6.AVAssetExportSession 输出工具

过程简述

过程简单而言, 就是将素材中的素材轨道, 按照自定义顺序或者形式, 放到合成工具的对应的轨道, 最后, 设定好参数, 通过输出工具将合成工具中的内容一键合成并且输出.

##代码
下面是核心代码

// 这里将video的内容倒叙操作,为了后面将视频  逐个插入0的位置
videoPaths = [[videoPaths reverseObjectEnumerator] allObjects];
// 合成工具
AVMutableComposition *composition = [AVMutableComposition composition];

// 创建获取素材参数, 这个可以直接为nil, 下方的参数含义是获取素材参数的时间为非精准, 默认为精准
NSDictionary *optDict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                    forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
// 合成工具的视频轨道
__block AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
// 合成工具的音频轨道
__block AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

// 遍历视频资源
[videoPaths enumerateObjectsUsingBlock:^(NSURL *videoPath, NSUInteger idx, BOOL * _Nonnull stop) {
    // 素材
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoPath options:optDict];
    // 获取素材中的轨道_视频
    NSArray<AVAssetTrack *> *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    if (videoTracks <= 0) {
        *stop = YES;
        completedBlock(NO, @"合成失败");
        return;
    }
    // 获取当前视频的时间长度
    CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
    // 素材的视频轨道
    AVAssetTrack *videoCompositionTrack = videoTracks.firstObject;
    // 设置合成工具的preferredTransform
    [compositionVideoTrack setPreferredTransform:videoCompositionTrack.preferredTransform];
    // 将素材的视频轨道添加到合成工具的视频轨道
    [compositionVideoTrack insertTimeRange:timeRange
                                   ofTrack:videoTracks.firstObject
                                    atTime:kCMTimeZero
                                     error:nil];

    // 下面是处理原视频中的音频, 静音的话, 可以不处理
    NSArray *audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
    if (audioTracks.count > 0) {
        // 将素材的音频轨道添加到合成工具的音频轨道
        [compositionAudioTrack insertTimeRange:timeRange
                                       ofTrack:audioTracks.firstObject
                                        atTime:kCMTimeZero
                                         error:nil];
    }
}];

// 存在旧数据, 删除旧数据
if ([[NSFileManager defaultManager] fileExistsAtPath:compoundVideoPath]) {
    NSError *error;
    [[NSFileManager defaultManager] removeItemAtPath:compoundVideoPath error:&error];
}

NSURL *outUrl = [NSURL fileURLWithPath:compoundVideoPath];
// 输出工具
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
// 输出类型
exporter.outputFileType = AVFileTypeMPEG4;
// 输出路径
exporter.outputURL = outUrl;
// 优化
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
    BOOL isSuccess = NO;
    NSString *msg = @"合并完成";
    switch (exporter.status) {
        case AVAssetExportSessionStatusFailed:
            NSLog(@"MediaManager -> combinationVidesError: %@", exporter.error.localizedDescription);
            NSLog(@"%@", exporter.error);
            msg = @"合并失败";
            break;
        case AVAssetExportSessionStatusUnknown:
        case AVAssetExportSessionStatusCancelled:
            break;
        case AVAssetExportSessionStatusWaiting:
            break;
        case AVAssetExportSessionStatusExporting:
            break;
        case AVAssetExportSessionStatusCompleted:
            isSuccess = YES;
            break;
    }
    if (completedBlock) {
        completedBlock(isSuccess, msg);
    }
}];
复制代码

添加背景音乐

添加背景音乐, 其实就是再添加一条音轨.

// 背景音乐 合成轨道
AVMutableCompositionTrack *compositionBGMAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

// 背景音乐
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:audioPath options:optDict];
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, allTime);
NSArray *bgmTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
[compositionBGMAudioTrack insertTimeRange:timeRange
                                  ofTrack:bgmTracks.firstObject
                                   atTime:kCMTimeZero
                                    error:nil];
复制代码

**作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发公众号:编程大鑫,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享