From 81abc4acca0b18837118b8cff7d2992bd881e3ae Mon Sep 17 00:00:00 2001 From: Deivid Soto Date: Thu, 7 May 2026 14:59:43 +0200 Subject: [PATCH] fix(transcoder): force aac stereo 48khz + frag_duration for mse compat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two transcoder fixes for browser MediaSource Extensions parsing: 1. -ar 48000 -ac 2 on the audio output. Source 5.1 / 7.1 streams produced a moov atom Chrome CHUNK_DEMUXER refuses to parse, even when the video metadata is fine and a non-MSE video element accepts the same file. Forcing AAC-LC stereo 48 kHz makes the moov shape MSE-compatible. 2. -frag_duration 1000000 (1 second) so each moof+mdat fragment caps at ~1s of media. Without it, ffmpeg only splits at keyframes and high- bitrate 1080p produces 8 MiB+ mdat boxes — MSE waits for the whole mdat before parsing the first fragment, so playback never starts. 3. -movflags +negative_cts_offsets so b-frames carry the right pts/dts offsets and the playhead doesn't reset every fragment. 4. New range_req debug log to make sizing bugs greppable. --- internal/engine/transcoder.go | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/internal/engine/transcoder.go b/internal/engine/transcoder.go index 1752d6d..215f5bd 100644 --- a/internal/engine/transcoder.go +++ b/internal/engine/transcoder.go @@ -259,18 +259,34 @@ func buildFFmpegArgs(filePath string, opts TranscodeOpts) []string { filterChain = "format=yuv420p,setparams=colorspace=bt709:color_trc=bt709:color_primaries=bt709:range=tv" } args = append(args, "-vf", filterChain) - args = append(args, "-c:a", "aac", "-b:a", coalesce(opts.AudioBitrate, "192k")) + // Force AAC-LC stereo 48 kHz so MSE's CHUNK_DEMUXER accepts the moov. + // 5.1 / 7.1 source streams produce a moov shape that MSE refuses to + // parse (the