Ruby 的 16-bit EXR,真把 SDR 里被裁的光找回来了吗?
2026 年 8 月,Runway 上线了一个叫 Ruby 的模型:输入一段 SDR 视频,输出一份按 HDR 包装的成品。宣传口径相当能打:BT.2020 色域、PQ 与 HLG 双传递函数、10/12-bit 的 ProRes/HEVC、16-bit EXR 序列,专业后期该有的格式一个不少。对刚用生成模型出片、想把成片交付成 HDR 的创作者来说,这几乎就是"一键把 SDR 变成真 HDR"。
这篇文章要回答一个问题:这些格式承诺究竟保证了什么,又保证不了什么?结论可以先放在这里:Ruby 真正改变的,是把 SDR 到 HDR 这条数学上走不通的路,包装成了一份可以交付的资产。16-bit EXR 不等于找回真光。被裁掉的光不会因为装它的盒子变大而回来。
1. 位深、BT.2020 都变大了,被裁掉的高光就回来了吗?
先看 Ruby 到底交付了什么。它挂在 POST /v1/video_to_hdr 端点,模型名 ruby,官方说明只有一句话:"Converts SDR video into true HDR, keeping the source pixels and audio." 输入必须是 SDR,API 文档的上限是 40 秒、单边小于 4096 像素(webapp 端约 30 秒,属于另一入口的限制),输出尺寸会被裁成 16 的倍数。这些约束是后面所有讨论的地基。Runway Ruby docs
五种输出格式是重点:
| 输出格式 | 容器与编码 | 位深 | 色域与传递函数 | 附加物 |
|---|---|---|---|---|
hdr10(默认) | HEVC Main 10 (.mp4) | 10-bit | BT.2020 + PQ | HDR10 元数据嵌入 |
hlg | HEVC Main 10 (.mp4) | 10-bit | BT.2020 + HLG | 无 |
hdr_prores | ProRes (.mov),422 / 422 HQ / 4444 | 10/12-bit | BT.2020 + PQ | 无 |
hdr_png_sequence | 16-bit PNG 帧序列 (.zip) | 16-bit | 由 sidecar 说明 | colorimetry sidecar,有音频时附 audio.wav |
hdr_exr_sequence | half-float OpenEXR 帧 (.zip) | 16-bit float | linear BT.2020 light(1.0 = 100 nits) | colorimetry + provenance sidecar,有音频时附 audio.wav |
这张表用词很精确:hdr10 和 hlg 是"10-bit HEVC",hdr_prores 是"BT.2020 + PQ 的 ProRes 中间档(mezzanine)",hdr_exr_sequence 是"linear BT.2020 light (1.0 = 100 nits)"。注意它们描述的全是信号怎么被包装,没有一句描述画面里出现了什么新内容;表里反复出现的 sidecar(伴生元数据文件)是后期语义的关键,第五章会专门讲。还要注意 PNG 的 16-bit 是无符号整数,EXR 的 16-bit 是 IEEE 754 半精度浮点,同样叫 16-bit,含义并不相同。Runway Ruby docs
位深就是最典型的一处。位深(bit depth)规定的是刻度的精细度:8-bit 只有 256 个档,10-bit 有约 1024 个档,16-bit 有 65536 个档,而 OpenEXR 的 half-float 模式编码上限高达 65504。档位越多,从黑到亮之间能塞下的渐变越平滑、量程越大。可"刻度精细"和"画面里有没有这个内容"是两件事。SDR 源里被裁掉的高光,在拍摄或编码那一刻已经变成了纯白一片,源文件里没有留下任何关于它的信息。half-float 的 65504 给的是编码余量,也就是能装多亮的数;被裁高光的恢复量,也就是画面里还有没有那个细节,和位深毫无关系。OpenEXR
这里值得把反直觉的地方直说出来。我们习惯把"位深变高"和"画面变好"绑在一起,但位深只是盒子能装什么的规格。装进去的还是原来那段 SDR 内容,位深从 10 变 16,不会让源里没有的细节凭空出现。
BT.2020 是同一类误会。BT.2020 是色域容器,它只规定三原色和白点,也就是"能表示的颜色范围"。BT.2100 标准没有另起炉灶,直接复用了 BT.2020 的色域作为 UHD/HDR 的系统色域。看这张图:BT.2100-3

