Keep a driven video ready while its sprite is off (#404)

A cut between two videos flashed white: the sprite switched on had
no picture yet, because its player only opened then or had been
dropped meanwhile. A driven video now waits muted at its time while
its sprite is off, in the editor and in a run.

- A disabled sprite with Video clock Driven asks for its player
  without drawing it. A Free video still opens when shown.
- A run's draw list keeps disabled driven sprites, marked as off.
  Before, collectWorldItems dropped every disabled object, so the
  game view never held a player for them.
- VideoLibrary.wear() counts as asking. The sweeper dropped a held
  player after 2 to 4 s and it was loading again at the cut.
- The speed of the asked time is read over a window that grows to
  500 ms. Over 100 ms one 1/60 s step more or less read as 17 % off,
  the playback rate jumped and the sound dropped out.
- A stream feeds every packet it has loaded to the decoder at once
  and waits once. One round trip per 20 ms packet let the decoder
  fall behind on a busy main thread, which made e2e 34 flaky in CI.

Tests:
- Unit streaming, video-library, video-follow: green, 4 new
- e2e 34 + 66 (atx): ALL PASSED, stream skipped 0, 66m new
- e2e 66 (atx), two runs: ALL PASSED, 25 checks, 66n new
- Gate (atx): CHECK EXIT 0, 297 files, 4557 tests
- Counter-checks: without the draw list fix 66n finds no player,
  without the wear() fix and with the old speed reading the new
  unit tests turn red

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-11 15:37:16 +02:00
1 parent 774207208c
commit 43fd22a763
11 files changed
+202 -40

No files matched your search

+4 -1
View File
@@ -92,7 +92,9 @@ export class VideoLibrary {
/**
* What a sprite wears (#404): with its clock driven, a player of its own that shows the picture
* at its Video time; otherwise the ref as it is. `wearer` names the sprite where it is drawn, so
* the same object in two views drives two players. Asked every frame, like `get`.
* the same object in two views drives two players. Asked every frame, like `get`, and it counts
* as an ask: a sprite switched off wears its player without drawing it, and one let go for that
* loaded again when it was switched back on, white until then.
*/
wear(ref: TextureRef, props: PropertyBag, wearer: string, heard: boolean): TextureRef {
if (!videoDrivenOf(props) || !isVideoKey(ref.file)) return ref;
@@ -100,6 +102,7 @@ export class VideoLibrary {
const time = videoTimeOf(props);
const player = this.players.get(key) ?? this.start(key, time);
if (!player?.drive) return ref;
player.asked = performance.now();
const drive = player.drive;
drive.time = time;
drive.heard = heard;