The game view could already record itself through nodes. Making a
video of the editor itself, to show how something is done, needed an
outside screen recorder. The main menu now starts and stops one, with
no options to set.
- "Start recording" sits in its own group before General settings, and
reads "Stop recording" while one runs. The name is
"Recording <time>", the size is the whole canvas in device pixels
(an odd row or column is cut), 60 fps always. Sound is the master,
saving goes the same way as for the game view.
- The encoder, the sound and the Matroska writing of a take moved from
GameRecorder.ts to RecordingTake.ts. A take now reads its pictures
from a FrameSource, so the game view and the editor share it.
- The editor's picture is copied from the canvas after each render, in
the same frame, so nothing is drawn twice. A resting editor does not
render, and the recording repeats its last picture.
- The mouse pointer is drawn into the recording in the shape the editor
shows (arrow, hand, resize arrows, I-beam, crosshair, move).
- A red dot with the running time stands beside the menu button on
screen only. It is drawn after the copy, and the toolbar makes room
for it.
- Drawing that dot made Pixi take it as the root for every hit test,
and the menu would not open any more. The stage is set back as the
last rendered object after it.
Tests:
- Gate on melektaus-atx green: 303 files, 4686 tests.
- Unit recording: 20 green, 5 new.
- e2e 67: 8 checks, 67e new. It records through the menu and decodes
the MP4: 1280x800 at 60 fps, the pointer black at the mouse, the dot
missing, 238 plain spots alike with the canvas. Without the pointer
and with the dot drawn before the copy, 67e is red.
- e2e 46: the main menu lists "Start recording".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A game can now film itself. A behavior starts and stops a take, and
the editor turns it into a video asset with the run's picture and the
sound the player hears. The exported game hands the file over as a
download, since there is no project to keep it in.
- New action nodes `Start recording` (Name, Resolution, FPS) and
`Stop recording`. An empty name becomes `Recording <timestamp>`.
- Resolution is `Game view`, `720p` or `1080p`. For the fixed sizes
the height is set and the width follows the camera.
- The picture is the camera only, without hints, overlays or the
letterbox. It is drawn into a render texture of the target size,
so a smaller window still gives full 1080p.
- `PictureReader` reads the texture back through pixel buffers with
a fence. The editor never waits on the GPU, and a frame with all
three buffers busy is dropped and counted.
- Nothing of the take reaches the visible canvas. A first version
drew tiles into it and copied them out, and with the low-latency
canvas that midway state flickered on screen.
- The sound is tapped behind the master limiter in the FX worklet
and encoded as Opus.
- H.264 is chosen when the browser has it, VP9 otherwise. A small
own Matroska writer packs both tracks, no new dependency. It names
the frame rate and BT.709 so ffmpeg keeps both.
- A second `Start recording` is ignored with a warning in the log.
A take goes on through `Load scene` and a restart, pauses with the
editor and is saved when the run ends. It stops at 2 GB.
- The editor uploads the take on the existing video route and makes
the asset once the run is over. The video tab gets a Download
button for the converted MP4.
- `downloadBlob` in `src/ui` replaces the song editor's own copy.
Findings:
- `On start` runs before the game screen knows the world. A take
therefore fixes its size on the first frame that has a camera.
- Without a frame rate in the file, ffmpeg turned 30 fps into 59.94.
- The worker's poster JPEG is off in colour for every upload (red
255 comes out as 229, BT.601). Not touched here.
Tests:
- Unit recording + matroska: 21 green, plus the node catalog cases.
The Matroska test reads the file back with its own EBML reader.
- e2e 67 (new) on melektaus-atx: ALL PASSED. 1080p30 from a
1280x800 window gives a 1920x1080 MP4 with sound and no dropped
frame. Every 4th pixel is checked, a green quarter catches an
upside-down picture. A take ended by Esc is saved with the
timestamp name.
- e2e 60j: the exported game downloads an `.mkv` with EBML magic.
- The flicker is gone on the user's machine without `?vsync`.
- Gate on melektaus-atx: CHECK EXIT 0, 299 files, 4586 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>