本文主要讲一类自托管媒体库(以 Octans 播放子系统为例)的转码支持矩阵读法:它回答什么、不回答什么,DirectPlay / DirectStream / Transcode 如何分层,以及客户端能力、媒体事实与服务端策略如何共同决定播放路线。重点是决策机制,而不是把整张能力表抄进文章。

支持矩阵一长,很容易被当成「某个 codec 能不能播」的是非题。实际播放规划通常要同时回答三件事:客户端能不能直接吃源片服务端能不能在不改视频的情况下转封装交付重新编码时输入 / 输出 / 色彩 / 画质各自走到哪条链路。下面按「先分清概念,再读矩阵轴」的顺序整理。

矩阵到底在回答什么

在 Octans 一类架构里,「转码支持矩阵」不是 GPU 厂商白皮书的镜像,也不是浏览器 canPlayType() 的全集。它描述的是当前业务 runtime 已接线、可生成命令、真实样片可播、失败可归因的路线集合。

读矩阵前先对齐四条口径:

口径含义
软件处理走 FFmpeg 软件解码 / 滤镜 / 编码,不依赖特定硬件加速入口
硬件路线(如 VAAPI)只代表已接入并验证的那条加速路径,不等于「机器上装了驱动就一定可用」
编码输出仅统计进入 Transcode + Hls 后的重新编码输出;视频 copy 不算编码支持
当前支持必须同时满足 Planner 可进入、HLS 命令可生成、样片可播、失败可解释

因此矩阵回答的是:

这台服务端 + 当前 FFmpeg runtime + 当前 Planner / 命令构造
  → 对某类输入(codec / 动态范围 / 音轨)
  → 能否走到某类输出(H.264 / HEVC / VP9 HLS,软件或硬件)

单独回答:

  • 某张显卡理论上是否支持该 profile(那是硬件能力研究的问题);
  • 某个客户端是否声明支持某种源格式(那是客户端能力模型的问题);
  • 用户主观观感是否「最好」(那是画质档位与 tone mapping 算法调参的问题)。

一句话:矩阵是业务接入真相表,不是芯片规格表,也不是客户端兼容性百科。

先分清:播放方式 ≠ 交付方式

支持矩阵经常和「最终怎么播」混在一起。先把两层拆开。

概念问的是什么常见取值
播放方式(PlayMethod)服务端是否改变媒体内容DirectPlay / DirectStream / Transcode / Unsupported
交付方式(Delivery)客户端如何拿到流HttpFile / Hls(以及未来可能的其它交付)

两者正交。同一条 HLS 既可承载 DirectStream(视频 copy),也可承载 Transcode(视频 re-encode)。Web 主链里常见组合是:

DirectPlay   + HttpFile   → 原始文件受控 Range 下发,不启 FFmpeg
DirectStream + Hls        → 视频 copy,必要时音频转码 / 转封装
Transcode    + Hls        → 视频(或完整主轨)重新编码后输出 HLS

排查「为什么没走 DirectPlay」时,矩阵只是后半段依据;前半段还要看客户端能力、选轨、字幕路线和策略偏好是否允许 HttpFile 直放。

DirectPlay / DirectStream / Transcode:读法上的分界

Planner 通常按从轻到重的顺序评估:

DirectPlay → DirectStream → Transcode → Unsupported

DirectPlay

服务端不改变媒体内容,只做受控 I/O(权限、鉴权、Range、进度)。适合:容器、视频编码、音频编码与色彩安全边界都落在客户端源格式能力内,且不需要强制 HLS。

读矩阵时:DirectPlay 几乎不看「编码输出」列。它看的是「源能不能原样交给客户端」,不是「服务端能不能把源转成某种 HLS 输出」。

DirectStream

主视频 copy,只做容器转封装、必要音频转码,或通过 HLS 交付但不重编视频。典型场景:

  • 视频编码客户端可解,但容器不兼容浏览器直放;
  • 视频可 copy,但选中音轨不兼容,需要转 AAC;
  • 前端强制 / 偏好 HLS,但视频本身无需重编。

读矩阵时:DirectStream 关心的是 HLS 输出侧是否允许该视频 codec 的 copy / remux,以及音频是否需要进入 AAC 输出模式。视频「编码输出」列仍然不是主依据。

Transcode

任一存在的主轨需要重新编码时归入 Transcode。注意口径:

  • video=copy + audio=aac 在部分实现里仍记为 Transcode(因为主轨发生了重编码);
  • video=h264 + audio=copy 也是 Transcode;
  • 只有视频与音频(若存在)全部 copy 时才是 DirectStream。

读矩阵时:Transcode 才真正消费「解码输入 × 编码输出 × 色彩处理 × 画质档位」这几张子表。

Unsupported