图注:CIE 1931 色度图上,外侧虚线是 BT.2020(UHDTV)色域三角形,内侧点线是 BT.709(HDTV)色域三角形,两者共享同一个 D65 白点。BT.2020 在青绿、黄绿、深红方向上明显更宽,但它只规定"能装多少颜色",不规定里面装了什么内容。Rec.2020 vs Rec.709
BT.709 之外被钳掉的越界颜色,不会因为换了个更大的三角形就重新出现。它们和过曝的高光一样,在源里就已经不存在了。把位深、色域、传递函数(把光编码成数字信号的曲线)放在一起看,它们全是"装信号的盒子"的规格;盒子变大了,盒子里被裁掉的内容并不会回来。至于这些内容为什么回不来,是下一章的问题。
2. 为什么补不回来:SDR→HDR 为什么数学上无解?
问题出在反色调映射(inverse tone mapping)上。通俗地说,SDR 是 HDR 场景经过色调映射(tone mapping)压缩后的降级结果,把一张大动态范围的图压进一个小容器;反色调映射就是倒过来,从压缩结果反推原场景。
这在数学上叫不适定问题(ill-posed):多个不同的 HDR 场景,经过压缩、截断、量化之后,可以变成完全相同的 SDR 画面。给你一张 SDR 帧,反方向上有无数个可能的"原场景",没有唯一解。模型能做的只有推断,甚至幻觉。这个问题 2006 年就被立成了正式研究课题:Banterle 等人在 GRAPHITE 2006 提出 inverse tone mapping 这个术语和 expand map 工具,并在自己的系统综述里承认,过曝区域超过画面 30% 时无法重建,因为"没有足够的信息可以利用"。Banterle 2006
二十年后的机器学习也没有绕开这条边界。SIGGRAPH Asia 2017 的 HDRCNN 是最早用深度网络做单帧 LDR→HDR 重建的公开系统之一(与同年 Endo 等人的 DrTMO 同期),看它论文里的对比图:

图注:同一场景的六联对比:输入 LDR、Banterle 扩图、Meylan 线性拉伸、Rempel 高斯扩图、HDRCNN、真值 HDR。前四种启发式方法把过曝天空整体提亮了,但饱和区域没有恢复出结构;HDRCNN 显著更接近真值,论文原话是"更接近"(significantly closer to),不是"等于"。HDRCNN
把论文的原话读一遍:"虽然这些方法能通过提升高光,给人动态范围变大的印象,但检查饱和图像区域时,几乎没有信息真正被重建出来。" HDRCNN 在结论里还承认,网络能处理多少缺失信息有一个内容相关的上限,这个上限很难量化。换句话说,连专门为这个任务训练的深度网络,也没能从源里不存在的像素里变出细节。这是不适定性的视觉铁证。HDRCNN
视频是唯一的补救路,而且只有一条。Ye 等人在 CVPR 2024 把跨帧曝光变化命名为 temporal clues(时序线索):相机拍摄时会缓慢平滑地调整曝光,当前帧过曝成一片的区域,几十帧之后可能恰好正常曝光。这些帧提供了同一场景的真实 HDR 信息,而不是模型从先验里编出来的幻觉。Ye 2024 CVPR

图注:Ye 等人 2024 年的两阶段管道:第一阶段从整段 LDR 序列中采样参考帧与关键帧,用 ICAM 模块提取并对齐跨帧线索、重建关键帧;第二阶段用 FCPM 模块把重建好的关键帧向邻居帧双向传播,生成完整 HDR 序列。橙色参考帧与绿色关键帧构成跨帧线索流。Ye 2024 CVPR
跨帧线索的意义在于"真实":它来自同一场景在不同曝光下的其他帧。但代价同样写在纸面上,跨帧对齐本身就是难题,过曝区域没有纹理,光流很容易算错;做完对齐还要处理闪烁。Ye 的论文直言,把单帧反色调映射方法直接套在视频上会出现时序不一致,也就是闪烁。Ye 2024 CVPR
2026 年的生成式路线把这个结论说得更直白。Tedla 等人在论文里写道:仅凭单张 SDR 图像,恢复是严重不适定的,被裁的高光与被压碎的暗部"必须被合理地幻觉出来"(must be plausibly hallucinated)。Tedla 2026 LumiVid 干脆在训练时主动往 SDR 参考上加压缩、模糊与曝光偏移,逼模型从视觉先验里把被抹掉的高光幻觉出来。LumiVid
所以答案很硬:单帧 SDR→HDR 是不适定的,模型补不回源里已经不存在的信息;视频这条线只能借跨帧曝光找回部分真实线索,其余部分仍是受时序约束的推断。这个结论从 2006 到 2026 没有松动过。Ruby 就生存在这条边界上。
3. Ruby 的「保留源像素」到底承诺了什么?
回到 Ruby 的官方表述:"Converts SDR video into true HDR, keeping the source pixels and audio." 关键词是 keeping the source pixels,保留源像素。官方承诺保留源像素,并列出这些输出语义:位深提升(把 SDR 的数值搬进 10/12-bit 或浮点容器)、传递函数包装(给数值换上 PQ 或 HLG 的语义)、sidecar 注入(给 EXR/PNG 帧序列附上说明色彩语义的伴生文件)。至于内部是否重建细节、如何重建,文档没有公开。Runway Ruby docs
把 Ruby 放进 Runway 的 HDR 链路里,定位会更清楚:
图注:Ruby 是跨模型的 HDR 后处理通道:Gen-4.5 在生成阶段就自带 HDR 调色,直接输出六种 HDR 格式;Aleph 2.0、第三方模型与用户上传的 SDR 素材,则统一汇入 Ruby 的 video_to_hdr 端点完成升格。调色决策发生在生成侧与编辑侧,Ruby 承担的是格式桥梁的职责。Runway Ruby docs
图里其实藏着三条路径。Gen-4.5 是生成侧原生 HDR,模型在生成时就把画面调成 HDR,官方称之为 graded into BT.2020 with measured HDR10 metadata,这是"生成时决策"。Aleph 2.0 官方文档明说不输出原生 HDR,想要 HDR 就得链式调用 Ruby。第三方模型与上传素材,则把 Ruby 当成统一的升格入口。这三条路径合起来说明一件事:Ruby 不是替代 Gen-4.5 的另一个 HDR 生成器,而是跨模型的 HDR 后处理通道。
和 2026 年的学术路线放在一起,这个定位会更锋利。Tedla 等人承认被裁信息"必须被幻觉出来",LumiVid 用主动抹掉训练数据的高光来逼模型从先验幻觉,这是"激进幻觉"的姿态;Ruby 的官方口径是 keeping the source pixels,这是"保守保持"的姿态。但这是两者公开定位的差异,不是被验证的内部机制:生成式论文把幻觉当作方法的一部分写进正文,Ruby 把保留源像素写进一句话产品定位。不能据此反推 Ruby 内部如何重建被裁区域,也不能据此承诺 Ruby 不会生成源里没有的内容。Ruby 的公开口径同样不承诺恢复源里丢失的光。
到这里,Ruby 的定位可以收口了:它把不适定问题的输出,包装成一份剪辑、合成与交付链路能直接接住的资产。它是格式桥梁,不是真值恢复器。下一章看这份资产内部的语义,也就是 PQ 和 HLG 到底在说什么。
4. PQ 和 HLG 差在哪,为什么不能混用?
对调色师和合成师来说,Ruby 输出里最值得读的信息在传递函数里。传递函数是"把光编码成数字"用的曲线。ITU-R BT.2100 定义了两种 HDR 传递函数,PQ 与 HLG,两种语义根本不同。
PQ(感知量化)是 display-referred(以显示器为准的编码)的绝对映射:数值描述的是"显示器最终发出的光"。signal value 1.0 恒对应 10000 cd/m²,和具体接什么显示器无关。看 PQ 的 EOTF 曲线,这条曲线把编码信号还原成显示器发出的亮度:

