Skip to content

fix: Stop treating ffmpeg's HLS segment-end EOF as an upstream failure#55

Merged
sparkison merged 1 commit into
m3ue:devfrom
Warbs816:fix/ffmpeg-8.1-segment-eof-false-positive
May 5, 2026
Merged

fix: Stop treating ffmpeg's HLS segment-end EOF as an upstream failure#55
sparkison merged 1 commit into
m3ue:devfrom
Warbs816:fix/ffmpeg-8.1-segment-eof-false-positive

Conversation

@Warbs816
Copy link
Copy Markdown
Contributor

@Warbs816 Warbs816 commented May 4, 2026

Summary

linuxserver/ffmpeg:latest recently ticked from 8.0.1 to 8.1, and 8.1 surfaces a new stderr line on every HLS segment fetch end: [http @ 0x...] Error reading HTTP response: End of file. The HTTP layer just closes when the segment body is exhausted, and -reconnect 1 -reconnect_streamed 1 silently reopens the connection for the next segment — i.e. it's normal traffic, not a failure.

But the existing input_error_patterns in pooled_stream_manager.py had a bare "end of file" entry, so this line started flipping status = "input_failed" once per HLS segment (~every 10 seconds), causing the streaming generator to trigger failover and the player to constantly reconnect. ffmpeg 8.0.1 didn't expose this log, which is why the issue only emerged with the latest base image.

What changed

  • Drop "end of file" from the input error patterns. Real upstream loss is still caught by:
    • the more specific patterns (connection refused, server returned 4xx/5xx, error opening input, connection timed out, invalid data found, etc. — emitted when ffmpeg's reconnect actually fails)
    • the low-bitrate / silence detectors in stream_manager.py, which trigger on actual data starvation regardless of stderr
  • Lift the two pattern lists to module-level tuples (_FFMPEG_WRITE_ERROR_PATTERNS, _FFMPEG_INPUT_ERROR_PATTERNS) so they can be referenced from tests and don't get rebuilt per stderr-reader call

Test plan

  • Existing failover tests pass (tests/test_failover.py::TestFFmpegErrorPatterns)
  • New regression test asserts a bare [http @ ...] Error reading HTTP response: End of file line on stderr does not flip status to input_failed
  • Verified live against ffmpeg 8.1 on an HLS source: no more 10-second flapping; failovers only occur when the upstream genuinely returns an HTTP error / closes the playlist refresh

Compatibility

The patch is purely subtractive and has no public-API impact. Older ffmpeg versions that don't print this line are unaffected. The remaining patterns cover the same set of genuine input failures they always did.

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:44
@sparkison
Copy link
Copy Markdown
Member

Thank you! Good catch on this one 🙏

@sparkison sparkison merged commit c3124fa into m3ue:dev May 5, 2026
4 checks passed
@Warbs816 Warbs816 deleted the fix/ffmpeg-8.1-segment-eof-false-positive branch May 5, 2026 14:35
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