audio: widen forward decode cushion 30/15->60/30s + add [BP-DIAG] back-pressure instrumentation

Byte cap (96MB) unchanged as the hard OOM bound; the wider time window only lets sparse Opus use existing memory headroom to ride out decode jitter. Diag logs pin whether the block is back-pressure or decode throughput.
This commit is contained in:
daniel-c-harvey
2026-06-25 21:52:20 -04:00
parent f0d1463619
commit 61e185a2f7
4 changed files with 126 additions and 12 deletions
@@ -1292,11 +1292,25 @@ public class StreamingAudioPlayerService : AudioPlayerService, IStreamingPlayerS
/// </summary>
private async Task DrainBackpressureAsync(CancellationToken cancellationToken)
{
// [BP-DIAG] Time how long the read loop is actually parked here. A drain that releases in a few
// hundred ms is healthy throttling; a drain that holds for many seconds (paired with the JS
// PAUSED line) confirms back-pressure is parking production — whereas NO drain lines alongside
// frequent JS underrun PARK/RESUME lines means the loop never throttled and decode simply could
// not keep up. Logged only when it actually waited, so steady-state no-op drains add no noise.
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var waited = false;
while (IsPaused || await _audioInterop.IsProductionPaused(PlayerId))
{
waited = true;
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(BackpressurePollMs, cancellationToken);
}
if (waited)
{
_logger.LogInformation(
"[BP-DIAG] DrainBackpressure released after {Ms} ms (isPaused={IsPaused}, gen={Gen})",
stopwatch.ElapsedMilliseconds, IsPaused, _loadGeneration);
}
}
private async Task ThrottledNotifyStateChanged()