The use case
I'm adding an optional determinate loading indicator to the host app's pre-playback screen: a progress bar with a percentage instead of the usual indeterminate spinner, so the user can tell a slow open apart from a stuck one.
I want the number to be honest, so it's driven purely by real startup checkpoints (completed steps over total steps), never elapsed time, byte counts, or an ETA. A slow stage holds, a skipped stage jumps. That part works and I'm happy with the semantics.
What's possible host-side today
The host can already derive a coarse ladder from existing publishes, and that's what I shipped:
- load dispatched
playbackPhase leaves .idle
- first non-empty
audioTracks (or a nonzero duration) lands, meaning the probe finished
isSessionReady
hasFirstFrameReadyForDisplay (nice addition in 6.13.0, this is its first use here)
- first
.playing
Six edges, so the bar moves in roughly 20% steps. Livable, but the real problem is where the edges sit: on a slow origin almost the entire wait is inside the open/probe window, between steps 2 and 3, and the host has zero visibility into it. The bar sits at 20% for ten seconds and then sprints to 100%, which reads worse than it should given how much real work the engine is progressing through in that window.
The ask
A published, generation-scoped startup progress snapshot the host can observe. Shape I'd find useful:
- a semantic current stage plus completed/total checkpoint counts (or a normalized fraction derived from them)
- monotonic within one load generation; steady republishes deduped
- a new
load() starts a fresh generation at zero; publishes from a superseded generation are ignored
- an engine-internal reroute (the remote-HLS bypass decision, a backend correction) stays inside the same user-visible startup and never lowers the value; it can update the stage label
- error/stop ends the sequence without ever publishing the final checkpoint
- checkpoints emitted from the code that actually completes the work, roughly: connection opened, probe finished, route chosen, backend host constructed, ready, first frame, playing
- paths that legitimately skip work (audio-only, the AVPlayer-direct bypass) complete the skipped checkpoints immediately rather than stalling
The biggest single win would be any sub-steps inside the open/probe window itself (connected vs first bytes vs probe complete, or however the internals naturally divide), since that's the stretch the host can't see at all and it's where slow sources spend their time.
Explicitly not asking for time estimates, byte-based percentages, or anything driven by timers. Checkpoints only, and no extra work on the startup path beyond publishing them.
If there's already a better seam for this than a new published property, happy to adapt to whatever fits the engine's conventions.
The use case
I'm adding an optional determinate loading indicator to the host app's pre-playback screen: a progress bar with a percentage instead of the usual indeterminate spinner, so the user can tell a slow open apart from a stuck one.
I want the number to be honest, so it's driven purely by real startup checkpoints (completed steps over total steps), never elapsed time, byte counts, or an ETA. A slow stage holds, a skipped stage jumps. That part works and I'm happy with the semantics.
What's possible host-side today
The host can already derive a coarse ladder from existing publishes, and that's what I shipped:
playbackPhaseleaves.idleaudioTracks(or a nonzeroduration) lands, meaning the probe finishedisSessionReadyhasFirstFrameReadyForDisplay(nice addition in 6.13.0, this is its first use here).playingSix edges, so the bar moves in roughly 20% steps. Livable, but the real problem is where the edges sit: on a slow origin almost the entire wait is inside the open/probe window, between steps 2 and 3, and the host has zero visibility into it. The bar sits at 20% for ten seconds and then sprints to 100%, which reads worse than it should given how much real work the engine is progressing through in that window.
The ask
A published, generation-scoped startup progress snapshot the host can observe. Shape I'd find useful:
load()starts a fresh generation at zero; publishes from a superseded generation are ignoredThe biggest single win would be any sub-steps inside the open/probe window itself (connected vs first bytes vs probe complete, or however the internals naturally divide), since that's the stretch the host can't see at all and it's where slow sources spend their time.
Explicitly not asking for time estimates, byte-based percentages, or anything driven by timers. Checkpoints only, and no extra work on the startup path beyond publishing them.
If there's already a better seam for this than a new published property, happy to adapt to whatever fits the engine's conventions.