Files
hyperframes/packages
Miguel Ángel 36db44d9b7 perf(core): a paused preview stops running its audio output (#4534)
* perf(core): a paused preview stops running its audio output

The preview runtime opened its AudioContext at load and left it running for the whole
session, so a paused Studio kept an audio output stream rendering silence in Chrome's
audio service and output threads, and on Chrome's fake sink once a context has been silent
for 30 s.

The transport now suspends the context once it has been paused for a second with no
captured track playing, and resumes it for Play and for a captured track that plays while
paused (the scrub route). The delay keeps a stop-and-reschedule inside one play (a rate
change, a hidden track, a seek while playing) from bouncing the output. A Play that lands
while a suspend is pending resumes anyway, and a Pause that lands while Play waits on
resume() lets the context go back to sleep.

* fix(core): decoded audio after an idle pause starts where the picture is

Review follow-ups to the idle suspend:
- A decoded track read its start time before waiting for the context to wake, so every
  Play after an idle pause anchored the clock that far back and the picture stepped back.
  The transport now reads the time after the wake.
- The transport kept every element it ever captured. It now holds only captured tracks
  that are playing, so a replaced track is free once it pauses.
- A failed suspend and destroy() both clear the pending-suspend flag, so the next pause,
  or a fresh init(), can suspend again.
- A test pins the one-second idle delay; the redundant "ended" listener is gone, since a
  track that ends fires "pause" first.

* fix(core): a preview whose browser starts audio late still goes quiet when idle

The idle timer was armed only if the context was already running when the transport opened
it or resumed it, so a browser that starts the context a moment after construction left it
running until the first pause. The transport now arms the timer from the context's own
statechange event, which Chrome fires after construction and on every resume, so the
separate arming in init() and after a stale Play are gone.

* fix(core): a reloaded track no longer keeps a paused preview's audio awake

Reloading a playing captured track (el.load(), a src swap) stops it without a "pause" event,
so the transport kept counting it as playing and a paused preview never went quiet. The
idle check now drops tracks that are already paused before it counts, and "emptied" is
handled like "pause" so the idle timer is armed when a reload stops a track.

* perf(core): a paused preview waits 10 s before its audio output goes to sleep

* docs(core): say why a paused preview's audio waits 10 s before it sleeps

* fix(core): a browser-side audio suspend drops the preview's idle timer
2026-09-26 15:26:03 +00:00
..
2026-09-25 22:58:59 -04:00
2026-09-25 22:58:59 -04:00