Commit graph

3 commits

Author SHA1 Message Date
Deivid Soto
3fcfaaf234 fix(stream): iOS exige total concreto en el Content-Range del remux
iOS/WebKit abre todo <video src> con una sonda "bytes=0-1" y se niega a
reproducir si el 206 no trae una longitud concreta en Content-Range —
"/*" (total desconocido, el fix anterior del loop de re-seek) le hacía
abortar y re-bootstrapear la sesión sin parar.

Vuelve a anunciar siempre un total numérico (exacto si ffmpeg terminó, el
estimado mientras crece). El loop de re-seek real no era el total
anunciado sino el init segment malformado, ya arreglado con +delay_moov
en buildFFmpegArgs. Test nuevo: la sonda 0-1 debe llevar total concreto.
2026-06-10 22:37:02 +02:00
Deivid Soto
5f2d1cdc70 fix(stream): no anunciar un total falso mientras el remux crece (loop de re-seek)
serveGrowing anunciaba en Content-Range total = EstimatedSize() = el tamaño
del MKV fuente mientras ffmpeg aún corría. Pero el fMP4 resultante no mide
eso (el audio re-encodea a AAC y la fragmentación cambian el byte count), así
que el <video> nativo mapeaba su timeline sobre una longitud falsa, pedía
offsets que no cuadraban, re-seekeaba y reabría la conexión cientos de veces
por segundo (el loop de reproducción remux).

Mientras crece (!Final) la longitud real es DESCONOCIDA: ahora se sirve
Content-Range "bytes start-end/*" (RFC 7233 §4.2) sin Content-Length, y el
cliente lee secuencial en vez de re-seekear. Cuando ffmpeg termina, el tamaño
real se conoce y se anuncia como antes. El 416 y el Content-Length del HEAD
solo cuando el total es real (final).
2026-06-10 19:42:37 +02:00
Deivid Soto
4a12f13b96 feat(stream): progressive fMP4 remux source for /stream (hueco #3 / 3b-i)
Agent side of 3b: serve a growing ffmpeg `-c copy` remux (mkv h264/aac →
fragmented MP4) over /stream with no video re-encode. Dormant until the web
sends PlayMethod="remux" (3b-ii), so this commit changes no live behavior.

- GrowingSource interface + transcodeSource already satisfies it; estimate is
  the source file size for copy actions (≈ remux output) vs bitrate×duration
  for real transcodes.
- NewRemuxSource: ffmpeg -c copy → growing fMP4 temp, returned as GrowingSource.
- StreamServer.SetGrowingFile + serveGrowing: manual Range responder for a
  growing source (http.ServeContent needs a fixed size). 206 with an estimated
  total in Content-Range; chunked body while not final (never promise bytes a
  running remux might not produce); exact Content-Length once final. Blocks via
  ReadAt for not-yet-produced bytes; forward seek waits, backward seek instant.
- daemon OnStreamSession: PlayMethod=="remux" → NewRemuxSource + SetGrowingFile
  + MarkSessionReady (after the ffmpeg check; copy still needs ffmpeg).
- Tests: parseByteRange + serveGrowing (full/offset/bounded/estimate/HEAD/416).
2026-05-31 11:49:31 +02:00