Screen helpers · interface
LockableSurface
The surface a clip is recorded from: a fixed-size frame, composited and paced.
Explained in Recording and clips.
interface LockableSurfaceimport type { LockableSurface } from '@driftengine/core';In depth
Three things it fixes, all of which were visible in the first export:
Aspect is rendered, not cropped. The scene is drawn at the export's own pixel size, so a vertical clip is framed vertically. Cropping a 16:9 view to 9:16 throws away 44% of the width, and the subject is exactly what falls outside — the shot was composed for the other rectangle.
The frame is composited. The scene canvas is copied into a target of exactly the requested size and the mark is stamped on top, so branding is inside the video rather than in DOM that the capture never sees.
Frames are paced. captureStream(0) records nothing until asked, so every
frame in the file is one the renderer actually finished. Capturing at a rate
the renderer cannot hold samples some frames twice and misses the next, which
is what uneven duplication looks like: judder.
The honest limit. MediaRecorder timestamps by wall clock, so an export
runs in real time and no amount of pacing changes that. There is no in-browser
way to render slower than real time and still have the audio line up, short of
shipping a muxer — which is a dependency, and the standing rule says no. What
pacing can do is make every frame in the file the same distance from the last,
by counting animation frames rather than milliseconds — see FramePacer. A
device that cannot hold the requested rate then records a slower clip rather than
a juddering one, and the measurement in pacing says which it was.
Methods
lockDrawingBuffer
lockDrawingBuffer(width: number, height: number): voidPin the drawing buffer to an exact pixel size, ignoring CSS and DPR.
| Parameter | Type | Description |
|---|---|---|
width | number | |
height | number |
unlockDrawingBuffer
unlockDrawingBuffer(): void