viewer HTTP: Content-Type application/octet-stream, not video/mp2t

VLC parses Content-Type before invoking the demuxer chain. With
video/mp2t it commits to demux="ts" by MIME alone, bypassing
byte-probing; when the ts demuxer's Open fails on the live HTTP stream
("no demux modules matched"), the input never opens. mpv probes
regardless of Content-Type.

Reproduced deterministically with a Python shim that mimics our
response headers byte-for-byte: only the Content-Type matters.
Changing it to application/octet-stream (or any non-video MIME, or
omitting the header) makes VLC fall back to byte-probing, which
finds the TS sync pattern and opens cleanly. mpv unaffected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 16:30:46 -04:00
parent 3aa8d73ea0
commit 0a253bd919
+8 -1
View File
@@ -225,8 +225,15 @@ async fn serve_capture(listener: TcpListener, mut gst_stdout: ChildStdout) {
return;
}
// Content-Type intentionally application/octet-stream, not video/mp2t.
// VLC eagerly maps video/mp2t to demux="ts" and bypasses content
// probing; its ts demuxer's Open then fails on the live HTTP stream
// with "no demux modules matched" and the input never opens. With a
// non-video Content-Type, VLC falls back to byte-probing, which finds
// the TS sync pattern and opens cleanly. mpv probes regardless of
// Content-Type, so it's unaffected.
const RESPONSE: &[u8] = b"HTTP/1.1 200 OK\r\n\
Content-Type: video/mp2t\r\n\
Content-Type: application/octet-stream\r\n\
Cache-Control: no-cache, no-store\r\n\
Connection: close\r\n\
\r\n";