Skip to content

Relay a live source at the source boundary, byte-exact - #128

Merged
ralyodio merged 1 commit into
mainfrom
stream-source-boundary
Sep 12, 2026
Merged

Relay a live source at the source boundary, byte-exact#128
ralyodio merged 1 commit into
mainfrom
stream-source-boundary

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Follows #124 (merged), which shipped the relay compression baseline with the source boundary documented but unbuilt. A live channel could only be relayed as its post-ffmpeg output, and asking for the source bytes always answered SOURCE_BOUNDARY_UNAVAILABLE. This builds the source boundary for the sources nixamp can read exactly.

What it does

  • A channel can read its own source and pipe it to ffmpeg instead of letting ffmpeg dial it. Every chunk down that pipe is handed to the source's taps first, so a tap sees exactly the bytes ffmpeg does: the original transport stream, padding and all, not the re-muxed output that drops null packets. The tap ends when the source starts over, and the pipe is paced by ffmpeg's own reading through ordinary backpressure.
  • Only exactly-readable sources are read this way: a transport stream from a plain http(s) URL or a local file, joined from its start, with no per-request headers and no separate audio file. Anything else stays ffmpeg's to dial, and a source-boundary relay of it is refused with the reason. The readability gate is one tested function; it treats ffmpeg transport demux tuning (-probesize, -analyzeduration, -fflags, as Raw 1080p and 4K transport streams play, go live, and reach a browser #126 now passes for every TS) as fine, and rejects only real request-header flags.
  • The envelope and negotiation now carry the boundary and the media codecs. A source relay taps the source; a channel relay listens to the output; the two are different variants, so a channel can serve both at once without one compressor doing the other's work. A receiver learns the boundary and codecs before the first byte, so a source-boundary receiver hands the bytes to its own ffmpeg without a probe.
  • Bringing a relay in probes it first: a source-boundary upstream is read through this server too, so it plays here and can be relayed on again at either boundary.
  • A source-boundary relay is a live join with no preface: the receiver's demuxer re-syncs on the next program table and keyframe, like any live join.

Tests (9, all passing)

  • the readability gate against each way a source fails it;
  • a deterministic byte-exact tap with a controlled source and a stub ffmpeg, including rollover ending the tap;
  • an end-to-end source relay over HTTP that reassembles the original packets byte for byte from the start;
  • a real-ffmpeg tee reading a transport-stream file;
  • and the existing route/negotiation suite.

Full suite: 545 pass, the one remaining failure is the pre-existing @profullstack/player web-test module resolution, unchanged from main.

Not here

Sources ffmpeg alone can reach — behind per-request headers (a yt-dlp link), a separate audio track, or a non-transport container — stay channel-boundary only, as documented. docs/stream-compression.md is updated for all of the above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MxNif5tsYq4LczgG7aE8Jp

The source boundary was documented but unbuilt: a live channel could only
be relayed as its post-ffmpeg output, and asking for the source bytes
always answered SOURCE_BOUNDARY_UNAVAILABLE. Now, for the sources nixamp
can read itself, it can.

A Channel may read its own source and pipe it to ffmpeg rather than let
ffmpeg dial it. Every chunk that goes down that pipe is first handed to
whoever has tapped the source, so a tap sees exactly the bytes ffmpeg
does -- the original transport stream, padding and all, not the re-muxed
output that drops null packets. The tap is ended when the source starts
over, so a new generation never follows the old middle, and the pipe is
paced by ffmpeg's own reading through ordinary backpressure.

Only the sources that can be read exactly are read this way: a transport
stream from a plain http(s) URL or a local file, joined from its start,
with no per-request headers and no separate audio file. Anything else
stays ffmpeg's to dial, and a source-boundary relay of it is refused with
the reason. The readability gate is one function, tested against each way
a source can fail it.

The relay encoder now carries its boundary in the envelope and the
negotiation headers; a source relay taps the source, a channel relay
listens to the output, and the two are different variants so a channel
can serve both at once without one compressor doing the other's work. A
receiver learns the boundary and the media codecs before the first byte,
so a source-boundary receiver can hand the bytes to its own ffmpeg
without a probe. Bringing a relay in now probes it first: a source-boundary
upstream is read through this server too, so it plays here and can be
relayed on again at either boundary.

A source-boundary relay is a live join with no preface: the receiver's
demuxer re-syncs on the next program table and keyframe, the same way a
listener joining a live channel does.

Tests: the readability gate; a deterministic byte-exact tap with a
controlled source and a stub ffmpeg, including rollover ending the tap;
an end-to-end source relay over HTTP that reassembles the original packets
byte for byte from the start; and a real-ffmpeg tee reading a transport
stream file. Full suite 509 pass; the one remaining failure is the
pre-existing @profullstack/player web-test module resolution on this
branch, unchanged from main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MxNif5tsYq4LczgG7aE8Jp
@ralyodio
ralyodio merged commit 47d0ba3 into main Sep 12, 2026
2 checks passed
@ralyodio
ralyodio deleted the stream-source-boundary branch September 12, 2026 12:45
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.

1 participant