A graphical subtitle burn-in demuxes the whole file first, and never reads what it extracted #168
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Turning on a PGS track freezes the player. The segment request never answers,
nothing is logged, and no encoder starts — because the request is inside a
demux of the whole file, extracting subtitle tracks the transcode does not read.
Measured on a 24.2 GB 1080p remux over a gigabit share: ~4¼ minutes before
the first segment, at 95 MB/s, which is the link saturated. Upstream serves the
same file with the same track in 2–3 seconds.
The extracted files are never used. The
filter_complexof our own job:[0:2]is the PGS stream mapped out of the input. The three.supfiles therequest waited on are referenced by nothing.
Where the two servers part.
EncodingHelperbranches onhasGraphicalSubsagainst
hasTextSubsin every filter chain it builds (4122/4150, 4340/4374,4679/4713, 4934/4976). Only the text branch calls
GetTextSubtitlesFilter, andonly that reaches
GetSubtitleFilePath→GetReadableFile→ExtractAllExtractableSubtitles. A graphical subtitle is overlaid from thestream and nothing is extracted at all.
Ours makes no such distinction:
crates/ephyra-app/src/streaming/encoder/extract.rs::burns_in_a_subtitleisstate.subtitle_stream.is_some() && (Encode || always_burn_in), soextract_subtitlesruns for a graphical burn-in too — andsubtitle::tracks_oftakes every extractable track in the file, so picking one English PGS track
extracted all three. The filter chains themselves are right:
software.rs:89/92and the three hardware chains pick
graphical_sub_preprocess_filtersortext_subtitles_filterexactly as upstream does. Only the extractor'sprecondition is wrong.
A cancelled attempt keeps nothing. The extraction is spawned with
kill_on_drop, and<path>.metais written only after a complete run, so aclient that gives up on the frozen player loses every byte read. Retrying
starts from zero. That is why it reads as broken rather than slow — and it
stays true for a text burn-in, where the extraction is correct and upstream's.
Where to start
burns_in_a_subtitleneeds the text test the filter chains already make —is_text_subtitleis inephyra-encoding. That alone turns four minutes intotwo seconds for every graphical burn-in.
Worth a second look afterwards: an extraction that survives the request that
started it, so the text case does not lose a long read to a client that stopped
watching.
How to know it is done
Burning in a PGS track starts within seconds of the segment request and writes
no
.supat all — the overlay reads the stream. A burned-in SRT or ASS stillextracts, and still burns in. A test over the argument builder that asks which
of the two a graphical track takes, failing today.
House rules
CLAUDE.mdis the short version and these are the parts that bite: tests rununder
cargo nextest; upstream's source is the checkout inupstream/at thepin; generated files are regenerated rather than edited; a comment says what
the code does, not how it got there.
A test that cannot fail is worse than none.