Skip to content

feat: draw external subtitles and play open-GOP sources during takeover - #11

Merged
InfinityPacer merged 5 commits into
mainfrom
sw/subtitles-open-gop
Oct 20, 2026
Merged

InfinityPacer merged 5 commits into
mainfrom
sw/subtitles-open-gop

Conversation

@InfinityPacer

Copy link
Copy Markdown
Owner

问题

  • 浏览器接管播放 STRM 时,选中外挂 SRT 字幕后 Plex Web 另发字幕转换请求,播放器随之关闭,外挂字幕也从不显示。
  • 开放式 GOP 的片源(关键帧之后还有引用前一 GOP 的帧,或短 GOP 的尾帧晚于下一个 IDR)在转封装时报时间戳错误,接管后一直加载。
  • 接管中读取失败时画面停在加载状态,没有任何提示。

结果

  • 外挂 SRT 与 WebVTT 由扩展读取并绘制,播放中打开、切换与关闭都跟随,Plex Web 每次换字幕会重建会话,扩展重新接管,缓冲几秒后从原位置继续。ASS 等格式提示字幕不可用,视频照常播放。control-v1 未改动。
  • 开放式 GOP 片源可以正常起播与拖动,从头播放与 Seek 走同一条分片转封装路径。
  • 接管中的读取失败改为弹出 Plex 自己的错误对话框,引擎的详细错误跨 Worker 保留。

验证

本地(Node 22、pnpm 11)

pnpm build        通过
pnpm typecheck    通过
pnpm lint         Checked 158 files, No fixes applied
pnpm test         Test Files 54 passed (54)  Tests 416 passed (416)
git diff --check  通过

真实页面(Plex Web + 配套反代,合成与公开测试片源)

  • 外挂字幕 8 步验收:选中外挂 SRT、换另一条、换内嵌、关闭、选中 ASS 出现提示且视频继续、拖动后只显示新字幕,均通过。
  • 开放式 GOP 的 4K 片源起播 0 丢帧,拖动到 7:54 正常续播。

限制:从头播放改走分片转封装后,没有做改动前后的首帧、CPU 与内存对比,仓库没有能自动复现播放管线的测量工具,上述真实页面验收覆盖了起播与 Seek 的功能表现。

🤖 Generated with Claude Code

InfinityPacer and others added 5 commits October 20, 2026 19:43
Open-GOP random access points (HEVC CRA, H.264 recovery-point I frames)
are followed in decode order by leading pictures that present earlier.
Seeking onto such a key fed those pictures with negative timestamps, and
leading pictures that present before an already written picture of the
previous GOP made the MP4 muxer reject the stream ("Timestamps cannot be
smaller than the largest timestamp of the previous GOP").

Video packets now pass through a leading-picture filter before the muxer.
The start key drops its undecodable leading pictures, and a mid-stream key
whose leading pictures cross the previous GOP drops only its own leading
pictures. Other open GOPs are passed through unchanged. Playback from the
start uses the same manual packet path as Seek so the filter applies to
both.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
When a takeover failed with a read-class error the hook only stopped the
session. Shaka's media data path was already unloaded, so Plex Web kept an
empty video element and an endless spinner, and the in-page notice
disappeared after a few seconds.

After releasing the session the hook now dispatches a critical Shaka
network error (HTTP_ERROR) on the current player for media_read_failed and
source_expired, before or after ready, so Plex shows its own s1002 dialog,
which the existing presenter rewrites with the ShimWeave message. These
failures do not block the source, so a retry takes over again. Nothing is
dispatched when Plex has started another load meanwhile or for stop codes
such as media_detached.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Some encodes, typically chunked encodes spliced at a scene cut, end a
short GOP with a picture that presents after the next IDR. The MP4 muxer
rejects that IDR ("Timestamps cannot be smaller than the largest timestamp
of the previous GOP"). Such a key is now demoted to a regular picture of
the current GOP, keeping every frame and the decode order and losing only
that random access point.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Error details longer than 200 characters were dropped entirely, so a muxer
failure reached the page only as "stream_failed Error". The worker now
keeps the first and last 80 characters of a long detail, which retains the
actual timestamps at the end of muxer messages, and the session-end detail
on the video element allows 320 characters.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@InfinityPacer
InfinityPacer merged commit fe52846 into main Oct 20, 2026
1 check passed
@InfinityPacer
InfinityPacer deleted the sw/subtitles-open-gop branch October 20, 2026 18:15
@InfinityPacer

Copy link
Copy Markdown
Owner Author

补上从头播放改走分片转封装(b7398e1)前后的对比。真实页面,Plex Web 播放一集 4K(3840×1632)STRM,默认音轨 EAC3,经配套反代由扩展接管,每次清掉播放记录从头播放,起播后 6 秒向后 Seek 120 秒。时间从点击播放算起,到画面开始推进。

版本 首帧推进 Seek 恢复 丢帧 主线程 CPU JS 堆
0.0.4 1112 / 1240 / 1191 ms 569 / 714 / 729 ms 0 / 160 10–11% 36–37 MB
0.0.5 1071 / 1178 / 1027 ms 700 / 536 / 692 ms 0 / 160 10–11% 36–37 MB

两版在误差范围内持平,均在发布门槛(首个可播放分片与 Seek 恢复 p95 < 2 s)以内。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant