视频处理相关(二) —— 基于AVFoundation的视频拼接处理(一)

版本记录

版本号 时间
V1.0 2019.11.27 星期三

前言

App中很多时候都需要进行视频处理,包括各种滤镜以及编解码等处理,好的视频处理不仅可以提高App的性能,也会给用户带来耳目一新的感觉,这里重新开了一个专题,专门讲述对视频的各种处理。感兴趣的可以看下面几篇文章。
1. 视频处理相关(一) —— 视频深度相关处理简单示例(一)

开始

首先看一下主要内容

基于库AVFoundation进行短视频的拼接处理和保存。

昨天一个同学私信我,问我下关于短视频拼接的问题,正好在项目闲暇时间写了这个demo,完成了视频的拼接处理以及保存到手机相册。

首先要准备的是视频素材,分别是各为4s的短视频。

video1
video2

下面就把这两个视频拼接到一起,直接看代码。

#import "ViewController.h"
@import AVFoundation;
@import AssetsLibrary;

@interface ViewController ()

@property (nonatomic, strong) AVAssetExportSession *exportSession;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //第一个资源
    NSURL *oneURL = [[NSBundle mainBundle] URLForResource:@"video_one" withExtension:@"mp4"];
    AVAsset *oneAsset = [AVAsset assetWithURL:oneURL];

    //第二个资源
    NSURL *twoURL = [[NSBundle mainBundle] URLForResource:@"video_two" withExtension:@"mp4"];
    AVAsset *twoAsset = [AVAsset assetWithURL:twoURL];

    // //创建轨道容器
    AVMutableComposition *composition = [AVMutableComposition composition];
    AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

    //使用AVAssetTrack对象从对应的AVAsset媒体容器中,抽取对应的视频文件和音频文件
    AVAssetTrack *assetTrackVideo = [oneAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
    AVAssetTrack *assetTrackAudio = [oneAsset tracksWithMediaType:AVMediaTypeAudio].firstObject;
    
    CMTime totalDuration = kCMTimeZero;

    //开始拼接第一个视频
    [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, oneAsset.duration) ofTrack:assetTrackVideo atTime:totalDuration error:nil];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, oneAsset.duration) ofTrack:assetTrackAudio atTime:totalDuration error:nil];
    totalDuration = CMTimeAdd(totalDuration, oneAsset.duration);
    
        
    assetTrackVideo = [twoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
    assetTrackAudio = [twoAsset tracksWithMediaType:AVMediaTypeAudio].firstObject;

    //开始拼接第二个视频
    [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, twoAsset.duration) ofTrack:assetTrackVideo atTime:totalDuration error:nil];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, twoAsset.duration) ofTrack:assetTrackAudio atTime:totalDuration error:nil];
    totalDuration = CMTimeAdd(totalDuration, twoAsset.duration);

    //使用AVAssetExportSession对象将将剪辑好的媒体文件导出,再保存到系统相册
    AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:[composition copy] presetName:AVAssetExportPresetHighestQuality];
    self.exportSession = exportSession;
    exportSession.outputURL = [self sandBoxAddress];
    exportSession.outputFileType = AVFileTypeMPEG4;
    __weak typeof(self) weakSelf = self;
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            AVAssetExportSessionStatus status = weakSelf.exportSession.status;
            if (status == AVAssetExportSessionStatusCompleted) {
                [weakSelf savePhoto];
            }
            else{
                UIAlertView *alerView = [[UIAlertView alloc]initWithTitle:@"出现错误" message:@"saveSynthetic方法" delegate:weakSelf cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
                [alerView show];
            }
        });
    }];
    
}

//获取沙盒路径存储到沙河中
- (NSURL *)sandBoxAddress
{
    NSString *filePath = nil;
    NSUInteger count = 0;
    do {
        filePath = NSTemporaryDirectory();
        NSString *numberString = count > 0 ? [NSString stringWithFormat:@"-%li",(unsigned long)count] : @" ";
        NSString *fileNameString = [NSString stringWithFormat:@"DaoKeLegend-%@.mov",numberString];
        filePath = [filePath stringByAppendingPathComponent:fileNameString];
        count++;
    }
    while ([[NSFileManager defaultManager] fileExistsAtPath:filePath]);
    return [NSURL fileURLWithPath:filePath];
}

//将合成写入照片库中
- (void)savePhoto
{
    NSURL *url = self.exportSession.outputURL;
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:url]) {
        [library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error) {
            if (error) {
                UIAlertView *alerView = [[UIAlertView alloc]initWithTitle:@"出现错误" message:@"保存到系统相册失败" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
                [alerView show];
            }
            else {
                [[NSFileManager defaultManager] removeItemAtURL:url error:nil];
                UIAlertView *alerView = [[UIAlertView alloc]initWithTitle:@"OK" message:@"已经保存到系统相册" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
                [alerView show];
            }
        }];
    }
    else {
        NSLog(@"保存失败");
    }
}

@end

下面我们看一下相册

那个8s的视频就是拼接以后的视频。

具体效果如下

这样就可以拼接到一起了。

后记

本篇主要讲述了基于AVFoundation的视频拼接处理,感兴趣的给个赞或者关注~~~

视频处理相关(二) —— 基于AVFoundation的视频拼接处理(一)_第1张图片

你可能感兴趣的:(视频处理相关(二) —— 基于AVFoundation的视频拼接处理(一))