Chrome stops calling requestAnimationFrame for a hidden tab, and Pixi's
ticker hangs on it. The run, the drawing and the recording all stood
still as soon as the user switched to another tab. A plain run keeps
standing still there, so a forgotten game does not play on unheard.
- backgroundBeat.ts ticks the editor from a worker at the recording's
fps while a recording goes and the tab is hidden, or the page has
not drawn a frame of its own for 250 ms. Once the page draws again,
the beat keeps out of the way.
- The worker looks every 4 ms whether a tick is due. A 16 ms interval
came in bursts behind a busy page, and the recording threw away the
second tick of each burst.
- backgroundTimers.ts and timerWorker.ts give the short waits of a
recording timers in a worker. Chrome slows the page's own timers to
once a second in a hidden tab. This covers the waits while saving
and the wait for a video's picture after a seek.
- Behind a tab Chrome does not call requestVideoFrameCallback, but the
picture is there at seeked. The wait there is 10 ms instead of
150 ms while the tab is hidden.
- The beat runs for Start recording, the exported game and Start
recording... in the main menu.
Tests:
- tsc, eslint, Prettier clean
- tests/viewport: 374 green, 3 new in background-beat.test.ts
- e2e 68k (3 checks) on melektaus-atx with the tab really hidden:
not in real time all 120 frames, colour changes every 30 frames,
the blip 8 ms from green; in real time 97 of 120 frames (73 with
the tab in front)
- Counter-check without the beat: all three 68k checks red, 3 frames
in 60 s not in real time, 7 frames in real time
- Gate on melektaus-atx: green, 311 files, 4821 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>