不是「文件坏了」,而是当前输入事实 + 客户端能力 + FFmpeg 能力 + 策略下,构不出可执行播放计划。常见于:客户端既不能 DirectPlay,也不支持所需 HLS 输出形态;或 runtime 缺少必需的编码器 / tone mapping 能力。

三条输入轴:能力 × 事实 × 策略

矩阵单元格背后,Planner 几乎总在交叉三组输入。

1. 客户端能力

客户端上报的是声明,不是最终结论。通常包括:

  • 能否 HttpFile 直放、能否 HLS(含 fMP4 等输出形态);
  • 源格式事实:容器 / 视频 codec / 音频 codec / profile / level;
  • 输出格式事实:HLS 输出侧允许的视频 + 音频组合;
  • 动态范围处理:SDR / HDR10 / HLG / Dolby Vision 等是否作为输入可被客户端承接。

读矩阵时的常见误读:

误读更准确的理解
「客户端支持 HEVC」= 一定 DirectPlay还要看容器、音频、色彩安全、选轨与字幕路线
「客户端不支持某源 codec」= 一定播不了可能仍可 Transcode 成客户端可播的输出 codec
「客户端支持某种 HLS 输出」= 服务端一定能产出服务端还要有对应编码器、profile 策略与 capability gate

2. 媒体事实

来自扫描 / 探测的结构化事实,而不是展示文案。读矩阵时优先对齐这些轴:

决策轴典型事实影响什么
容器mkv / mp4 / webm …DirectPlay 容器匹配;HLS remux 边界
视频编码H.264 / HEVC / VP9 / MPEG-2 / VC-1 …能否 copy;解码输入是否在主线
profile / level / bit depthMain10、L5.1、10-bit …硬解约束、copy 安全、客户端 fact 匹配
动态范围SDR / HDR10 / HLG / DV(含有无 fallback)是否 tone mapping;走哪条硬件 / 软件链
分辨率与码率宽高、源码率画质档位是否可用、是否降分辨率 / 限码率
音轨codec、声道数、是否选中非默认轨copy 还是 AAC;是否阻断 DirectPlay
字幕路线关闭 / overlay / 是否要求 HLS window是否拒绝 HttpFile;一般不强制烧录视频

Dolby Vision 一类不要按「profile 数字」直接对号入座;更稳妥的读法是:有没有可用 fallback 层(SDR / HDR10 / HLG),有则按 fallback 路线走,没有才进入 pure DOVI reshaping 一类路径。

3. 服务端策略与 runtime 能力

策略决定「允许什么输出」,runtime 决定「机器现在能不能做」:

  • 输出 codec 策略:例如优先保留源 codec(在白名单内)、或强制 H.264 / HEVC / VP9;
  • 画质档位白名单:最大高度、目标码率、是否禁止升档;
  • 硬件加速策略:Auto 优先硬件,失败可回退软件;
  • FFmpeg capability graph:启动时探测的编码器、滤镜、VAAPI profile / 分辨率约束、OpenCL interop 等。

矩阵里的「当前支持」通常隐含:策略允许 + capability 存在 + 命令构造已接线 + 样片验过。缺任一环,都不能把厂商规格书上的「支持」写成业务上的「当前支持」。

读矩阵时建议的顺序

不要从左上角第一个 codec 格开始扫。更省时间的顺序是:

1. 这是 DirectPlay / DirectStream / Transcode 哪一层的问题?
2. 媒体事实落在哪条「解码输入」行?
3. 动态范围要不要 tone mapping?走软件 / VAAPI / OpenCL 哪类链?
4. 目标输出 codec 是否在 HLS 输出白名单内?
5. 画质档位是否触发降分辨率 / 限码率(与动态范围无关)?
6. 音频是 copy 还是统一 AAC?会不会单独把路线从 DirectPlay 推走?
7. 客户端 output fact 是否接得住该 HLS 输出组合?

解码输入 vs 编码输出

很多矩阵拆成两列:解码输入编码输出。读法差异很大:

读它解决的问题
解码输入服务端能不能读懂源视频并进入转码 / remux 主链
编码输出服务端能不能把结果重新编成某种 HLS 视频编码

例如:MPEG-2 / VC-1 可能已作为解码输入接入,但不在 HLS 编码输出白名单;PreserveSource 遇到它们会回退到 H.264 一类基线输出。AV1 则可能整行「暂不做服务端 HLS 输入 / 输出」。

色彩范围 ≠ 画质档位

另一类混读是把 HDR 处理和「选 720p」当成同一张表:

  • 色彩 / 动态范围:HDR10 / HLG / DV → Web SDR(BT.709)是否需要 tone mapping,走哪条滤镜链;
  • 输出质量:降分辨率、限码率、pixel format 整理、HLS 关键帧对齐。

SDR 源通常不需要 tone mapping,但仍可能因客户端能力或用户选档而进入 Transcode。HDR 源即便选「Direct」画质档,只要客户端不能安全直放,仍可能先 tone map 再输出。

