Commit graph

2 commits

Author SHA1 Message Date
Deluan
8dee15501f refactor(transcoding): repair piped headers behind one patcher
The FLAC and mp3 repairs had grown into two copies of the same wrapper: the same
lazy peek on the first Read, the same MultiReader hand-off, the same tolerance of
a short read, and the same comment twice. They now share one headerPatcher, with
a prefix function per container.

Transcode no longer selects the patcher by opts.Format. That string is the target
format of a transcoding profile, which users can name anything, so a row called
'mp3 320' running the default mp3 command got no repair at all, while a row whose
command emits FLAC got one only because the FLAC arm was the default. The shared
peek dispatches on the magic bytes instead, which both patchers already had to
check, and leaves anything it does not recognize untouched.

Also drops b2i in favour of gg.If, and lowers the ID3 bound to 64KB: ffmpeg
cannot write an attached picture to a non-seekable output, so the tag ffmpeg
pipes out stays small.
2026-09-24 17:16:04 -04:00
Deluan
c05fbd0edb fix(transcoding): declare the duration of a piped mp3 transcode
The mp3 muxer writes the Xing frame that carries the frame count only after
rewinding to the start of the stream, which it cannot do on a pipe (-f mp3 -).
An uncached transcode therefore declares its length nowhere: no Xing frame, and
no Content-Length unless the client asks for the estimate. A decoder has to
guess the duration from the bytes it has so far, and an offline copy stays
unseekable, the same defect #6105 fixed for FLAC.

Transcode now inserts a Xing frame ahead of the first audio frame, carrying the
frame count derived from the track duration. Only the frame count is declared:
a piped encode cannot know its own byte size, and a wrong size is worse than an
absent one. Decoded audio is unchanged, since decoders skip the tag frame.

Measured on a 20s 128kbps transcode: ffprobe reports 20.010s instead of
20.036s, and Firefox reports 19.998s at loadedmetadata instead of 2.04s
climbing over nine durationchange events. This does not make an uncached
transcode resumable; that needs range support, which only the cache path has.

Reported in #6170.
2026-09-24 17:16:04 -04:00