feat: proactive MPEG-TS codec probe for automatic transcoding fallback#119
feat: proactive MPEG-TS codec probe for automatic transcoding fallback#119
Conversation
…anual button click Agent-Logs-Url: https://github.com/cbulock/iptv-proxy/sessions/11e04321-61e7-453c-a7bd-b3b61344dbe8 Co-authored-by: cbulock <176519+cbulock@users.noreply.github.com>
Add GET /api/stream-probe/:source/:name server endpoint that fetches the first 64 KB of a channel's upstream stream and parses the MPEG-TS PAT/PMT tables to identify video/audio stream types. Returns whether the codecs are compatible with browser MSE. Update admin UI setupVideoPlayer() to run the probe in parallel with HLS.js for ALL channels (not just HDHomeRun): - If probe detects MPEG-2 video (0x02), MPEG-1 (0x01), AC-3 (0x81), or other browser-incompatible codecs before HLS.js succeeds, pre-empt and switch to server-side transcoding via ffmpeg automatically. - If HLS.js fires MANIFEST_PARSING_ERROR (raw MPEG-TS response), await the probe result: incompatible → setupTranscodePlayer(), compatible → mpegts.js. - For HDHomeRun channels the probe URL includes ?streamMode=hls so the server probes the same content the browser will receive. Remove the old HDHomeRun-specific HEAD/GET content-type probe which only detected MPEG-TS vs HLS at the container level without inspecting codecs. Add 14 integration + unit tests covering MPEG-2/AC-3 detection, H.264/AAC pass-through, HLS detection, ?streamMode=hls forwarding, upstream errors, and PAT/PMT-absent fallback (assumes compatible to avoid false positives). Agent-Logs-Url: https://github.com/cbulock/iptv-proxy/sessions/34e5832a-aa46-4669-bce2-fbcfc736b3a8 Co-authored-by: cbulock <176519+cbulock@users.noreply.github.com>
… log transcode failures Agent-Logs-Url: https://github.com/cbulock/iptv-proxy/sessions/34e5832a-aa46-4669-bce2-fbcfc736b3a8 Co-authored-by: cbulock <176519+cbulock@users.noreply.github.com>
…-packet prefix Agent-Logs-Url: https://github.com/cbulock/iptv-proxy/sessions/34e5832a-aa46-4669-bce2-fbcfc736b3a8 Co-authored-by: cbulock <176519+cbulock@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a proactive stream codec probe (PAT→PMT parsing for MPEG-TS) so the admin UI can automatically fall back to server-side transcoding when the upstream stream carries browser-incompatible codecs (e.g., MPEG-2 video / AC-3 audio), preventing “black screen” playback.
Changes:
- Introduces
GET /api/stream-probe/:source/:nameto fetch a small upstream byte range and infer container + codec compatibility. - Updates the admin UI video player setup flow to run the probe in parallel with HLS.js and choose between HLS.js, mpegts.js, and transcoding based on probe results (with stale-guarding).
- Adds integration/unit tests for MPEG-TS codec detection and the new probe route behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
server/stream-probe.js |
New server route and MPEG-TS PAT/PMT parser used to infer codec compatibility. |
test/integration/stream-probe.test.js |
New unit/integration coverage for codec parsing and /api/stream-probe responses. |
index.js |
Registers the new stream-probe route in the server startup. |
admin/src/App.vue |
Replaces the old HDHomeRun-only Content-Type probe with a unified codec probe to drive fallback behavior. |
| before(async () => { | ||
| await fs.mkdir(path.dirname(channelsFile), { recursive: true }); | ||
| try { | ||
| originalChannels = await fs.readFile(channelsFile, 'utf8'); | ||
| hadOriginalChannelsFile = true; | ||
| } catch (err) { | ||
| if (err.code !== 'ENOENT') throw err; | ||
| } | ||
|
|
||
| await fs.writeFile(channelsFile, JSON.stringify(testChannels), 'utf8'); | ||
| await initChannelsCache(); | ||
|
|
||
| const app = express(); | ||
| setupStreamProbeRoutes(app); | ||
| app.use(errorHandler); | ||
|
|
There was a problem hiding this comment.
This integration test mounts setupStreamProbeRoutes() directly but does not isolate CONFIG_PATH/app.yaml or provide session middleware. If a developer has admin_auth configured locally, requireAuth becomes active and these requests will return 401, making the test environment-dependent. Consider setting process.env.CONFIG_PATH to a temp dir with an empty app.yaml (or stubbing req.session.authenticated) within this suite, similar to other integration tests that isolate auth config.
There was a problem hiding this comment.
Fixed in e5f1fb3. The before() block now creates a temp dir, writes an empty app.yaml into it, sets process.env.CONFIG_PATH to that dir, and calls invalidateAuthCache() — matching the pattern used in guide.test.js and mcp.test.js. The after() block restores CONFIG_PATH (deleting it if it was originally unset) and calls invalidateAuthCache() again to clean up.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… auth 401s Point process.env.CONFIG_PATH at a temp dir containing an empty app.yaml before the suite runs, then restore + invalidateAuthCache() in after(). This ensures requireAuth always passes through regardless of a developer's local config/app.yaml containing admin_auth credentials. Agent-Logs-Url: https://github.com/cbulock/iptv-proxy/sessions/50c4cbde-0224-4fc0-9b46-e6faa64bb32c Co-authored-by: cbulock <176519+cbulock@users.noreply.github.com>
The admin UI player would silently show a black screen for streams carrying MPEG-2 video or AC-3 audio — mpegts.js accepts the data but drops incompatible frames without emitting an error. The old HDHomeRun-specific
Content-Typeprobe couldn't distinguish codec compatibility within the MPEG-TS container.Server:
GET /api/stream-probe/:source/:nameFetches the first 64 KB of a channel's upstream and parses the MPEG-TS PAT → PMT chain to extract actual elementary stream types. Returns:
{ "container": "mpeg-ts", "browserCompatible": false, "videoStreamType": 2, "audioStreamType": 129 }0x01MPEG-1,0x02MPEG-2,0x80DigiCipher II0x03/0x04MPEG-1/2,0x81AC-3,0x87E-AC-3?streamMode=hlsto match what the browser actually receives (modern firmware returns HLS at that URL; older firmware returns MPEG-TS regardless)browserCompatible: truewhen PAT/PMT can't be parsed — biases toward false negatives over false-positive transcodingAdmin UI: unified codec probe in
setupVideoPlayer()Replaces the HDHomeRun-only HEAD/GET Content-Type probe with a single codec probe that runs for all channels:
MANIFEST_PARSING_ERRORbefore the probe returns — then routes tosetupTranscodePlayer()(incompatible) orsetupMpegtsPlayer()(compatible) based on actual codecsTests
14 new tests covering: MPEG-2/AC-3 detection, H.264/AAC pass-through, HLS content-type short-circuit,
?streamMode=hlsforwarding, upstream unreachable (502), PAT/PMT-absent fallback, and sync-boundary alignment with a null-packet prefix.