Skip to content

Videola 0.3.0 — nesting, keyframed transforms, agents that can see

Choose a tag to compare

@github-actions github-actions released this 08 Aug 21:47

Compound clips, keyframable transforms, agents that can see their own work, and a Docker image that
serves more than static files.

New in this release

  • Compound clips. Fold a selection into one clip. That the picture does not change is proven
    six ways, each against the render before the fold: the whole frame buffer at tolerance zero,
    the draw list at sixteen instants, the source mapping in Rust at 1/60 s steps, the recorded GPU
    batch replayed, and the audio render sample for sample — plus a counterweight so "the compound
    drew nothing" cannot pass.
  • Keyframable transforms. A clip's position, scale, rotation and anchor animate over time,
    resolved in the Rust core like every effect parameter, so the preview and the export cannot
    disagree. Clip::keyframes had existed since the first schema with nothing reading it.
  • Track and project effect chains have an address in the model, and the master volume has a
    command. Nothing renders or sounds them yet — that is the next step, and it is now unblocked.
  • project_getFrame and project_getAudioPeaks. An agent can look at what it just cut. The
    still comes out of the same wasm core, draw list and WebGL2 compositor the editor draws with, in
    headless Chrome, so it cannot show something the editor would not.
  • Autosave. Project state into OPFS every 30 s — not a .videola, because the media are
    already there under their content hash. The banner offers, never takes.
  • Docker that does something. One Node process serves the editor, the HTTP API, the MCP server
    and the CLI. nginx is gone. It refuses to start on a public address without VIDEOLA_TOKEN and
    says why.
  • A CLI: videola apply | describe | validate | schema.
  • Auto-update wired for the desktop builds, injected by CI only when both signing key halves
    exist.

Fixed along the way

Media imported through the API got a library entry with no duration, no dimensions and no channel
count — which silently dropped every such clip from the draw list and from the audio. A get_frame
on a server-imported video would have shown the background and reported success. Both hosts now
build the entry through the same function.

What is still missing

No masks, motion paths, motion blur or LUT import. No EQ or compressor. No noise reduction, ducking
or beat detection. A compound clip is flattened rather than isolated, so opacity, effects and blend
apply per nested clip. The magnetic timeline is deliberately absent — the useful half is ripple
delete and trim, and the rest would change an overlap rule that transitions, layering and roll/slide
all depend on. FFmpeg is not bundled.

How it is checked

385 Rust tests, 1022 JavaScript tests, and five harnesses needing only an installed Chrome: 198
pixel checks against a real WebGL2 driver, 35 export checks that hand the written file to ffprobe
and ffmpeg, 52 against real browser layout, 167 driving the built application on desktop, tablet
and phone viewports, and one driving the built server bundles over real stdio and HTTP.

The application harness is not a CI gate: it depends on font metrics, core count and devtools
timing. Loosening what it asserts would be worth less than the assertions.

Installers

Windows NSIS, Linux deb and AppImage, macOS DMG — all unsigned. Android and iOS are wired but
skipped without signing keys.