Migrating from Revideo
Revideo is a fork of Motion Canvas built for rendering from code: scenes with variables, a render function and a player. Its scenes port to oxframe the same way as Motion Canvas scenes; this page covers what Revideo adds on top.
Scenes: the Motion Canvas guide applies
A Revideo scene is a Motion Canvas generator with a name: makeScene2D('card', function* …). Nodes, signals, all, waitFor and the rest map as in Migrating from Motion Canvas: yield* becomes .await, refs become the handles view.add returns, and the scene's name
is the name of the async fn.
What Revideo adds, in oxframe
| Revideo | oxframe |
|---|---|
useScene().variables.get('name', 'Ada') | ordinary Rust: read the value from the environment or a file in the scene, or build the
project in main from it |
renderVideo({ projectFile, variables, settings }) | NAME=Grace oxframe render --out welcome.mp4; a loop in a shell script or CI
renders one video per input |
| rendering in headless Chromium | no browser: oxframe draws frames itself, on the GPU or with --cpu |
| parallel rendering in workers | oxframe render --jobs 8: 2-second segments in parallel, the same bytes as one
job |
<Audio>, <Video> | sound(…).play(), Audio::track(…), Video (feature video) |
| the player for your own site | no published player package yet: share the rendered video or a playground link |
The same scene in both
A welcome title with a name passed in from outside, rendered to a file.
Revideo
// src/scenes/card.tsx
import {Txt, makeScene2D} from '@revideo/2d';
import {createRef, useScene, waitFor} from '@revideo/core';
export default makeScene2D('card', function* (view) {
const name = useScene().variables.get('name', 'Ada');
const title = createRef<Txt>();
view.add(<Txt ref={title} text={() => `Welcome, ${name()}`} fontSize={96} fill={'white'} opacity={0} />);
yield* title().opacity(1, 0.5);
yield* waitFor(1.5);
});
// render.ts
import {renderVideo} from '@revideo/renderer';
await renderVideo({
projectFile: './src/project.ts',
variables: {name: 'Grace'},
settings: {outFile: 'welcome.mp4'},
}); oxframe open it in the playground
use oxframe::prelude::*;
#[oxframe::scene]
pub async fn card(view: View) {
// Revideo's variables: here the environment (or a file you read).
let name = std::env::var("NAME").unwrap_or_else(|_| "Ada".into());
let title = view.add(Txt::new().text(format!("Welcome, {name}")).display().opacity(0.0));
title.opacity().to(1.0, 0.5).await;
wait_for(1.5).await;
}
pub fn project() -> Project {
Project::new("welcome").scene(card())
}- The variable becomes
std::env::var("NAME")with a default, so the scene still runs when nothing is passed — in the editor and in the playground too. renderVideobecomes the CLI:NAME=Grace oxframe render --out welcome.mp4.
Porting a project
- Port the scenes as in the Motion Canvas guide.
- Move each variable into Rust: the environment for one value, a JSON or CSV file for many (read
it with
std::fsandserde). - Replace the render script with
oxframe renderin CI;--cpuruns on any runner. - Run
oxframe checkfor each input you render.
With an agent: the motion-canvas-to-oxframe skill covers
Revideo scenes as well; install it with npx skills add oxygenframe/oxframe-sdk.