本文主要介绍一类媒体库产品在多端客户端上的总路线:为什么不能把「跨平台 UI 框架是否足够好」当成顶层问题;为何应坚持 Web 做基线、各端原生 UI、各端 native 播放;以及协议、能力上报与服务端 fallback 哪些可以共享、哪些必须按平台落地。
以 Octans 为例。目标不是「用一套 UI 覆盖手机、平板、桌面和 TV」,而是在每个平台尽量正确播放真实媒体库中的复杂资源,并在 TV / HTPC 上给出符合遥控器与 10-foot 场景的交互。下面把研究结论压成可复用的产品架构表述。
优先级:播放先于 UI 复用
普通业务 App 常按「UI 框架 → 业务页面 → 再接播放器插件」选型。媒体库客户端应反过来:
播放功能兼容性
↓
平台播放输出链路与 TV 交互
↓
UI 框架工程效率
↓
UI 是否跨平台复用
顶层要回答的是:
HEVC Main10、HDR10/HDR10+/HLG/ Dolby Vision 能否正确解码、tone mapping、直出或可控 fallback。DTS/DTS-HD/TrueHD/ Atmos 等能否解码为 PCM、HDMI bitstream 或服务端转码。PGS/VobSub/ 简单与复杂ASS能否同步渲染,或走 overlay / burn-in。- 高码率 MKV、蓝光 remux、HTTP Range、HLS fMP4、字幕 sidecar 与服务端 planner 能否形成稳定决策。
- Android TV、tvOS、Windows HTPC 等 10-foot 入口能否稳定处理焦点、返回栈、OSD 与失败恢复。
跨平台 UI 只在上述四项不被破坏时才进入考虑。UI 能不能复用,不是第一问。
Web 是基线,不是能力上限
服务端决策、客户端执行:权限、媒体事实、播放方式、受控流地址与进度回收在服务端;播放器执行、交互、错误展示与进度上报在客户端。
Web 正式边界适合作为管理端、内容浏览、轻播放与服务端适配后的 HLS 基线:
PlaybackSession
DirectPlay / HttpFile
DirectStream + Hls
Transcode + Hls
stream token · HTTP Range · Progress / Resume
字幕 full-cache / 客户端渲染
服务端 fallback planner
浏览器 <video> / hls.js 不能代表 Android TV、Apple TV、Windows HTPC 或移动端原生播放器的上限。对外表述应是:Web 承接基线体验与远程管理;高规格播放由各端 native 内核承担。
Web 前端自身的 UI 基座(自有 primitives、表格与主题边界)是 Web 产品内部问题,不自动导出为「全端统一壳」。Web 基座选型见同系列 媒体内容产品 + 管理后台混合前端的 UI 基座选型。
为何不把「统一跨平台 UI」当总方案
主流跨平台 UI 框架都能接原生播放器(channel、plugin、platform view、native module),但通常只是调用或嵌入。它们不能保证:
- 某台设备能硬解某份
HEVC Main10/AV1/VP9 Profile 2样本。 - 某个 Dolby Vision profile 能被正确识别、fallback 或触发电视 DV 模式。
- 某台盒子能经 HDMI/eARC 正确 bitstream 高阶音频。
- PGS composition 在 seek 后不漏显;复杂 ASS 达到 libass 级排版。
- 各桌面 OS 的 HDR 输出、音频设备与 GPU backend 行为一致。
评估时应问:
是否允许无损接入本平台最合适的播放器内核?
是否妨碍 native surface、HDR surface、音频 passthrough、字幕 overlay 与 TV 焦点?
是否让 fallback、诊断、能力上报与错误恢复更复杂?
简要结论(只作 UI shell 评估,不等于播放器能力):
| 路线 | 对 Octans 类产品的价值边界 |
|---|---|
| Flutter / React Native | 普通移动业务 UI 可行;高规格播放与 TV 仍要大量平台代码,复用价值易被播放复杂度抵消 |
| .NET MAUI / Avalonia / Uno | 桌面壳或普通业务可行;不替代已定的 Host + native 播放,TV 非强项 |
| Compose Multiplatform | Android 生态内 Compose / Compose for TV 有明确价值;不宜扩成全端统一 UI |
| Qt / QML | 桌面播放器级候选;若已有主 Web UI 与 Desktop 复用决策,重写收益通常不足 |
| Electron / Tauri / WebView | 复用现有 Web UI 价值最高;适合控制面与轻播放,不适合 Android TV / tvOS 播放本体 |
| 平台原生 UI | 最少抽象损耗,最易处理 HDR / 音频 / 字幕 / TV 焦点 |
**拒绝「一个 Flutter / RN / MAUI / Qt App 覆盖所有端」**的核心原因相同:播放验证矩阵不会因 UI 框架统一而缩小;TV 焦点与系统媒体栈仍要平台特化;对已有 Web 管理资产的复用往往更差。
DirectPlayFile 与 TV:两条硬边界
原生客户端不能只围着 HLS
Web HLS 对浏览器重要;Android、Windows、Linux 与部分高级桌面模式必须保留 DirectPlayFile(或等价:原文件 / 受控 Range URL → 本地 demux → 系统硬解或 libmpv → 音频 / 字幕分级处理)。若客户端只播 HLS,蓝光 remux、内嵌 PGS、TrueHD / DTS-HD、复杂 ASS、HDR / DV 会过早落入服务端转码,失去原生客户端价值。
TV 不是桌面或平板的放大版
TV 的核心是输入模型与播放场景:D-pad 焦点、媒体键、10-foot 信息密度、横向 shelves、OSD、音轨字幕菜单、刷新率与 HDR 输出、HDMI/eARC 音频、可遥控操作的失败恢复。通用跨平台 UI 可以模拟部分焦点;长期质量通常取决于 Android TV 原生焦点 / Compose for TV、tvOS Focus Engine 或 Windows HTPC 自建 InputRouter。
Android 侧「单 App + 触控 / TV 双 Shell」与 Compose for TV 主线,见 Android 媒体客户端:单 App 双 Shell 与 Compose for TV 选型。Windows 侧「WebView2 复用管理 UI + native 播放,HTPC 另议」见 Windows 媒体客户端 UI 路线:WebView2 复用、WinUI 3 候选与当前主线。
推荐分层:共享产品,不共享内核与壳
总原则
统一产品协议
统一播放抽象
统一能力上报模型
统一服务端 playback planner 与 fallback policy
不统一播放器内核
不统一 UI 框架
不把 UI 跨平台复用放在播放兼容性前面
三层拆分
Shared Product Layer
认证 · 目录模型 · Playback API / Session
进度续播 · 选轨模型 · Capability report
错误分类 · 诊断 / 遥测 · 用户播放策略
Platform Playback Layer
Windows / Linux:受控 LGPL libmpv(Linux POC;失败可转 libVLC 等)
Android / Android TV:Media3 / ExoPlayer(高级兼容内核仅 POC + 许可门禁)
Apple:AVPlayer / AVFoundation
Web:browser video / hls.js 基线
Server:remux / 转码 / 音频 fallback / 字幕提取与 burn-in / HDR tone mapping
Platform Interaction + UI
Web:既有 Vue 内容与控制台
Windows Desktop:Host + WebView2 复用主 Web UI;播放 native
Windows HTPC:独立大屏 shell + InputRouter + native OSD
Android Phone / Tablet:Kotlin + Compose
Android TV:Compose for TV / 原生焦点体系
iOS / iPadOS / tvOS:SwiftUI / UIKit + Focus Engine(TV)
macOS:SwiftUI / AppKit 默认;高级桌面可评估 libmpv
播放器抽象(UI 不直操作具体内核)
产品层统一引擎语义(load / play / pause / seek / 选轨 / 输出模式 / stats / capability / release 与对应事件)。平台映射示例:
| 平台 | 后端映射(示意) |
|---|---|
| Windows | LibMpvBackend;简单格式可 Media Foundation 兜底 |
| Linux | LibMpvBackend;必要时 libVLC 等 |
| Android | Media3PlayerEngine;可选高级兼容引擎 |
| Apple | AVPlayerEngine |
| Web | HtmlVideoEngine / HlsJsEngine |
能力上报是 runtime fingerprint
客户端能力不是静态「平台支持表」,而是运行时指纹:交付方式(Range / HLS / DirectFile)、容器、视频 codec / HDR / DV profile、渲染 surface、字幕多级能力、音频解码与 passthrough、TV 焦点与 OSD 等。失败原因回传服务端以便 replan(codec / HDR / 音频 / 字幕 / surface / runtime / 许可门禁等)。
服务端 fallback 树保持最终防线:DirectPlay → Remux / DirectStream → 仅音频转码 → 字幕转换 / overlay → burn-in → HDR tone map 转码 → 全量视频转码 → 明确 unsupported。
各端主线一览
| 平台 | UI / 壳 | 播放主线 | 关键边界 |
|---|---|---|---|
| Web | Vue + 自有 UI | <video> / hls.js | 基线与管理;复杂媒体承诺保守 |
| Windows Desktop | Host + WebView2 复用主 Web | 受控 LGPL libmpv | Web 是控制面,不是播放本体 |
| Windows HTPC | 独立大屏 shell | 同上 + WASAPI / InputRouter | 不复用桌面表格与控制台页 |
| Linux Desktop | Web shell 或轻 Host | LGPL libmpv POC | 自带 runtime,不绑发行版任意 mpv |
| Android Phone / Tablet | Kotlin + Compose | Media3 / ExoPlayer | 保留 DirectPlayFile;平板走自适应布局 |
| Android TV 等 | Compose for TV | Media3 + 能力探测 / passthrough 策略 | TV 独立信息架构 |
| iOS / iPadOS / tvOS | SwiftUI / UIKit | AVPlayer | 长尾(MKV / PGS / TrueHD 等)靠服务端适配 |
| macOS | SwiftUI / AppKit | AVPlayer 默认 | libmpv 仅高级模式候选 |
复杂能力(HDR / DV、高阶音频、PGS / ASS)必须分层表述,避免写成单一 boolean「支持」。例如 DV 更适合写「兼容播放;完整输出依赖设备 / 系统 / 容器 / profile;否则 fallback HDR10 或 SDR tone mapping」,而不是「完整支持 Dolby Vision」。
闭源商用下的播放内核约束
技术能力之外还有分发边界(非正式法律意见):
- 优先:系统播放器 API(AVPlayer、Media3、Media Foundation 等)、宽松许可证组件、合规动态链接的 LGPL runtime。
- 严格审计:FFmpeg、libmpv、libVLC、GStreamer 插件、预编译 native 包。
- 不适合作为闭源内嵌主线:默认 GPL mpv / GPL FFmpeg 构建、未审计 AAR、GPL-only 插件链入主程序等。
正式分发前仍需要 license inventory、SBOM、source offer、构建参数与 third-party notice。Windows 受控 libmpv 运行时细节见同系列相关文。
常见误区
| 误区 | 后果 | 纠正 |
|---|---|---|
| 先定跨平台 UI 再补播放 | 高规格播放后期被迫重写 | 内核与验证矩阵先定,UI shell 后定 |
| 把 Flutter / RN 等当成 codec 矩阵解法 | 复杂样本仍失败 | 只当 UI shell,播放按 native 验收 |
| Windows WebView2 复用 = 浏览器播放 | 削弱 HTPC / remux 目标 | UI 控制面 vs LibMpv 播放面写死 |
| Android 只做 HLS | remux / PGS / 高阶音频过早转码 | 保留 DirectPlayFile 与能力上报 |
| Apple 强行万能内核主线 | 牺牲 HDR / DV / 能效 / 系统集成 | AVPlayer 主线,服务端处理长尾 |
| TV 复用手机或桌面页 | 焦点、OSD、返回栈体验差 | TV shell 独立 |
| 字幕 / DV / Atmos 写成单一「支持」 | 用户预期与样本结果错位 | 多级能力 + 明确 fallback 文案 |
对同类产品的启示
- 产品协议可以统一,播放表面与焦点模型不能硬统一。
- Web 复用解决的是管理面与轻播放速度,不是 TV 与 OSD 免费。
- 「能接原生播放器」不等于「跨平台 UI 已解决播放」。
- 验证矩阵按媒体样本 × 设备 × 输出链路 × 交互 gate 建,不按框架文档建。
- 闭源分发时,LGPL / runtime 门禁与 UI 路线正交,换壳不得回退合规。
注意事项
- 本文是架构与选型边界说明,不是某一端的实现手册或交付排期。
- 跨平台框架能力会随版本变化;判断标准是「是否无损接入本平台最佳内核」,不是某插件 README 的平台勾选列表。
- 内部计划拆分、样本库与设备清单属于执行层;对外只需固定「不统一 UI / 不统一内核、统一协议与 planner」原则。
相关阅读
- Windows 媒体客户端 UI 路线:WebView2 复用、WinUI 3 候选与当前主线:Desktop 控制面复用与 native 播放 / HTPC 边界。
- Android 媒体客户端:单 App 双 Shell 与 Compose for TV 选型:触控与 TV 交互隔离,TV 框架主线。
- 媒体内容产品 + 管理后台混合前端的 UI 基座选型:Web 端自有 UI 边界;多端是原生各自 UI。
来源
本文改写自 Octans 项目「多平台客户端 UI 与播放优先选型」研究材料,并结合 Windows Desktop UI 复用、Android Shell / Compose for TV 与 Web UI 基座等已公开决策口径整理。实现路径与内部仓库路径已脱敏;不构成法律意见。