A second LoadTrackStreaming for the same in-flight track (UI double-fire, queue re-entry, or JS false-end auto-advance) is now dropped; a different-track load still supersedes. Targets the Opus double-load; keeps load-gen diagnostics.
The inter-segment back-pressure gate matched WAV byte density but let a 4MB Opus segment (~100s at 320kbps) decode eagerly into main-process RAM, OOMing the tab with HW accel off. Drain per chunk past high-water, gated on playback start. Adds load-generation diagnostics for the double-load hypothesis.
RecoverFromFailedRefill now sets IsStreamingMode=true so the in-place
seek-retry route isn't wedged. The generic-catch unload path is gated on
the loadCts identity, so a superseded load no longer clobbers a newer
operation's state.
cursor>=totalLength is the sole forward-EOF test; a short non-final body is
a truncation error, not EOF. Mid-stream forward-load failures now invoke
RecoverFromFailedRefill so the scheduler halts instead of a silent false end.
Two regression tests pin both paths.
Replace the open-ended forward GET with sequential bounded bytes=start-end
segments, the next fetched only when the scheduler drains below low-water,
so the browser holds ~one segment regardless of file size. Seek converges
on the same loop. Strip BP-DIAG.
Temporary, grep-tagged diagnostics at the read-loop pause, the scheduler
latch, and the chunk-result path to show whether ProductionPaused latches,
reaches C#, and parks the loop. Strip once the cause is confirmed.
C6/AC8: IsStillActiveSeek() predicate guards all three SeekBeyondBuffer
failure exits, so a superseded seek never recovers over a newer seek's
state. AC6: empty scheduler routes to seekBeyondBuffer so a same-target
retry (seek or play) refetches instead of no-oping.
Seek-back past the retained tail reuses the existing seek-beyond-buffer
Range path (per-path resolver). A failed refill now halts the scheduler
into a paused-but-loaded state (AC6) instead of a silent false end.
Skip the back-pressure interop poll while paused (UC5). Document complete()
draining the stash in full by design. Rename scheduler isProductionPaused to
evaluateProductionPause (latch-advancing); window exposure name unchanged.
Shared scheduler fill signal (forward water-marks + hard byte cap) pauses
the C# read loop above high-water and, for Opus, stops the demux/decode
feed so WebCodecs queues stay near-empty. Routes through the existing
cancellation discipline; releases the latch on clear/seek.
Player picks Opus when the browser can decode it and a sidecar exists (else lossless), injecting the sidecar before stream init; seek reuses the same format. Adds the Backfill-Opus bulk API endpoint + CMS action.
DOM bar chart with clip-overlay progress split; pointer-capture drag;
WaveformProfile fetched on load (fire-and-forget, cancellable); flat
fallback when no profile; small lazily-loaded waveformSeeker.js for
getBoundingClientRect and setPointerCapture.