用 AVFoundation 导出 HDR 媒体
Export HDR media in your app with AVFoundation
2020年6月24日
一句话判断
这场 Session 是 10009 的姊妹篇,聚焦在”导出”这一个环节——如果你的 App 需要生成 HDR 视频文件,这里讲了从 AVAssetWriter 配置到文件格式选择的所有细节。
这场 Session 讲了什么
与 10009 侧重播放和编辑不同,这场 Session 专门讲解如何将 HDR 内容正确导出为文件。核心围绕 AVAssetWriter 和 AVAssetExportSession 两种导出路径。
对于简单的导出需求,AVAssetExportSession 提供了预设的 HDR 兼容导出配置。但对于需要精细控制的场景(如自定义编码参数、嵌入特定元数据),AVAssetWriter 是更好的选择。Session 详细讲解了如何配置 AVAssetWriterInput 的输出设置字典,包括视频编码器选择(HEVC 是 HDR 的首选编码器)、色彩空间标签、传输函数、以及矩阵系数的设置。
特别值得关注的是 fragmented MPEG-4(fMP4)格式的支持——它允许边写边播放,非常适合流媒体场景。同时,Session 还讨论了如何在导出过程中保留杜比视界的动态元数据。
值得深挖的点
HEVC 编码器是 HDR 导出的核心。 H.264 不支持 HDR 元数据嵌入,HEVC(H.265)是目前唯一支持在容器中携带 HDR 信息的常用编码器。选择正确的 profile(Main 10 或 Main 10 Still Picture)对 HDR 质量至关重要。
导出设置字典中的色彩参数。 视频输出的色彩正确性依赖于三个关键参数:Primary(色彩空间原点,如 BT.2020)、Transfer Function(传输函数,如 PQ 或 HLG)、Matrix Coefficients(矩阵系数)。这三个参数必须与源内容匹配,否则导出的视频会出现色彩偏差。
代码片段
import AVFoundation
// 配置 HDR 视频导出设置
let hdrOutputSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.hevc, // HDR 必须使用 HEVC
AVVideoWidthKey: 1920,
AVVideoHeightKey: 1080,
AVVideoCompressionPropertiesKey: [
AVVideoAverageBitRateKey: 20_000_000, // 20 Mbps,HDR 需要更高的码率
AVVideoProfileLevelKey: kVTProfileLevel_HEVC_Main10_AutoLevel // Main 10 profile
],
// 色彩空间相关设置
AVVideoColorPropertiesKey: [
AVVideoColorPrimariesKey: AVVideoColorPrimaries_ITU_R_2020,
AVVideoTransferFunctionKey: AVVideoTransferFunction_ITU_R_2100_HLG,
AVVideoYCbCrMatrixKey: AVVideoYCbCrMatrix_ITU_R_2020
]
]
// 使用 AVAssetWriter 导出 HDR 视频
let writer = try AVAssetWriter(outputURL: outputURL, fileType: .mov)
let writerInput = AVAssetWriterInput(
mediaType: .video,
outputSettings: hdrOutputSettings
)
writerInput.expectsMediaDataInRealTime = false
writer.add(writerInput)
// 开始写入
writer.startWriting()
writer.startSession(atSourceTime: .zero)
// 在写入循环中追加 HDR 帧数据
// 确保每个 CVPixelBuffer 都有正确的色彩空间附件
// 简单导出:使用 AVAssetExportSession
let exportSession = AVAssetExportSession(
asset: asset,
presetName: AVAssetExportPresetHighestQuality
)!
exportSession.outputFileType = .mov
exportSession.outputURL = outputURL
// ExportSession 会自动检测并保留 HDR 属性
exportSession.exportAsynchronously {
// 处理导出完成
}
最佳实践
- 始终使用 HEVC 编码器导出 HDR 内容。 H.264 不支持 HDR 元数据,强行使用会导致色彩信息丢失。
- 导出前验证源内容的色彩空间。 如果源视频已经是 HDR,确保导出设置与之匹配;如果源是 SDR,不要伪造 HDR 标签。
- 为不同设备准备多个版本。 考虑同时导出 HDR 和 SDR 版本,用 HLS 的自动码率适配让客户端选择。
- 测试导出结果在多种设备上的表现。 不同型号 iPhone 的屏幕亮度范围不同,HDR 在低亮度屏幕上的表现需要实际验证。
还有什么值得关注
- fragmented MPEG-4 格式支持边写边播,适合直播和流媒体点播场景
- HEVC 编码器的 Main 10 Profile 是 HDR 视频的最低要求
- 导出的 MOV 文件可以在 QuickTime Player 中验证 HDR 标签
- 配合 AVAssetExportSession 的 metadata 参数可以保留自定义元数据