Videos: game view recordings are limited range, colour in the stream

- How it is made: the GPU turns the picture into I420, limited range
  BT.709, and avcColour.ts writes the colour into the SPS too.
- Why: VLC 3 showed full-range recordings too dark, even with the
  range in the stream. Older recordings stay full range.
- Development: 2068 editor checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adminandClaude Opus 5.5 committed 2026-10-13 19:48:47 +02:00
1 parent 7b29263879
commit 3311619147
2 files changed
+13 -7

No files matched your search

+1 -1
@@ -21,7 +21,7 @@ php tests/php/releases.test.php # the release stor
php tests/php/files.test.php # uploaded files in a folder per account (#344), the same way
php tests/php/videos.test.php # the video store, its queue and the worker (#402), with the
# real ffmpeg: the CI image and feuerwerk-video have it
node tools/seed-e2e.mjs && node tools/e2e.mjs # 2067 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 2068 editor checks, screenshots in /tmp/gm-e2e-*.png
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
./e2e.sh start [GM_STEPS] # the same run detached, see below
./e2e.sh status # live progress, or the last run's result
+12 -6
@@ -223,12 +223,18 @@ Two action nodes record what the game view shows, with what the master plays (#4
How it is made: H.264 from Chrome's `VideoEncoder` (VP9 where there is no H.264), hardware where
the computer has it, 10 Mbit/s at 1080p60, a keyframe every 2 s. The file is Matroska, written by
the editor itself (`src/core/recording/matroska.ts`) in clusters as the frames come, with the
frame rate and the colour (BT.709) in its head, so nothing has to guess them. The rules (size,
codec level, which frames are taken, where the picture goes in a frame) are plain functions in
`src/core/recording/recording.ts`, the browser's side is `src/viewport/GameRecorder.ts`, and
`src/viewport/PictureReader.ts` reads the frames back through pixel buffers with a fence. The
encoders, the sound and the file are `src/viewport/RecordingTake.ts`, which the editor recording
below shares.
frame rate and the colour (BT.709) in its head, so nothing has to guess them. The colour goes into
the H.264 stream as well (`src/core/recording/avcColour.ts` writes it into the SPS of the
encoder's `avcC`), for players that read only the stream, such as VLC. A game view recording is
limited range like any video: the GPU turns the picture into I420, limited range BT.709, before it
is read back, and the encoder gets the planes with that colour. Fed RGB, Chrome's encoder made
full-range video, and VLC 3 showed that too dark and its colours off, even with the range in the
stream. Game view recordings saved before 2026-10-13 are full range and stay so. A player that
heeds the range shows them right. The rules (size, codec level, which frames are taken, where the
picture goes in a frame) are plain functions in `src/core/recording/recording.ts`, the browser's
side is `src/viewport/GameRecorder.ts`, and `src/viewport/PictureReader.ts` reads the frames
back through pixel buffers with a fence. The encoders, the sound and the file are
`src/viewport/RecordingTake.ts`, which the editor recording below shares.
## Recording the editor