Skip to content

LL-DASH partial byte-ranges are .byteranges-sidecar-only — read them from the MPD instead #986

Description

@jonathaneoliver

Context

The encoder (infinite-streaming-encoder) is moving to self-describing manifests: all fragment byte-range information now lives inside playlist.m3u8 and manifest_fragmented.mpd, and the per-segment .byteranges JSON sidecars are to be removed.

Verified against the sample encode insane_fpv_shots_hydrofoil_windsurfing_p200_h264_xs (encoded 2026-08-07):

  • HLS<rung>/playlist.m3u8 carries the full part list:
    #EXT-X-PART:DURATION=0.200200,URI="segment_00001.m4s",BYTERANGE="82678@432",INDEPENDENT=YES
  • DASHmanifest_fragmented.mpd carries per-fragment ranges:
    <SegmentURL media="1080p/segment_00001.m4s" mediaRange="432-150105"/>
  • manifest.mpd stays at segment granularity (<SegmentURL media=.../>, no range).

The sidecar content is now strictly redundant — segment_00001.m4s.byteranges holds exactly the same offsets/lengths/independent flags as the #EXT-X-PART lines.

Problem

The HLS path is already ready. The DASH path is not.

HLS — OK. Both readers prefer the manifest and only fall back to sidecars:

  • go-live/pkg/parser/playlist.go:126 LoadPlaylistInfoWithByteranges builds ranges from parsed segment.Parts, falling back at :170 only when no parts were found.
  • go-live/pkg/parser/byterange.go:31 LoadByterangesForPlaylist parses #EXT-X-PART first, falls back to sidecars at :108.

DASH — broken. go-live/pkg/dash/mpd.go:619 loadByterangesForSegment() reads only <segment>.byteranges:

byterangesPath := segmentPath + ".byteranges"
payloadBytes, err := os.ReadFile(byterangesPath)

There is no manifest-derived path. go-live writes mediaRange on output (mpd.go:1107, :1135) but never reads it, and nothing in go-live/ or go-upload/ references manifest_fragmented.mpd.

Impact — silent degradation, not a hard failure

Both call sites treat a missing sidecar as "no partials" rather than an error:

  • mpd.go:580 → on err != nil || len(fragments) == 0, appends a single whole-segment virtualSegment{Offset: 0, Length: 0}.
  • mpd.go:1070usePartials block is skipped entirely when the read fails.

So once the encoder stops emitting sidecars, LL-DASH and the sub-6s DASH variants will quietly drop to whole-segment granularity. No error, no log line — the manifests just stop carrying partials. This is the dangerous part: it will look like it still works.

Proposed change

  1. Teach go-live/pkg/dash to source fragment ranges from manifest_fragmented.mpd (SegmentURL/@mediaRange, grouped by @media), keyed the same way loadByterangesForSegment keys today.
  2. Keep the sidecar read as an explicit fallback for legacy content.
  3. Make the "no fragment data at all" case loud — log once per content that DASH partials are unavailable, instead of silently emitting whole-segment ranges.

Acceptance criteria

  • LL-DASH and 1s/2s DASH variants generated from insane_fpv_shots_hydrofoil_windsurfing_p200_h264_xs with all .byteranges files deleted carry the same mediaRange values as they do today with sidecars present.
  • Legacy content with sidecars but no manifest_fragmented.mpd is unchanged.
  • Content with neither logs a distinguishable warning.

Related: sidecar removal cleanup (separate issue), near-CBR + ladder validation (separate issues).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggoPull requests that update go codepoints:5Fibonacci story points: 5priority:P1This sprintvalue:highHigh product value

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions