Highlight
Apple 在 AVFoundation 的 AVVideoComposition 中加入 HDR 编辑支持:内建 compositor 和内建 Core Image filter 可以处理 HDR,自定义 compositor 需要声明 10-bit 像素格式、HDR source frames 和 Wide Color source frames。
核心内容
视频编辑 App 以前把主要精力放在剪切、拼接、变换和混合上。进入 HDR 之后,问题变得更细:像素可能超过 SDR 的 0 到 1 范围,常见分发格式会使用 10-bit,传输函数可能是 HLG 或 PQ。一个已有的转场、滤镜或自定义合成器,如果仍按 SDR 假设处理颜色,就可能把高亮压掉,或把滤镜结果算成负值。
这场 session 把风险收敛到一个核心对象:AVVideoComposition。AVComposition 主要描述时间线上的素材对齐,基本不关心 HDR;AVVideoComposition 负责几何变换、混合和滤镜处理,必须知道输入和输出的颜色特性。Apple 的更新让两条常见路径变得简单:使用内建 compositor,或用 AVMutableVideoComposition(asset:applyingCIFiltersWithHandler:) 调用内建 Core Image filter 时,框架会替你处理 HDR 帧。
真正需要开发者改代码的地方是自定义逻辑。自定义 Metal Core Image kernel 要接受扩展动态范围,不能假设最大亮度就是 1。自定义 compositor 还要告诉 AVFoundation:它支持 10-bit 或更高位深的 pixel buffer,愿意接收 HDR source frames,并且能处理 Wide Color。播放端再用 AVPlayer.eligibleForHDRPlayback 判断当前硬件和显示器是否适合 HDR 预览。
详细内容
1. 内建 compositor 的 HDR 路径(06:43)
常见剪辑工作流会先创建 AVComposition 和 AVVideoComposition,再把它们交给 AVPlayerItem 预览,或交给 AVAssetExportSession 导出。session 明确说,HDR 的关键在 AVVideoComposition,因为它负责混合和变换。
let videoComposition = AVMutableVideoComposition()
videoComposition.instructions = [videoCompositionInstruction]
videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
videoComposition.renderSize = assetSize
关键点:
instructions描述每段时间线里如何混合或变换视频层;多条 instruction 不能重叠,也不能留下时间空洞。frameDuration决定合成输出帧率,示例用 1/30 秒。renderSize决定输出画面尺寸。- 这段代码没有设置
customVideoCompositorClass,AVFoundation 会使用内建 compositor;transcript 中说明,已有 App 在这种路径上输入 HDR video,通常可以得到按同一组 instruction 合成后的 HDR 输出。
2. 用 Core Image filter 创建 AVVideoComposition(09:55)
第二条路径适合单视频层滤镜。AVMutableVideoComposition 会把第一条 enabled video track 的当前帧传给 handler,开发者拿到 request.sourceImage 后送进 CIFilter,最后调用 request.finish 返回结果。
let videoComposition =
AVMutableVideoComposition(asset: asset,
applyingCIFiltersWithHandler: {
(request: AVAsynchronousCIImageFilteringRequest) -> Void in
let ciFilter = CIFilter(name: "CIZoomBlur")
ciFilter!.setValue(request.sourceImage, forKey: kCIInputImageKey)
request.finish(with: ciFilter!.outputImage!, context: nil)
})
关键点:
applyingCIFiltersWithHandler省掉了手写 composition instruction 的工作,把焦点放到每帧滤镜处理上。request.sourceImage是当前输入帧,对应 transcript 中的CIImage。CIZoomBlur是 Core Image 内建 filter;session 说明 Core Image 的内建 filter 能处理 HDR source。request.finish(with:context:)把滤镜输出交回 AVFoundation,后续仍由 video composition 管线处理。
3. 自定义 Core Image kernel 要接受扩展动态范围(10:57)
如果 handler 调用的是自定义 Metal Core Image kernel,代码就要理解 HDR 帧的像素范围。session 给了一个高亮检查 kernel:只要任一 RGB 通道超过 1,就把该像素涂成超亮红色。
#include <metal_stdlib>
#include <CoreImage/CoreImage.h>
using namespace metal;
extern "C" float4 HDRHighlight(coreimage::sample_t s, coreimage::destination dest) {
if (s.r > 1.0 || s.g > 1.0 || s.b > 1.0)
return float4(2.0, 0.0, 0.0, 1.0);
else
return s;
}
关键点:
CoreImage/CoreImage.h引入 Metal Core Image kernel 需要的类型。coreimage::sample_t s是输入像素;HDR 内容里s.r、s.g、s.b可能大于 1。float4(2.0, 0.0, 0.0, 1.0)故意输出超过 SDR 白点的红色,用来标记 HDR 高亮区域。- session 随后用 color inverter 举反例:如果继续按 SDR 写
1.0 - s.r,HDR 像素大于 1 时结果会变成负值。
4. 自定义 compositor 必须声明 HDR 能力(13:58)
自定义 compositor 的自由度最高,可以混合多个视频层,对每一层做几何变换和滤镜处理。代价是框架不会自动假定它能处理 HDR。开发者要同时处理真实合成逻辑和能力声明。
class SampleCustomCompositor: NSObject, AVVideoCompositing {
var sourcePixelBufferAttributes: [String : Any]? =
[kCVPixelBufferPixelFormatTypeKey as String:
[kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange]]
var requiredPixelBufferAttributesForRenderContext: [String : Any] =
[kCVPixelBufferPixelFormatTypeKey as String:
[kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange]]
var supportsHDRSourceFrames = true
var supportsWideColorSourceFrames = true
func startRequest(_ request: AVAsynchronousVideoCompositionRequest) {
...
}
func renderContextChanged(_ newRenderContext: AVVideoCompositionRenderContext) {
}
}
关键点:
sourcePixelBufferAttributes告诉框架 compositor 支持哪些输入 pixel buffer 格式。requiredPixelBufferAttributesForRenderContext告诉框架输出 render context 需要哪些格式。kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange是示例中的 10-bit pixel format;实际项目要填自己真正支持的格式。supportsHDRSourceFrames = true是新字段。没有设置,或设置成false,框架会在交给 compositor 前把 HDR source 转成 SDR。supportsWideColorSourceFrames = true对应 HDR 常伴随 Wide Color 的事实;transcript 说明,框架会假设能处理 HDR 的 compositor 也能处理 Wide Color。
5. 颜色属性和播放资格检查(17:49、21:01)
不指定 composition color properties 时,框架会按 HLG、PQ、SDR 的优先级选择输出格式。需要固定输出到 HLG、PQ 或 SDR 时,要显式设置 colorPrimaries、colorTransferFunction 和 colorYCbCrMatrix。播放预览还要检查当前系统是否能显示 HDR。
extension AVPlayer {
@available(macOS 10.15, *)
open class var eligibleForHDRPlayback: Bool { get }
}
if AVPlayer.eligibleForHDRPlayback {
videoComposition.colorPrimaries = AVVideoColorPrimaries_ITU_R_2020
videoComposition.colorTransferFunction = AVVideoTransferFunction_ITU_R_2100_HLG
videoComposition.colorYCbCrMatrix = AVVideoYCbCrMatrix_ITU_R_2020
}
else {
videoComposition.colorPrimaries = AVVideoColorPrimaries_ITU_R_709_2
videoComposition.colorTransferFunction = AVVideoTransferFunction_ITU_R_709_2
videoComposition.colorYCbCrMatrix = AVVideoYCbCrMatrix_ITU_R_709_2
}
关键点:
AVPlayer.eligibleForHDRPlayback是 class var,不需要创建AVPlayer实例就能查询。- 返回
true表示系统能消费 HDR video,并且至少有一个内建或外接显示器能显示 HDR。 - HLG 示例使用
ITU_R_2020color primaries、ITU_R_2100_HLGtransfer function 和ITU_R_2020YCbCr matrix。 - 不具备 HDR 播放能力时,示例把 composition color properties 设为 SDR,避免为无法显示的 HDR 预览花处理资源。
- transcript 额外提醒:这个属性只描述播放能力。不能播放 HDR 的系统,仍可能可以走 HDR export path。
核心启发
- HDR 剪辑预览器:做一个 macOS 视频剪辑预览窗口。为什么值得做:内建 compositor 可沿用现有
AVVideoCompositioninstruction 处理 HDR。怎么开始:先保持现有AVMutableVideoComposition结构不变,检查是否显式把 color properties 固定到了 SDR。 - HDR 高光检查滤镜:做一个把超过 SDR 白点区域标红的诊断 filter。为什么值得做:session 的
HDRHighlightkernel 直接用s.r > 1.0等条件识别 HDR 高亮。怎么开始:把 kernel 放进 Metal Core Image 文件,再用applyingCIFiltersWithHandler接入预览。 - 自定义 compositor HDR 升级:给多图层转场或画中画编辑器补上 HDR 能力。为什么值得做:自定义 compositor 可以同时做多层混合、几何变换和每层滤镜。怎么开始:先支持 10-bit pixel buffer,再设置
supportsHDRSourceFrames和supportsWideColorSourceFrames。 - HDR/SDR 自动预览切换:根据设备能力给用户显示 HDR 或 SDR 预览。为什么值得做:
eligibleForHDRPlayback同时检查系统消费 HDR 的能力和显示器条件。怎么开始:播放路径读取该 class var,true 时设置 HLG color properties,false 时设置 ITU_R_709_2。 - 分享用 SDR 副本:在剪辑 App 中提供“导出给普通显示设备”的选项。为什么值得做:transcript 明确给出邮件分享场景,接收方可能没有 HDR 播放系统。怎么开始:在该导出或预览路径上把 video composition 的三项 color properties 设置为 SDR。
关联 Session
- Export HDR media in your app with AVFoundation — 继续讲 HDR 内容导出,覆盖
AVAssetExportSession、AVAssetWriter、支持格式和平台限制。 - Optimize the Core Image pipeline for your video app — 解释视频滤镜中的
CIContext、Metal 队列和AVMutableVideoComposition性能实践。 - Build Metal-based Core Image kernels with Xcode — 深入
.ci.metal文件、kernel 加载和 Core Image 自定义滤镜集成。 - Decode ProRes with AVFoundation and VideoToolbox — 补充 macOS 上 AVFoundation 视频解码、VideoToolbox 和 Metal 显示管线。
评论
GitHub Issues · utterances