Skip to content

6.27.1 - The live join gate names what it held

Choose a tag to compare

@superuser404notfound superuser404notfound released this 16 Aug 21:07
· 701 commits to main since this release

One diagnostic change on the loopback live path. No API change, no change to playback itself, drop-in from 6.27.0.

A startup nobody could see from outside

A loopback live session's entire join latency is one withheld /media.m3u8 response. The first serve holds until the window carries the live-edge holdback (3 x TARGETDURATION, the RFC 8216bis floor the served playlist advertises) of content behind the edge, because serving earlier puts AVPlayer's opening seek inside its own stall-danger zone, where it restarts in a loop instead of playing (#189).

Everything else the engine does for that session is finished before the gate is entered. Measured with aetherctl live against a paced raw-MPEG-TS origin, same machine and fixture, varying only the backlog the origin holds at join:

backlog at join first readyToPlay
0 s (strict realtime) 18.66 s
6 s 12.70 s
12 s 6.75 s
30 s 0.43 s

The startup ladder reached sessionConstructed at +0.19 s in every one of them. The wait is the runway being filled at whatever rate the origin hands it over, and nothing else.

Only a FAILED gate used to log. A successful eighteen-second hold left no trace at all, so a host measuring a slow live start had no way to tell it apart from a slow probe without instrumenting from outside the engine.

What every exit says now

[HLSVideoEngine] first live manifest served after 18.154s: 5 segments / 20.000s >= 18.000s holdback (TARGETDURATION 6s)
[HLSVideoEngine] first live manifest served after 0.088s: 5 segments / 20.000s >= 18.000s holdback (TARGETDURATION 6s)
[HLSVideoEngine] first live manifest served after 10.284s: 2 segments / 10.000s < 15.000s holdback (TARGETDURATION 5s), fastZap bounded start after 2.000s grace

Two of those exits changed more than their wording:

  • The bounded .fastZap start reported its grace alone, which is the last leg of the wait rather than the wait. The third line above described itself as 2.000s while having held for 10.284s.
  • The exit where no segment was ever cut returned in silence, which from a host's side is the one outcome indistinguishable from a merely slow origin. It says so now.

The interval is monotonic, because it is a measurement. One account per session, so a steady playlist refresh does not repeat it.

Reading a slow live start

startupProgress stalls at sessionConstructed for the whole wait, so the checkpoint at the slow moment separates this from the demux probe (streamsProbed) and the display handshake (routed).

LoadOptions.liveJoinProfile is the lever. .fastZap collapses TARGETDURATION to the source keyframe cadence and the holdback follows it down, but the win belongs to the source GOP rather than to the flag, since TARGETDURATION can never fall below ceil(max EXTINF): on a 1 s-GOP fixture .fastZap reached readyToPlay at 1.98 s against .standard's 18.66 s, and on a 5 s-GOP one it still took 12.59 s.

docs/api.md gains Where a live start's seconds go, the paragraph this section summarises.

Raised by @ksktech-dev while measuring AetherEngine against libVLC across their device matrix (#374).