Export HDR media in your app with AVFoundation
Audio & Video 进阶 24m

用 AVFoundation 导出 HDR 媒体

Export HDR media in your app with AVFoundation

2020年6月24日

在 Apple 官方观看视频

一句话判断

这场 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 参数可以保留自定义元数据
WWDC 2020