Skip to content

feat: Expose output_media_info for transcoded streams#56

Merged
sparkison merged 4 commits into
m3ue:devfrom
Warbs816:feat/expose-output-media-info
May 11, 2026
Merged

feat: Expose output_media_info for transcoded streams#56
sparkison merged 4 commits into
m3ue:devfrom
Warbs816:feat/expose-output-media-info

Conversation

@Warbs816
Copy link
Copy Markdown
Contributor

@Warbs816 Warbs816 commented May 4, 2026

Summary

Pairs with the editor PR that adds an "Output" badge row to the Stream Monitor — m3ue/m3u-editor#1095. The existing media_info publishes the source ffmpeg is reading; this PR adds an output_media_info counterpart describing what ffmpeg is producing (encoder codec, target resolution, muxer container, plus the live progress numbers, which are technically output stats).

Also includes the fix from #55 (merged into this branch). If #55 lands first I'll rebase to drop the duplicate commit; if you'd rather have one PR, #55 can be closed in favour of this.

What changed

Parser state machine (src/pooled_stream_manager.py)

SharedTranscodingProcess gains an output_media_info: Dict[str, Any] and a _parsing_output: bool flag. A new _parse_ffmpeg_output_line matches the "Output #N, FORMAT, to 'TARGET':" line ffmpeg prints once per output, captures the muxer container, and flips _parsing_output = True. _parse_ffmpeg_stream_line then routes subsequent Stream # ... Video|Audio: ... lines to output_media_info instead of media_info. _parse_ffmpeg_progress keeps writing bitrate_kbps/fps/frame/speed to media_info (so the existing Stream Info row in the editor doesn't regress) and additionally mirrors them into output_media_info once the output marker has been seen.

API surface (src/stream_manager.py)

A symmetrical _get_output_media_info mirrors _get_media_info and is included alongside media_info in the per-stream payload of get_stats(). Empty for plain HTTP-proxy streams (no ffmpeg → no encoder side) and for resolver-backed streams (yt-dlp/streamlink).

EOF fix (carried from #55)

Drops the bare "end of file" from input_error_patterns. ffmpeg 8.1 emits Error reading HTTP response: End of file on every HLS segment fetch end and silently reconnects via -reconnect 1, so that line was triggering false-positive failover roughly every 10 seconds against the latest linuxserver/ffmpeg:latest. Real upstream loss is still caught by the more specific patterns and the data-starvation detectors.

Test plan

  • Stream Info badge row in the editor still populates from probe data + live ffmpeg input fields (no regression — covered by existing tests in PR feat: Expose live stream media info for the Stream Monitor UI #54)
  • Output row populates with encoder codec/resolution/audio/container/fps/bitrate from a live transcoded stream
  • Plain HTTP-proxy stream: output_media_info returned as {} so the editor's Output row stays hidden
  • HLS / yt-dlp / streamlink resolver paths: output_media_info empty (no ffmpeg encoder)
  • No segment-end-EOF false-positive failovers under ffmpeg 8.1

Compatibility

  • media_info shape is unchanged for existing readers (progress fields still present there)
  • New output_media_info field is additive in the API response — older editor versions ignore it

Warbs816 added 3 commits May 3, 2026 17:20
Pairs with the m3u-editor side: surfaces what ffmpeg is *producing* (encoder
codec, target resolution, muxer container) alongside the existing media_info
which describes the source ffmpeg is reading. The Stream Monitor UI's existing
"Stream Info" badge row reflects the input; the editor adds an "Output Info"
row to render this new payload separately.

The parser now tracks state — once ffmpeg's "Output #" line is observed,
subsequent "Stream #N: Video|Audio:" lines populate output_media_info instead
of media_info. Live progress fields (bitrate/fps) describe encoder output and
are dual-written so existing Stream Info readers keep working without coupling
to a coordinated client release.
ffmpeg 8.1 (linuxserver/ffmpeg:latest as of May 2026) writes
"Error reading HTTP response: End of file" to stderr at the end of every
HLS segment fetch — the HTTP layer closes when the segment body is
exhausted and -reconnect 1 silently reopens the connection for the next
segment. ffmpeg 8.0.1 didn't surface this; 8.1 does, and it tripped the
existing "end of file" entry in input_error_patterns, causing the proxy
to fail over every ~10 seconds during normal playback of any HLS source.

Drop the bare "end of file" string. Real upstream loss is still caught by:
- the more specific input patterns (connection refused, server returned
  4xx/5xx, error opening input, etc. — emitted when reconnect actually
  fails)
- the low-bitrate / silence detectors in stream_manager.py, which trigger
  on actual data starvation regardless of stderr.

Also: extract write/input pattern lists to module-level tuples so they
can be referenced by tests and don't get rebuilt per stderr-reader call.
@Warbs816 Warbs816 marked this pull request as ready for review May 4, 2026 23:57
@sparkison sparkison merged commit 0fa1e7e into m3ue:dev May 11, 2026
3 checks passed
@Warbs816 Warbs816 deleted the feat/expose-output-media-info branch May 11, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants