本文主要对照 Kodi 对 VobSub(idx/sub)的客户端原生路径,与媒体库产品把 VobSub 统一转成 Blu-ray PGS(.sup 再按既有 bitmap 合同分发的做法。目标是讲清架构差异与历史演进,不是承诺恢复 pair 数据面或各端自带 VobSub 渲染器。

媒体库字幕主线通常是:主视频不烧录;HLS 主输出固定去字幕流;客户端只提交 subtitleTrackId;服务端返回 presentation descriptor,客户端走唯一呈现路径。VobSub 一旦进入多端(Web / libmpv / Media3),「谁 demux、谁渲染、时间轴以谁为准」会迅速分叉。

Kodi:什么叫「原生 VobSub」

文件模型

文件内容
.idx文本索引:语言轨、timestamp + filepos、palette / size 等
.sub二进制 MPEG PS 中的 DVD SPU 包(常见 00 00 01 BA

完整路径需要 pair;孤立 .sub 不会被当成完整 VobSub 主路径。

发现与 demux

播放本地片源时扫描媒体旁路目录(subs / subtitles / vobsubs 等),对 .idx 找配对 .sub。专用 demux 大致:

  1. 文本读 .idx
  2. 用 FFmpeg 以 video/x-vobsub → mpeg 打开 .sub
  3. 用 idx 的 pts 覆盖 packet 时间戳
  4. 解码走 FFmpeg AV_CODEC_ID_DVD_SUBTITLE,渲染进自有 overlay

观察: Kodi 的「原生」= 自研 idx 时间轴 demux + 文件发现,解码主力仍是 FFmpeg dvdsub,不是从零写一套与 FFmpeg 无关的 DVD 解码器。碟片 SPU 菜单高亮路径与外挂 VobSub 也不完全同一条。

这对「我们自己做一个 VobSub 组件」的估工作量有直接含义:至少要覆盖发现、pair、时间轴、多语言轨、overlay 几何,而不是「调一个解码 API」。

媒体库侧:统一转 PGS 主线

当前合同(转 SUP 后)

来源产品主线
内嵌 VobSub服务端转 单语言 complete-file .sup
外置 idx/subcatalog 按语言拆轨后同样转 SUP
各端呈现复用既有 PGS / bitmap-overlay 路径

典型端侧消费:

客户端 / 内核HTTPFILEHLS
Webbitmap-overlay + complete-file track.sup同左 + timeline offset
Windows / Android libmpv不走 VobSub native-embedded;sidecar / 与 PGS 同类主输出 -sn + sidecar
Android Media3app-layer PGS overlay;不是 Exo 原生 VobSubcomplete-file overlay

转换侧质量合同往往包括:外置时间优先 IDX timestamp;画布保留源 size;颜色映射避免整字发黑;几何安全边距等。这些规则是「转一次、各端一致」的基础——若客户端各自 demux/渲染,必须在某处复刻,否则端间观感分叉。

为何收敛到转 SUP

历史演进(摘要):

  1. 外置 pair 阶段:Web 有 loadVobSub + index/data URL;Media3 基本不支持;内嵌长期缺口。
  2. native-embedded 窗口:HTTPFILE 上曾允许内嵌 bitmap in-band 策略,但内嵌 VobSub 产品上仍常因路由 / 资源缺失不可播——策略允许 ≠ 全端可用。
  3. 统一转 PGS:删除 pair 端点与 Web loadVobSub;presentation 显式禁止 VobSub in-band native-embedded;各端只消费 track.sup

动机可以压成三条:

  • 各端 VobSub 能力不一致,矩阵维护成本高
  • PGS 路径已在 Web / libmpv / Media3 overlay 打通
  • 服务端可集中落实时间轴与颜色合同

「客户端自己处理」要按三维矩阵想

讨论「不走服务端转 SUP」时,至少拆开:

取值
内核Web / Windows libmpv / Android libmpv / Android Media3
交付HTTPFILE 完整源文件 / HLS 无字幕主输出
来源内嵌 dvd_subtitle / 外置 idx+sub

再叠加身份命名空间:

UI / API:   subtitleTrackId
Catalog:    外置索引 / 内嵌 ffmpegStreamIndex
Kernel:     mpv sid | Media3 track | Web overlay session

libmpv 侧还有既有铁律:禁止把业务 track id 或源 ffmpegStreamIndex 直接当 sid;HLS 更禁止用源 index 映射当前 playlist 的 sid。这些约束与「能不能解 dvdsub」无关,却决定远程场景能不能做对。

可行性观察(非产品决议)

方向观察
本机外挂 + 单内核最接近 Kodi;与媒体库「远端 session」模型仍不同
HTTPFILE 内嵌 + libmpv技术上可能讨论 in-band;要重做选轨与禁止误映射
HLS + 任意内核主输出无字幕时,客户端仍需要 独立字幕资源;等价于另一种 sidecar 合同
Media3 原生 VobSub不能假设 Exo 开箱等于 Kodi pair 体验
每端一个组件可能让部分格子亮起来;时间轴 / 颜色 / 多端一致要付四次税

有可能性 ≠ 值得做。 统一转 SUP 用一次服务端复杂度换四端合同收敛,是媒体库多端场景里更常见的取舍。

和 PGS 压扁问题的衔接

转 SUP 之后,客户端仍可能踩 PGS plane AR ≠ 视频 AR 的绘制问题(尤其 Media3)。那是 bitmap 呈现层的几何问题,见 Android Media3 PGS字幕画幅排障。转格式解决的是 格式分裂,不自动解决 overlay 几何

相关阅读

参考与边界

  • Kodi 开源树中外挂字幕扫描、DVDDemuxVobsub、FFmpeg overlay codec 路径
  • 媒体库侧以当前 presentation / route 策略与已归档「VobSub→PGS」计划为准
  • 本文不做「是否恢复 pair」的产品决策,也不给改动清单