媒体创作和编辑基本是 AVFoundation 的高级接口,较少涉及底层接口。整个过程总的来说就是构建 AVAsset 的过程,而在视频编辑中,构建的是 AVMutableComposition 的过程。
整体关系
Composition :作为内容主体,一个抽象的可编辑的 AVAsset 子类,提供面向对象的多轨操作。
CompositionTrack ×N:管理时间,总的音视频轨信息。
AssetTrack 片段 ×N
轨道的偏好信息:naturalTimeScale
、preferredTransform
、preferredVolume
AudioMix :附加信息,对音量的描述
inputParameters
:AudioMixInputParameters ×N:描述音量(+ 时间 = 渐变)、变速时的音调策略
AudioMixInputParameters 的 audioTapProcessor
可以使用 AudioUnit 给音频增加效果,但似乎查不到具体的额 API 文档,可参考:MTAudioProcessingTap with kMTAudio… | Apple Developer Forums 、gchilds/MTAudioProcessingTap-in-Swift: Example of creating an MTAudioProcessingTap in Swift4.2 。
VideoComposition :附加信息,对画面的描述
视频属性控制:
frameDuration
renderSize
colorParimaties
colorTransferFunction
colorYCbCrMatrix
视频操作,通过以下三种方式:
instructions
:AVVideoCompositionInstructionProtocol ×N
animationTool
:提供与 Core Animation 的几种交互方式,不能实时预览的,即设置到 playerItem 看不到效果。
新增一个用 CALayer 表示的视频轨:init(additionalLayer: CALayer, asTrackID: CMPersistentTrackID)
用 CALayer 层级关系管理视频轨:init(postProcessingAsVideoLayer: CALayer, in: CALayer)
、init(postProcessingAsVideoLayers: [CALayer], in: CALayer)
customVideoCompositorClass
:自己实现一个 VideoComposition,可通过 GL、Metal 实现自定义的转场
以上 API 的 Mutable 版本的类才是可编辑的。
以上的 Composition,可用于创建 PlayerItem、AssetExportSession。AudioMix、VideoComposition 作为属性设置到 AssetExportSession、AssetReaderAudioMixOutput、playerItem。
具体 API
AVMutableComposition
AVAsset 的子类,因此这是最后预览、导出操作的数据对象。
整体操作
对整个 composition 对象进行整体操作,当然这会涉及多个轨道,除了对整体进行时间伸缩,否则较少使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 /// 插入空占位 func insertEmptyTimeRange(_ timeRange: CMTimeRange) /// 插入asset func insertTimeRange(_ timeRange: CMTimeRange, of asset: AVAsset, at startTime: CMTime) throws /// 移除时间段的内容,注意这里不会移除既有的轨道。 func removeTimeRange(_ timeRange: CMTimeRange) /// 伸缩时间,即改变时间区间内所有轨道的时长 func scaleTimeRange(_ timeRange: CMTimeRange, toDuration duration: CMTime) /// 配置视频画幅尺寸 var naturalSize: CGSize { get set }
轨道操作
大多数操作都是基于轨道。
1 2 3 4 5 /// 添加、移除轨道 func addMutableTrack(withMediaType mediaType: AVMediaType, preferredTrackID: CMPersistentTrackID) -> AVMutableCompositionTrack? func removeTrack(_ track: AVCompositionTrack) // 其他API只是获取轨道等非常用操作
AVMutableCompositionTrack
一个可修改的轨道。
常用配置属性
1 2 3 4 5 6 7 8 9 10 /// 视频翻转矩阵 var preferredTransform: CGAffineTransform { get set } /// 音频轨道音量 var preferredVolume: Float { get set } /// 其他不太常用的属性 var languageCode: String? { get set } var extendedLanguageTag: String? { get set } var naturalTimeScale: CMTimeScale { get set }
增删改查
1 2 3 4 5 6 func insertEmptyTimeRange(_ timeRange: CMTimeRange) func insertTimeRange(_ timeRange: CMTimeRange, of track: AVAssetTrack, at startTime: CMTime) throws func insertTimeRanges(_ timeRanges: [NSValue], of tracks: [AVAssetTrack], at startTime: CMTime) throws // 似乎不常用 func removeTimeRange(_ timeRange: CMTimeRange) func scaleTimeRange(_ timeRange: CMTimeRange, toDuration duration: CMTime) var segments: [AVCompositionTrackSegment]! { get set }
AVMutableAudioMix
包含混音(目前的混音只有音量调节)参数,所以其对象只有一个属性:
1 var inputParameters: [AVAudioMixInputParameters] { get set }
音频混音参数。
1 2 3 4 5 6 7 8 9 10 11 /// 创建 convenience init(track: AVAssetTrack?) /// 创建后也可以修改trackId更变应用的轨道 var trackID: CMPersistentTrackID { get set } /// 设置音量 func setVolume(_ volume: Float, at time: CMTime) func setVolumeRamp(fromStartVolume startVolume: Float, toEndVolume endVolume: Float, timeRange: CMTimeRange) /// 设置音调算法 var audioTimePitchAlgorithm: AVAudioTimePitchAlgorithm? { get set }
AVMutableVideoComposition
控制视频轨道组合行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /// 创建 init(propertiesOf asset: AVAsset) /// 配置视频相关属性 var frameDuration: CMTime { get set } var renderSize: CGSize { get set } var renderScale: Float { get set } // 不常用 var colorPrimaries: String? { get set } var colorTransferFunction: String? { get set } var colorYCbCrMatrix: String? { get set } /// 配置视频操作 var instructions: [AVVideoCompositionInstructionProtocol] { get set } var animationTool: AVVideoCompositionCoreAnimationTool? { get set } var customVideoCompositorClass: AVVideoCompositing.Type? { get set }
AVMutableVideoCompositionInstruction
提供一个时间范围内的视频组织信息。由一组 AVMutableVideoCompositionLayerInstruction 对象格式定义的指令组成的。
1 2 3 4 5 /// 自顶而下排列的layerInstructions var layerInstructions: [AVVideoCompositionLayerInstruction] { get set } var timeRange: CMTimeRange { get set } var enablePostProcessing: Bool { get set } var backgroundColor: CGColor? { get set }
AVMutableVideoCompositionLayerInstruction
给视频特效,用于定义给定视频轨道应用的基于时间的模糊、变形、和裁剪效果。从其构建方式可见,其更类似于 AVMutableAudioMixInputParameters。
1 2 3 4 5 6 7 8 9 10 11 /// 构建 convenience init(assetTrack track: AVAssetTrack) var trackID: CMPersistentTrackID { get set } /// 支持的操作 func setOpacity(_ opacity: Float, at time: CMTime) func setOpacityRamp(fromStartOpacity startOpacity: Float, toEndOpacity endOpacity: Float, timeRange: CMTimeRange) func setTransform(_ transform: CGAffineTransform, at time: CMTime) func setTransformRamp(fromStart startTransform: CGAffineTransform, toEnd endTransform: CGAffineTransform, timeRange: CMTimeRange) func setCropRectangle(_ cropRectangle: CGRect, at time: CMTime) func setCropRectangleRamp(fromStartCropRectangle startCropRectangle: CGRect, toEndCropRectangle endCropRectangle: CGRect, timeRange: CMTimeRange)
LayerInstruction 是应用于一个轨道的,意味着要想在应用特效的时候能看到底下的视频,则需要多个视频轨道。
VideoComposition+CoreAnimation
视频编辑中除了可以叠加轨道,还可以叠加 CALayer。这通过 VideoComposition 的 animationTool 实现。其类是 AVVideoCompositionCoreAnimationTool:
1 2 3 4 5 6 7 8 /// 添加额外的图层 convenience init(additionalLayer layer: CALayer, asTrackID trackID: CMPersistentTrackID) /// 自定义组织视频层与根图层。这里animationLayer是根图层,videoLayer视频层是其子图层,除此以外还可以在animationLayer添加更多子图层。 convenience init(postProcessingAsVideoLayer videoLayer: CALayer, in animationLayer: CALayer) /// 拷贝视频帧到多个视频层 convenience init(postProcessingAsVideoLayers videoLayers: [CALayer], in animationLayer: CALayer)
在视频中使用 CoreAnimation,常需要设置 geometryFlipped 属性,让其坐标翻转一遍。
通过 AVVideoCompositionCoreAnimationTool 使用 Core Animation 时需要注意:
用 AVCoreAnimationBeginTimeAtZero
表示 0 时间点;
isRemovedOnCompletion
设为 false;
避免使用与 UIView 关联的 CALayer。
AVAssetExportSession
高级导出类,是个高级 API,要想更细化地配置,还是需要 AVAssetReader+AVAssetWriter。
构建
1 init?(asset: AVAsset, presetName: String)
当然可以直接构建后就开始导出。其音视频的转码配置都囊括在 presetName 中,即既有的方案中去直接套用。
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 /// 输出文件路径 var outputURL: URL? { get set } /// 文件类型,准确地来说是容器类型 var outputFileType: AVFileType? { get set } /// 文件长度限制 var fileLengthLimit: Int64 { get set } /// 导出时间区间 var timeRange: CMTimeRange { get set } /// 附带的元数据 var metadata: [AVMetadataItem]? { get set } /// 混音 var audioMix: AVAudioMix? { get set } /// 音调算法(在伸缩时长时) var audioTimePitchAlgorithm: AVAudioTimePitchAlgorithm { get set } /// 是否为网络播放优化 var shouldOptimizeForNetworkUse: Bool { get set } /// video composition var videoComposition: AVVideoComposition? { get set } /// custom video compositor var customVideoCompositor: AVVideoCompositing? { get }
未找到相关的 Issues 进行评论
请联系 @bqlin 初始化创建