(1)视频编辑的目录说明
前段时间需要做一个视频剪辑的模块,当时对视频编辑方面了解的不多,在实现上走了很多弯路,遇到了不少的问题,现在总结一下分享给有需要的。视频编辑实现了大部分市面上同类型软件的功能,考虑了部分兼容扩展性,因为功能相对来说比较简单,结构上面难免存在不足,写出来给大家提供参考。
本专栏的视频编辑技术是基于AVFoundation来打造,滤镜部分会用到GPUImage、LUT滤镜等。大概会从下面几个部分来分享
- 视频编辑基础概述
- 框架设计
- 基础编辑(每个基础编辑功能的实现)
- 添加字幕、水印、动画
- 滤镜转场、画中画实现
- 音频混合以及视频导出
下图是编辑主界面的截图
(2)视频编辑基础概述
使用AVFoundation做视频编辑,我们从基础的开始说起,涉及到视频编辑的各个功能模块的单独实现和组合,视频编辑框架的设计。
1、视频编辑必要的基础知识
1.1、AVFoundation介绍
AVFoundation是iOS开发者可以用来播放和创建基于时间的视听媒体的几个框架之一,其提供了检查、创建、编辑或重新编码媒体文件的接口,也使得从设备获取的视频实时数据可操纵。下图是AVFoundation在iOS上的体系结构
1.2 AVFoundation类
视频编辑的对象视频资源(AVAsset),包含多条资源轨道(AVAssetTrack),包括视频轨道,音频轨道,字幕等。编辑就是对这些轨道上的资源做处理。
在用AVFoundation做视频编辑的时候,会用到一个可变的资源组合(AVMutableComposition),它是视频资源的描述,组合工具,基类是AVAsset,可以用来编辑、播放、导出。视频编辑过程中的AVMutableComposition就像下图这样,包含多条轨道,每条轨道的视频又可以来自不同的资源。
AVAsset(资源容器)
AVAsset
是一个抽象类和不可变类,定义了媒体资源混合呈现的方式.可以让我们开发者在处理时基媒体提供了一种简单统一的方式,它并不是媒体资源,但是它可以作为时基媒体的容器.
从相册和本地导入视频、音频资源的时候一般会用到他的子类AVURLAsset
,在初始化AVURLAsset
之后,其实系统并没有同步加载数据,所以在调用之前需要先加载,或者在初始化AVURLAsset
的时候带上。
从URL初始化的时候可以这样写:
NSDictionary *options = @{AVURLAssetPreferPreciseDurationAndTimingKey:@YES};
self.asset = [AVURLAsset URLAssetWithURL:url options:options];
从相册获取的:
[self.asset loadValuesAsynchronouslyForKeys:@[@"tracks", @"duration", @"commonMetadata"] completionHandler:^{
}]
这样我们的资源就加载好了,后续可以直接使用duration等属性了。
在AVAsset
中重要的就是资源轨道,可以获取到视频,音频等轨道
//Provides the array of AVAssetTracks contained by the asset
@property (nonatomic, readonly) NSArray<AVAssetTrack *> *tracks;
AVAssetTrack(资源轨道)
AVAssetTrack
是资源轨道,后续都称为资源轨道。可能是视频、音频或者字幕等轨道。可以从AVAsset
中获取到资源的各个轨道。
//Provides an array of AVAssetTracks of the asset that present media of the specified media type
- (NSArray<AVAssetTrack *> *)tracksWithMediaType:(AVMediaType)mediaType;
需要注意的是在获取资源轨道的时候需要保证资源的track已经加载好。
资源轨道的的类型有:
AVF_EXPORT AVMediaType const AVMediaTypeVideo
AVF_EXPORT AVMediaType const AVMediaTypeAudio
AVF_EXPORT AVMediaType const AVMediaTypeText
AVF_EXPORT AVMediaType const AVMediaTypeClosedCaption
AVF_EXPORT AVMediaType const AVMediaTypeSubtitle
AVF_EXPORT AVMediaType const AVMediaTypeTimecode
AVF_EXPORT AVMediaType const AVMediaTypeMetadata
AVF_EXPORT AVMediaType const AVMediaTypeMuxed
通常我们需要获取的有AVMediaTypeVideo、AVMediaTypeAudio这两种资源轨道,在一个视频资源中,一般会有一条视频轨道,一条音频轨道,也有可能有多条,主要看视频。大多数从相册获取的视频资源的各类型轨道都是只有一条的。
理解了媒体资源和资源轨道之后,我们开始了解视频编辑组合相关的内容:
AVMutableComposition(资源组合)
下图是AVMutableComposition的继承关系图,可以发现AVMutableComposition继承自AVAsset。其实它也是表示的视频资源,不过我们可以通过它做视频的组合,添加音频轨道、添加转场等,是视频编辑中最重要的类。
资源轨道的类继承图如下:
AVMutableComposition 是一个或多个轨道(AVCompositionTrack)的集合,每个轨道会根据时间线存储源媒体的文件信息,比如音频、视频等。
//AVMutableComposition 创建一个新AVCompositionTrack的API
- (nullable AVMutableCompositionTrack *)addMutableTrackWithMediaType:(AVMediaType)mediaType preferredTrackID:(CMPersistentTrackID)preferredTrackID;
每个轨道由一系列轨道段(track segments)组成,每个轨道段存储源文件的一部分媒体数据,比如 URL、轨道 ID(track identifier)、时间映射(time mapping)等。
我们可以添加个多个AVMutableCompositionTrack,需要指定媒体类型和trackID。
AVMutableComposition合成新视频的流程 如下图
AVMutableAudioMix(音频混合)
使用AVMutableAudioMix类,你可以在合成中的音轨上执行自定义音频处理
AVMutableAudioMix 可以通过 AVMutableAudioMixInputParameters 指定任意轨道的任意时间段音量。
AVMutableVideoComposition
我们还可以使用 AVMutableVideoComposition 来直接处理 composition 中的视频轨道。处理一个单独的 video composition 时,你可以指定它的渲染尺寸、缩放比例、帧率等参数并输出最终的视频文件。通过一些针对 video composition 的指令(AVMutableVideoCompositionInstruction 等),我们可以修改视频的背景颜色、应用 layer instructions。
这些 layer instructions(AVMutableVideoCompositionLayerInstruction 等)可以用来对 composition 中的视频轨道实施图形变换、添加图形渐变、透明度变换、增加透明度渐变。此外,你还能通过设置 video composition 的 animationTool 属性来应用 Core Animation Framework 框架中的动画效果。
AVVideoCompositing(帧处理)
我们可以使用AVVideoCompositing来处理针对视频每一帧做处理,包括添加滤镜、转场等功能,也可以结合GPUImage来做滤镜转场,opengl等来处理每一帧的图片。自由度非常高,我们将在滤镜转场文章中详细介绍
AVAssetExportSession(导出)
导出的步骤比较简单,只需要把上面几步创建的处理对象赋值给导出类对象就可以导出最终的产品。
2、一些基础知识
CMTime
typedef struct
{
CMTimeValue value;
CMTimeScale timescale;
CMTimeFlags flags;
CMTimeEpoch epoch;
} CMTime
CMTime定义是一个C语言的结构体,CMTime是以分数的形式表示时间,value表示分子,timescale表示分母,value/timescale = seconds,flags是位掩码,表示时间的指定状态。在创建时间的时候timescale我们一般选择600。
CMTimeRange
typedef struct
{
CMTime start;
CMTime duration;
} CMTimeRange
其中start表示时间的起点,duratin表示时间范围的持续时间。
AVAssetImageGenerator
我们可以使用AVAssetImageGenerator来获取视频的缩略图,我们只需要传入指定的时间即可获取到此时间的缩略图。
_imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:self.asset];
_imageGenerator.maximumSize = CGSizeMake(120, 120); //最大缩略图的大小
[self.imageGenerator generateCGImagesAsynchronouslyForTimes:timeArray
completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *_Nullable error) {
UIImage *videoImage = [UIImage imageWithCGImage:image];
}]
我们可以传入指定时间的数组来批量获取缩略图。
需要注意的是,传入的时间获取到的缩略图不一定是准确的,可能会有误差,如果要获取准确的时间点的缩略图,需要设置下面两个属性的值为:kCMTimeZero @property (nonatomic) CMTime requestedTimeToleranceBefore; @property (nonatomic) CMTime requestedTimeToleranceAfter
资料推荐
如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群1012951431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。