Jump to content

Live TV (HLS/IPTV): Emby reads inflated bitrate from TS stream headers rather than HLS BANDWIDTH= value, incor


Recommended Posts

me@jackbenda.com
Posted

I first spoke about this bug on a thread in the Linux page and have just gotten around to raising this as a bug report on GitHub, though I'm not sure how actively that's monitored. Posting here as well in case it's a better route to the right people, like @Luke

---

Environment

Emby Server: 4.9.3.0
OS: Ubuntu Server 24.04 LTS
Hardware: Intel i5-12500, Intel UHD 770 (VAAPI / QuickSync)
IPTV source: ErsatzTV 26.3.0 (Docker), HLS Segmenter mode
Client: Emby for Android 3.5.28

---

What's happening

When playing a Live TV channel via an HLS/IPTV source, Emby detects a significantly inflated stream bitrate and triggers ContainerBitrateExceedsLimit, forcing unnecessary transcoding of a stream that should be eligible for direct play.

ErsatzTV is configured to encode at 1200 kbps video + 128 kbps audio (~1.33 Mbps total). The HLS manifest advertises a correct BANDWIDTH= value consistent with this. However, Emby's Live TV pipeline detects the stream at 4,192,000 bps (~4.2 Mbps) - more than 3x the actual encode bitrate.

From the transcoding logs, Emby is summing bitrate values read from the probed TS stream headers:

  Video stream:    BitRate 4,000,000
  Audio stream:    BitRate 192,000
  Container total: Bitrate 4,192,000

These values do not reflect the actual encode settings. Emby appears to be trusting stream-level header metadata from the probed TS segments rather than the BANDWIDTH= value advertised in the HLS manifest.

---

Steps to reproduce

1. Add an HLS-based M3U source to Emby Live TV (e.g. ErsatzTV configured to encode at ~1.2 Mbps)
2. Set the client's streaming bitrate above the actual encode bitrate but below ~4.2 Mbps
3. Play a Live TV channel
4. Observe ContainerBitrateExceedsLimit in the transcoding log and transcoding being initiated despite the stream being within the client's stated limit

---

Expected behaviour

Emby uses the BANDWIDTH= value from the HLS manifest to determine the stream bitrate. A ~1.33 Mbps stream should direct-play when the client bitrate limit is set above that value.

---

Actual behaviour

Emby probes the TS segment headers and reads a bitrate of ~4.2 Mbps regardless of the actual encode bitrate or the BANDWIDTH= value in the HLS manifest. ContainerBitrateExceedsLimit is triggered even when the client limit far exceeds the true stream bitrate.

---

Log evidence

Two separate sessions confirm the same behaviour:

Session 1 — client bitrate limit set to 3,808,000 bps:
  Detected container bitrate: 4,192,000 bps
  TranscodeReasons: ContainerBitrateExceedsLimit, DirectPlayError

Session 2 — client limit raised to 4,000,000 bps (still just below the detected value):
  Detected container bitrate: 4,192,000 bps
  TranscodeReasons: ContainerBitrateExceedsLimit, DirectPlayError

The second session is particularly telling — raising the client limit to exactly 4 Mbps still triggers transcoding because the detected container bitrate is 4,192,000, just above it. Full logs attached.

---

Related

ErsatzTV issue #2022 — HLS stream bitrates inflated during detection in Jellyfin/Emby Live TV pipelines

---

Workaround

Setting the client's maximum streaming bitrate to 20–30 Mbps masks the problem by raising the threshold above the inflated detected value. This is not a fix... it disables a meaningful safeguard and causes all Live TV to transcode regardless of source quality.

---

Potential solution

For Live TV HLS sources, Emby should use the BANDWIDTH= value from the HLS manifest as the authoritative bitrate for the ContainerBitrateExceedsLimit check, rather than probing the TS segment headers. The manifest value is what the HLS spec intends for this purpose (probing live segments for bitrate is unreliable, as segment headers may carry peak or nominal values that don't reflect the actual encode target.)

It's also worth noting that the reason the probed values are so far off (4 Mbps vs ~1.33 Mbps actual) may involve incorrect bitrate metadata being written into the TS stream headers by ErsatzTV, but regardless of the source of that discrepancy, trusting the manifest BANDWIDTH= value would be the more correct and robust behaviour.

ffmpeg-transcode-2c59b904-f3b8-417a-91db-6111478bb332_1 (1)(2).txt ffmpeg-transcode-3aa1a334-fdde-419f-a931-cb9380d36de0_1(1).txt

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...