AVFoundation – AVComposition AVMutableComposition 将多个媒体合并

AVComposition AVMutableComposition 将多个媒体合并

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 基础

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 线程

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> OpenGL ES

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> GPUImage

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> AVFoundation

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> CocoaPods


一.前言

1.AVAsset

Assets 可以来自一个文件或用户的相册,可以理解为多媒体资源,通过 URL 作为一个 asset 对象的标识. 这个 URL 可以是本地文件路径或网络流;


2.AVAssetTrack

AVAsset 包含很多轨道 AVAssetTrack 的结合,如 audio, video, text, closed captions, subtitles…


3.AVComposition / AVMutableComposition

使用 AVMutableComposition 类可以增删 AVAsset 来将单个或者多个 AVAsset 集合到一起,用来合成新视频。除此之外,若想将集合到一起的视听资源以自定义的方式进行播放,需要使用 AVMutableAudioMix 和 AVMutableVideoComposition 类对其中的资源进行协调管理;


4.AVMutableVideoComposition

AVFoundation 类 API 中最核心的类是 AVVideoComposition / AVMutableVideoComposition 。

AVVideoComposition / AVMutableVideoComposition 对两个或多个视频轨道组合在一起的方法给出了一个总体描述。它由一组时间范围和描述组合行为的介绍内容组成。这些信息出现在组合资源内的任意时间点。

AVVideoComposition / AVMutableVideoComposition 管理所有视频轨道,可以决定最终视频的尺寸,裁剪需要在这里进行;


5.AVMutableCompositionTrack

多个 AVAsset 集合到一起合成新视频中轨道信息,有音频轨、视频轨等,里面可以插入各种对应的素材(画中画,水印等);


6.AVMutableVideoCompositionLayerInstruction

AVMutableVideoCompositionLayerInstruction 主要用于对视频轨道中的一个视频处理缩放、模糊、裁剪、旋转等;


7.AVMutableVideoCompositionInstruction

表示一个指令,决定一个 timeRange 内每个轨道的状态,每一个指令包含多个 AVMutableVideoCompositionLayerInstruction ;而 AVVideoComposition 由多个 AVVideoCompositionInstruction 构成;

AVVideoCompositionInstruction 所提供的最关键的一段数据是组合对象时间轴内的时间范围信息。这一时间范围是在某一组合形式出现时的时间范围。要执行的组全特质是通过其 AVMutableVideoCompositionLayerInstruction 集合定义的。


8.AVAssetExportSession

AVAssetExportSession 主要用于导出视频;


二.开篇

AVFoundation 框架中提供了丰富的接口用于视听资源的编辑,其中的关键是 composition ,它将不同的 AVAsset 相结合并形成一个新的 AVAsset 。

使用 AVMutableComposition 类可以增删 AVAsset 来将单个或者多个 AVAsset 集合到一起。除此之外,若想将集合到一起的视听资源以自定义的方式进行播放,需要使用 AVMutableAudioMix 和 AVMutableVideoComposition 类对其中的资源进行协调管理。

如果需要保存文件的话,要使用 AVAssetExportSession 类将编辑的内容保存到文件中。


三.AVComposition 简介

AVComposition 继承自 AVAsset,可以将多个视频媒体数据组合在一起显示,或处理来自多个源媒体数据;

同 AVAsset 拥有多个 AVAssetTrack 一样,作为子类的 AVComposition 也拥有多个 AVCompositionTrack ,而 AVCompositionTrack 是 AVAssetTrack 的子类。所以,AVComposition 实例对象是多个 track 的集合,真正描述媒体属性的是 AVCompositionTrack 实例对象。而 AVCompositionTrack 又是媒体数据片段的集合,这些数据片段由 AVCompositionTrackSegment 类进行描述。


AVComposition 相关属性和方法如下:

//获取 composition 中包含的 tracks
@property (nonatomic, readonly) NSArray<AVCompositionTrack *> *tracks;

//获取 composition 中可视媒体资源播放时在屏幕上显示的大小
@property (nonatomic, readonly) CGSize naturalSize;

//获取 composition 生成 asset 时的指定配置
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> *URLAssetInitializationOptions NS_AVAILABLE(10_11, 9_0);

//根据不同的参数,获取 composition 中的 track
- (nullable AVCompositionTrack *)trackWithTrackID:(CMPersistentTrackID)trackID;

- (NSArray<AVCompositionTrack *> *)tracksWithMediaType:(NSString *)mediaType;

- (NSArray<AVCompositionTrack *> *)tracksWithMediaCharacteristic:(NSString *)mediaCharacteristic;


四.AVMutableComposition 简介

AVVideoComposition 继承自 NSObject,表示不可变视频合成的对象,AVMutableComposition 是 AVComposition 的子类, 可以使用它创建新视频,它将不同的 AVAsset 相结合并形成一个新的 AVAsset 。

值得注意的是 AVComposition 类中并没有提供初始化方法,一般我们使用它的子类 AVMutableComposition ,进行各种操作后,再生成 AVComposition 实例以供查询,如下:

AVMutableComposition *mutableComposition = [AVMutableComposition composition];

//进行添加资源等操作
//1.添加媒体1的视频轨道
//2.添加媒体1的音频轨道
//3.添加媒体2的视频轨道
//4.添加媒体2的音频轨道
//.....


//使用可变的 composition 生成一个不可变的 composition 以供使用
AVComposition *composition = [myMutableComposition copy];
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:composition];

