--scene.
What a scene is
A scene is a folder. The file inside depends on the engine.
The agent can put its own SVG drawings in the folder and use them with
<img src="cook.svg">.
What vfrey supplies
vfrey writes these intoDIR/vfrey/ when the scene is made and again when it renders. Do not edit them. They are replaced each time.
A Remotion scene gets the same timing and art, and imports its helpers from
@vfrey/scene instead of vfrey.js.
The scene can use any of it or none of it.
What vfrey fixes
These do not change, whatever the scene says.- The video is 1080×1920 at 30 fps. It lasts as long as the voice, plus 0.3 seconds.
- vfrey burns the
AI-GENERATEDlabel on top after the engine renders. Nothing a scene draws can hide it. - The network is blocked while a scene renders. A request to the outside gets a warning on the run. It does not hang. A scene cannot load a CDN, so use the local files.
- A scene folder can be 50 MB at most. SVGs are sanitized.
- vfrey copies the scene for each job. It keeps the copy with the run, in the data folder’s
scenes/JOB_ID/(.vfrey/scenes/JOB_ID/in a project).
The workflow
1
Start from a starter
my-scene/index.html and the vfrey/ files. Add --script script.json to time the scene from your script; without it, vfrey/timing.json comes from a sample script and says "placeholder": true. Add --engine remotion for index.tsx. --engine also takes framey (the default) and hyperframes. The starter is a short example. Replace it.2
Edit
The agent designs the picture for the idea in front of it.
3
Look at a frame
--script: without it the sample script times the frame. Until a voice exists, the timing is estimated from your script. Once a run has made the voice for that script, the same command times the frame by the real voice, so beats land where they will in the final render (the Timing: line says which). Open it, fix the layout, and check a second moment such as --frame 9.4
Make the video
Scene: agent-written. --json has a scene field.5
Look again after the first render
After the first full render, re-check the frames at the beat times in
vfrey/timing.json (beats[].start). Run the same --frame command again: the preview now uses the real voice and can differ from the first estimate. Fix what moved, then render again.render --scene DIR without --frame renders the whole scene to an MP4. Pass --engine whenever you use a scene, so the scene file and the engine match.
Look before you change, and edit by eye
Two commands help when you change an existing scene. Both are for HTML scenes only.npx vfrey scene inspect DIRfinds the exact element, CSS rule, and GSAP tween (with file and line) behind the thing you name, so a “change just this” edit touches only that.--at SECONDSseeks the timeline.--selector CSSor--text "words"narrows it.--script FILEsets the text.--jsonprints it for a machine.npx vfrey scene studio DIRopens the scene in a visual editor (timeline, code, and live preview) and saves your edits back intoDIR. It runs on your machine at127.0.0.1, on a free port from 47000, until you press Ctrl+C.--port Npicks the port.--no-browserprints the address only.
Blocks
For a lower third, a chart, a chat card, or an overlay, the agent can copy a ready-made block into the scene withnpx vfrey scene add BLOCK DIR and time it with vfrey.block. See Scene blocks.
Transitions
To cut between two shots with a shader, such as a glitch, a light leak, or an iris, an HTML scene callsvfrey.transition. There are 15 types, listed by npx vfrey scene transitions. A Remotion scene does not support them. See Shader transitions.
An HTML example
This is a short scene forvfrey-framey. A dot grows when the second line is spoken, and the captions follow the voice.
Keep every visible thing a function of timeline time. Do not use
Date.now or unseeded random, or a frame will differ from render to render.
A Remotion example
This is the same idea forremotion. Use npx vfrey scene init my-scene --engine remotion to start.
The timing data
vfrey.timing and useTiming() return the same shape, in seconds.
durationSec: the length of the voice.words:{ i, text, start, end, line }for each word.lines:{ i, text, start, end, firstWord, lastWord }for each line.beats:{ i, role, text, caption, start, end, firstLine, lastLine }for each beat.
For agents
- Design the picture for the idea. Do not copy a starter or an example.
- Run
scene init DIRfor a start, then replace it. - Look at a frame with
--framebefore you make the video. Check a second moment. - Pass
--enginewith--scene. Say whether the scene was agent-written or the default template. - The scene is checked before and after the render. A failed check has a
Fix:line: do it. See Quality checks. - If a run stops with a
Fix:line, relay it. Do not switch engines quietly.