音频与字幕:别让它们污染视频结论

读视频矩阵时,注意边界:

  • 视频转码能力判断,一般不应被「AAC profile 是否可用」污染;只有最终候选选择了「音频输出为 AAC」时,才检查 AAC 路径。
  • video=copy + audio=aac 在业务上可能记 Transcode,但视频链仍是 copy。
  • 字幕多走独立资源(VTT / ASS / SUP 等),主视频命令常固定不烧字幕;字幕要求 HLS window 时,会阻断 DirectPlay,但不等于必须视频重编码。

用三个小场景练读法

下面不贴完整表,只演示「看到现象 → 该查矩阵哪一轴」。

场景 A:Web 上 MKV + H.264 + AAC,却进了 HLS

优先查:

  1. 客户端是否偏好 / 强制 HLS;
  2. 容器是否不在 DirectPlay 源事实内;
  3. 是否选了非默认轨 / 外置音轨 / 需要 mapped delivery;
  4. 字幕路线是否要求 HLS window。

若最终 video=copy,这是 DirectStream 问题,不必先翻「H.264 软件编码输出」那一格。

场景 B:HEVC HDR10 在浏览器里变成 1080p H.264

这是典型 Transcode 读法:

  1. 解码输入:HEVC + HDR10 → 需要 tone mapping 到 SDR;
  2. 编码输出:客户端 Web 主线常落到 H.264(或策略允许的 HEVC / VP9);
  3. 画质档:用户或默认策略选了 1080p 上限;
  4. 加速:Auto 下可能优先 VAAPI tone map + 硬编,失败再 OpenCL / 软件。

矩阵要回答的是「HDR10 → SDR 的链路是否当前支持」,不是「浏览器能不能原生播 HDR10 源文件」。

场景 C:VP9 源有时 DirectPlay,有时 video copy + 音频 AAC

同一源 codec 可以走出完全不同的 PlayMethod:

  • 容器 / 音轨都在客户端源事实内 → DirectPlay;
  • 视频可 copy,但音轨(如 Vorbis)在 HLS 输出侧必须转 AAC → 常为 Transcode(视频仍 copy);
  • 选了降分辨率档 → 视频也会离开 copy,进入真正的视频重编码。

读矩阵时要把「VP9 输入支持」和「VP9 作为重新编码输出」分开:前者是解码 / copy 边界,后者是 encoder + 客户端 output fact + 策略开关。

「当前支持」的四道门

把单元格标成「当前支持」前,业务侧通常隐含四道门。公开文档或运维笔记里可以用同一清单自检:

门禁不过时的表现
Planner 可进入永远落在 Unsupported,或诊断码指向能力 / 策略拒绝
命令可生成会话创建成功但 FFmpeg 参数缺失 / 启动即失败
样片可播CLI 连续解码或浏览器能稳定拉 playlist / segment
失败可归因硬件回退原因、capability 缺失、策略拒绝可在日志中解释

因此:硬件白皮书支持 ≠ 矩阵当前支持CLI 手动 ffmpeg 成功 ≠ 业务已接线某一版 smoke 通过 ≠ 所有 profile / 分辨率 / bit depth 都过关

和排障文档怎么配合

  • 想确认「为什么是这条 PlayMethod」:先看 Planner 决策顺序与会话响应里的 method / delivery,再回矩阵核对该 method 依赖的轴。
  • 想确认「硬解 / tone mapping 为何回退」:矩阵给路线候选,具体回退原因仍以运行时日志与 capability 探测为准。
  • 想确认「媒体事实准不准」:先保证探测字段(codec、色彩、DV fallback 等)可靠,再谈矩阵命中;探测分工见 MediaInfo / ffprobe 相关文。

小结

阅读转码支持矩阵时,建议始终带着这张心智模型:

客户端能力(源事实 / 输出事实 / 动态范围处理)
  × 媒体事实(codec / 色彩 / 音轨 / 字幕路线 / 分辨率码率)
  × 服务端策略与 FFmpeg capability
  → PlayMethod + Delivery + 具体变换链
  • DirectPlay:几乎只问「源能否原样交给客户端」。
  • DirectStream:问「视频能否 copy 进 HLS,音频是否必须改」。
  • Transcode:才完整消费解码输入、编码输出、tone mapping 与画质档位。
  • 矩阵是业务接入真相,要和硬件规格、客户端声明、探测事实分开读,避免用一张表回答三个领域的问题。

相关阅读

同系列还可对照:

来源

本文改写自 Octans 项目文档中的播放转码支持矩阵(octans-docs usage 层),并吸收播放架构中关于 PlayMethod / Delivery 与 Planner 决策顺序的说明。正文强调读法与决策轴,不展开完整矩阵表与内部 API 字段细节;具体「当前支持」以目标环境版本与 capability 探测为准。