由于AVComposition 继承自 AVAsset,而 AVPlayerItem 需要 AVAsset 作为数据源 ,所以可以通过该方法完美解决上一篇文章《AVQueuePlayer 播放多个媒体文件》中播放多个媒体头疼的问题;

使用 AVQueuePlayer 和 AVPlayer 播放多个视频时,是很容易出现性能问题的,切换视频时会存在卡顿现象,尤其在视频内容比较多的时候,无法完美衔接,中间会有一个短暂的停留,这个不太符合我们的需求;


五.AVComposition/AVMutableComposition 函数简介


1.AVMutableComposition 中提供了两个类方法用来获取一个空的 AVMutableComposition 实例对象

+ (instancetype)composition;
+ (instancetype)compositionWithURLAssetInitializationOptions:(nullable NSDictionary<NSString *, id> *)URLAssetInitializationOptions NS_AVAILABLE(10_11, 9_0);


2.AVMutableComposition 获取 track 或向其中添加/移除 track 方法

//向 composition 中添加一个空的 track ,并且指定媒体资源类型及 trackID 属性值
//若提供的参数 preferredTrackID 无效或为 kCMPersistentTrackID_Invalid ,那么唯一的 trackID 会自动生成
- (AVMutableCompositionTrack *)addMutableTrackWithMediaType:(NSString *)mediaType preferredTrackID:(CMPersistentTrackID)preferredTrackID;

//从 composition 中删除一个指定的 track
- (void)removeTrack:(AVCompositionTrack *)track;

//获取一个与 asset track 相兼容的 composition track 
//为了更好的性能,composition track 的数量应保持最小,这个数量与必需并行播放的媒体数据段数量以及媒体数据的类型相关
//对于能够线性执行且类型相同的媒体数据应使用同一个 composition track ,即使这些数据来自不同的 asset
- (nullable AVMutableCompositionTrack *)mutableTrackCompatibleWithTrack:(AVAssetTrack *)track;


3.AVMutableComposition 中也提供了过滤 AVMutableCompositionTrack 的接口

- (nullable AVMutableCompositionTrack *)trackWithTrackID:(CMPersistentTrackID)trackID;
- (NSArray<AVMutableCompositionTrack *> *)tracksWithMediaType:(NSString *)mediaType;
- (NSArray<AVMutableCompositionTrack *> *)tracksWithMediaCharacteristic:(NSString *)mediaCharacteristic;


4.修改 AVMutableComposition track 时间

//将指定时间段的 asset 中的所有的 tracks 添加到 composition 中 startTime 处
//该方法可能会在 composition 中添加新的 track 以便 asset 中 timeRange 范围中的所有 tracks 都添加到 composition 中
- (BOOL)insertTimeRange:(CMTimeRange)timeRange ofAsset:(AVAsset *)asset atTime:(CMTime)startTime error:(NSError * _Nullable * _Nullable)outError;

//向 composition 中的所有 tracks 添加空的时间范围
- (void)insertEmptyTimeRange:(CMTimeRange)timeRange;

//从 composition 的所有 tracks 中删除一段时间,该操作不会删除 track ,而是会删除与该时间段相交的 track segment
- (void)removeTimeRange:(CMTimeRange)timeRange;

//改变 composition 中的所有的 tracks 的指定时间范围的时长,该操作会改变 asset 的播放速度
- (void)scaleTimeRange:(CMTimeRange)timeRange toDuration:(CMTime)duration;


5.AVMutableComposition 配置视频大小

//AVAsset视频部分的尺寸大小;如果未设置此值,则默认行为由AVAsset定义;将值设置为CGSizeZero以还原为默认行为。
@property(nonatomic) CGSize naturalSize;

六.AVComposition/AVMutableComposition 使用

使用 AVComposition / AVMutableComposition 将两个视频合并为一个视频并导出,简单流程如下:

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:AVComposition  AVMutableComposition 将多个媒体合并
//@Time:2021/08/06 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/ 

//加载媒体
AVURLAsset *firstVideoAsset = [AVURLAsset URLAssetWithURL:firstVideoUrl options:nil];
AVURLAsset *secondVideoAsset = [AVURLAsset URLAssetWithURL:secondVideoUrl options:nil];
AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:audioUrl options:nil];

//获取视频资源中的第一个 asset track
AVAssetTrack *firstVideoAssetTrack = [[firstVideoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack *secondVideoAssetTrack = [[secondVideoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack *audioAssetTrack = [[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

//第一个视频插入的时间点是 kCMTimeZero
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, firstVideoAssetTrack.timeRange.duration) ofTrack:firstVideoAssetTrack atTime:kCMTimeZero error:nil];

//第二个视频插入的时间点是第一个视频结束的时间
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, secondVideoAssetTrack.timeRange.duration) ofTrack:secondVideoAssetTrack atTime:firstVideoAssetTrack.timeRange.duration error:nil];

//音频的持续时间是两个视频时间的总和
CMTime videoTotalDuration = CMTimeAdd(firstVideoAssetTrack.timeRange.duration, secondVideoAssetTrack.timeRange.duration);
[audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoTotalDuration) ofTrack: atTime:kCMTimeZero error:nil];

//导出
....

完整代码请跳转:

  • 《AVComposition / AVMutableComposition 合并视频并导出》
  • 《AVComposition / AVMutableComposition 合并视频并播放》

七.猜你喜欢


推荐文章

发表评论