图注:PQ 的 EOTF 曲线:横轴是非线性信号值 0 到 1,纵轴是显示器发出的亮度 0 到 10000 cd/m²。曲线暗部爬升缓慢、高光处陡峭上扬,signal 1.0 永远落到 10000 cd/m²,这是一个与显示器无关的绝对亮度锚点。PQ EOTF
HLG(混合对数伽马)走的是另一条路:scene-referred(以场景光为准的编码)的相对映射。HLG 编码里 E'=0.5 对应的是场景光 1/12,而不是某个固定的 cd/m²;同一个 HLG 编码在峰值 600 和 1000 cd/m² 的显示器上,实际亮度不同,因为它的 OOTF(光学传递函数)在显示端完成。PQ 则相反,OOTF 被放在相机端、在生产流程中施加,所以它的编码值是绝对的。BT.2100-3
BT.2100 对这两种系统有一句明文规定,值得逐字读:"HDR 电视的生产与显示,应一致使用其中一套传递函数,不得混用。"BT.2100-3 注意这句话管的是同一份素材内部:生产侧与显示侧要自洽,不是说 Ruby 不能同时输出两种格式。Ruby 同时提供 PQ 的 ProRes 和 HLG 的 HEVC,是给下游不同交付链路各取所需:ProRes 进调色与合成,PQ 的绝对锚点方便把数值钉在物理亮度上;HEVC 进流媒体分发,HLG 对 SDR 显示器向后兼容。你拿到的是哪份,就按哪套语义来读。
| 维度 | PQ | HLG |
|---|---|---|
| 参照系 | display-referred,以显示器为准 | scene-referred,以场景光为准 |
| 亮度锚点 | signal 1.0 恒为 10000 cd/m² | E'=0.5 对应 scene-light 1/12 |
| 与显示器的关系 | 无关,绝对 | 相关,峰值不同则亮度不同 |
| OOTF 位置 | 相机端(生产流程中施加) | 显示端 |
| 典型交付 | 后期母版、HDR 电视与流媒体 | 直播、需兼容 SDR 的分发 |
判断一份 HDR 素材该按什么标准看,第一步永远是先确认它走 PQ 还是 HLG。这是验收 Ruby 输出的第一把尺。那么问题来了:Ruby 里信息量最大的那档输出,16-bit EXR,又该按什么语义读?
5. Ruby 的 16-bit EXR 里存的,算不算场景真值?
最后把镜头对准最抓眼球的那档输出:hdr_exr_sequence,half-float OpenEXR 帧序列。OpenEXR 是电影工业最常见的浮点中间格式,后期里它的优势很明确:可表示高于 1.0 的线性值、没有固定的 HDR 显示峰值语义,合成时不用先解 EOTF、改数值、再重新编码。但"能装大数"不是"没有上限",half-float 的数值上限仍是前章所述的 65504,只是相对于 SDR 那 0 到 1 的刻度,余量大到几乎感觉不到边界。而"是浮点"和"存的是场景真值"是两回事,OpenEXR 官方文档自己把边界画得很清楚:

图注:OpenEXR 官方文档的图像处理流程:EXR 文件落在白平衡之后、色调映射之前,处于上方的 scene-linear 区域;JPEG 是做完所有步骤、可直接显示的 display-referred 文件。EXR 与 JPEG 在链路中的位置差异,就是"以场景光为准"与"以显示为准"的位置差异。OpenEXR
设计意图是 scene-referred linear,这一点 OpenEXR 文档开门见山。但紧跟其后的限定语同样关键:"OpenEXR 图像被设计用于存储 scene-referred linear 数据,但库并不强制这一点。"OpenEXR 容器只是意图,EXR 文件自己不说话。所以 Ruby 给这份 EXR 写的标注就格外值得读:文档写的是 half-float OpenEXR frames as linear BT.2020 light (1.0 = 100 nits)。1.0 对应 100 nits,nits 是显示器亮度的单位,这看起来是一个以显示亮度为参照的标度线索,等于在暗示"1.0"被钉在一个具体的显示峰值上。但它只是线索,不是结论:文档这么写,不代表实际文件的头字段里真的写下了 whiteLuminance = 100,也不代表每个帧序列都严格按这个标度生成。所以此刻还不能断言 Ruby 的 EXR 就是 display-referred linear。能说的是:如果 1.0 = 100 nits 在实际文件的头字段与 sidecar 里得到确认,那它就不是 ACES2065-1 那种 scene-linear(后者以场景曝光参考白为尺度,18% 灰卡记作 0.18)。同一个浮点容器,两套坐标系,字节看起来一模一样。
怎么判定一份 EXR 到底属于哪套坐标系?靠头字段和 sidecar,而不是靠文档描述。OpenEXR 头字段里,chromaticities 规定三原色与白点,whiteLuminance 规定 (1,1,1) 对应的 nits 数。OCIO(OpenColorIO)把色彩编码分成七类:scene-linear、display-linear、log、hdr-video、edr-video、sdr-video、data。按这把尺,如果 Ruby 的 EXR 头字段确实写明 whiteLuminance = 100(也就是 1.0 = 100 nits),它才应当标成 display-linear,而不是 scene-linear;如果头字段里查不到这个值,说明标度尚未定义,得回到 sidecar 与 provenance 记录里继续找。无论哪种情况,在标度确认之前直接按 scene-linear 接进 ACES 链路,所有颜色转换都会错位。ACES Metadata File(AMF)正是这套判定的落地工具:它用 inputTransform、lookTransform、outputTransform 的有序列表记录素材经历了哪些变换,随素材归档,业内俗称"色彩食谱"。Input Transform 也必须等元数据明确之后才能指定:确认是 display-linear,就按 display-linear 选择对应的 Input Transform;确认不下来,就把判定挂起,别替文件写答案。OCIO/ACES
ACES 的工作流正好示范了这套判定在真实链路里怎么落地:

图注:ACES 文档给出的「a sample workflow」,一个用 ACES 组件搭建的样本工作流:左侧输入 Camera 与 CGI,中间经过 Dailies Grade、Compositing、DI Grade 等处理节点,右侧输出 ACES Archive with Metadata 与 SDR/HDR 交付物。注意它只是一个样本,色彩语义的真正裁决者,是随素材归档的元数据与 sidecar。ACEScentral
这里还要把 BT.2100 的 Table 10 拉回来兜底:标准明确允许 16-bit 浮点既承载"与场景光成比例的 RGB"(scene-referred),也承载"参考显示器上的绝对显示光"(display-referred)。标准自己就允许两种解释并存。所以一份 EXR 算不算场景真值,永远要靠元数据确认,不能靠格式名字推断,也不能只靠文档里的一句话。
小结一句话:拿到 Ruby 的 16-bit EXR,先打开 sidecar 与头字段核验。"浮点"只说明编码余量,不代表它存的就是场景真值;文档里的 1.0 = 100 nits 同样只是待核验的标度线索。元数据确认之后,才能决定接进 ACES/OCIO 链路时该用哪个 Input Transform;在确认之前把它当场景线性档案直接使用,会翻车。最后的问题就剩一个:这东西到底能不能放心用?
6. 什么时候点 Ruby 就够了,什么时候必须自己调 HDR 母版?
Ruby 是可用的工具,它的边界在哪?AIM 2025 的 Inverse Tone Mapping Challenge 给了最客观的参照。这个挑战让全世界的队伍在统一协议下做单图 SDR→HDR:69 名注册参赛者、319 次有效提交、6 支决赛队伍。冠军 ToneMapper 用 NAFNet 打到 PU21-PSNR 34.49 dB,顶在当时单图 ITM 的学术 SOTA 上。但报告在总结最低分队伍时写了一句耐人寻味的话:29.22 dB 的成绩,"证明了恢复严重饱和或欠曝区域的难度"。AIM 2025
反差值得点破:这还是在受控数据集上的结果。退化链是实验室里合成的,先估计最大合法曝光、注入噪声、再钳制到 [0,1],远比真实世界随手拍的 SDR 视频客气。即便如此,这份报告的整体结果与作者在总结里的提示,都指向同一个判断:严重饱和与欠曝区域的恢复,依然是单图 ITM 没啃下来的难点。学术侧二十年没破解的不适定,到了 Ruby 这里不会自动消失。所以验收 AI HDR 素材,不能只看位深标语。
具体落到动作上,可以照这张决策图走:
低风险分支并不是免检放行,它保留的最低检查是一次快速 QC:抽查几帧关键画面,确认文件能正常读取、位深标签符合预期、曝光标称与 sidecar 一致,通过就直接交付,不通过就升级到逐项核查。高风险分支则要单列对待,四个检查项每一项目标都明确。高光纹理:窗户、灯罩、水面反光这类区域有没有死白或色斑,这是"被裁的光"最直接的残留现场。暗部噪声:被压碎的阴影抬起来之后,噪点有没有跟着一起放大。饱和色:红绿灯、霓虹这类高饱和色有没有色偏。跨帧闪烁:同一区域的亮度在相邻帧之间有没有抖动,这是视频 HDR 区别于单帧 HDR 的专属问题。四个检查项都在校准过的 HDR 监视器上逐一过检,任何一项不过关,就回到 SDR 母版,人工做 HDR 母版。为什么必须保留 SDR 母版和转换参数?因为"看起来更亮"是这类工具的出厂设置,把高光提亮本来就是最容易讨喜的做法,但亮不等于对。验收的唯一标准是语义可追溯、残留在可接受范围、时间上稳定。
回到开篇的问题。Ruby 的 16-bit EXR 真把 SDR 里被裁的光找回来了吗?没有,也不会。被裁掉的光在源里已经不存在,Ruby 做的事情,是把它包装成一份后期链路能接住、能交付的资产。这份资产的价值是真实的:它把生成视频送进了剪辑、合成与交付链路,省掉了一整条手动搭建 HDR 管线的功夫。但"可交付"与"找回真光"是两件事。把 Ruby 当自动 HDR 首版,它是好工具;把它当无需验收的 HDR 母版,你会被最亮的那帧骗到。这个区分,就是这篇文章想让你带走的东西。
参考文献
本专题引用的核心资料如下,建议深入学习时阅读原文:
- Runway Available AI Models — Ruby (SDR to HDR) — https://docs.dev.runwayml.com/guides/models.md
- Recommendation ITU-R BT.2100-3 — Image parameter values for high dynamic range television — https://www.itu.int/rec/R-REC-BT.2100-3-202502-I/en
- OpenEXR — Scene-Linear Image Representation — https://openexr.com/en/latest/SceneLinear.html
- Banterle, Ledda, Debattista, Chalmers — Inverse Tone Mapping (GRAPHITE 2006) + Banterle 2009 PhD thesis — https://researchr.org/publication/BanterleLDC06
- Eilertsen et al. — HDR Image Reconstruction from a Single Exposure Using Deep CNNs (SIGGRAPH Asia 2017) — https://arxiv.org/abs/1710.07480
- Ye, Zhang, Zhao, Cao, Wang — Deep Video Inverse Tone Mapping Based on Temporal Clues (CVPR 2024) — https://openaccess.thecvf.com/content/CVPR2024/papers/Ye_Deep_Video_Inverse_Tone_Mapping_Based_on_Temporal_Clues_CVPR_2024_paper.pdf
- Tedla et al. — Generating HDR Video from SDR Video (arXiv 2605.14703, 2026-05-14) — https://arxiv.org/abs/2605.14703
- Korem et al. — LumiVid: HDR Video Generation via Latent Alignment with Logarithmic Encoding (arXiv 2604.11788, 2026-04-13) — https://arxiv.org/abs/2604.11788
- OpenColorIO + ACES Central — Color Management, Sidecars, and Scene-Linear Workflows — https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/main/docs/guides/authoring/colorspaces.rst
- Wang, Banterle, Ren, Timofte et al. — AIM 2025 Challenge on Inverse Tone Mapping Report (ECCV AIM workshop 2025) — https://arxiv.org/abs/2508.13479