Automate Rendering

Preview and render a local Editframe project, verify API access, and submit a cloud render from the command line.

Use the CLI when the source of truth is a local Editframe project. The same project can be previewed and rendered to a local MP4, then packaged and submitted to the Editframe cloud for server-side rendering.

Prerequisites

  • Node.js 22 or later
  • An HTML or React project created with the Editframe scaffold
  • FFmpeg on your PATH for the local render command
  • An Editframe API token for auth and cloud-render

The cloud command reads EF_TOKEN from the environment. Keep the token out of source files and shell history where possible.

1. Create or check the project

Create an HTML project with the supported non-interactive flags:

bash
npm create @editframe@latest -- html -d my-video -y --skip-skills
cd my-video

The scaffold creates index.html, vite.config.ts, package.json, and src/. Edit the <ef-text> in index.html so the composition has a visible result:

html
<ef-text duration="5s" class="text-white text-4xl">Hello from automation</ef-text>

Run the preview when you want to inspect the composition before submitting it:

bash
npm start

2. Produce a local output

From the project root, render the default index.html to an explicit output path:

bash
npx editframe render -o output.mp4
ls -lh output.mp4

The command uses headless Chrome to capture the composition and FFmpeg to encode the MP4. A non-empty output.mp4 is the local verification that the composition and render dependencies are working.

3. Verify the API token

Replace the placeholder below with your real Editframe token (in the form ef_<secret>_<key>), then ask the CLI to fetch the organization data associated with it:

bash
export EF_TOKEN="ef_secret_exampleKey"
npx editframe auth

The command prints the API key name when authentication succeeds. The CLI accepts -t, --token as an alternative to EF_TOKEN, but using the environment variable keeps it consistent across the cloud-render command.

4. Submit a cloud render

The Vite scaffold is the bundled-project path. It builds the project, syncs processed files from src/assets/.cache when present, reads the composition metadata, creates a render job, and uploads the bundled assets:

bash
npx editframe cloud-render .

The command requires index.html at the project root. On success, the output includes Render assets uploaded and the created render object with its id and status. The command submits the job; use the returned id in the API or Editframe dashboard to monitor and retrieve the finished MP4.

For a project that already contains a self-contained index.html, the same command works from that directory. The optional strategy flag currently accepts v1:

bash
npx editframe cloud-render . --strategy v1

5. Track and download with the API

If a server process needs to own status polling and file delivery, install the API package in that server project:

bash
npm install @editframe/api

Save the following as scripts/download-render.mjs, then run it with the same token used by the CLI and the id printed by cloud-render:

bash
export EF_TOKEN="ef_secret_exampleKey"
export EDITFRAME_RENDER_ID=render_id_from_cloud_render
node scripts/download-render.mjs
js
// scripts/download-render.mjs
import { writeFile } from "node:fs/promises";
import {
  Client,
  downloadRender,
  getRenderInfo,
  getRenderProgress,
} from "@editframe/api";

const token = process.env.EF_TOKEN;
const renderId = process.env.EDITFRAME_RENDER_ID;
if (!token) throw new Error("EF_TOKEN is required");
if (!renderId) throw new Error("EDITFRAME_RENDER_ID is required");

const client = new Client(token);
console.log(`Render status: ${(await getRenderInfo(client, renderId)).status}`);

const progress = await getRenderProgress(client, renderId);
for await (const event of progress) {
  if (event.type === "progress") {
    console.log(`${Math.round(event.data.progress * 100)}%`);
  }
}

const finalInfo = await getRenderInfo(client, renderId);
if (finalInfo.status !== "complete") {
  const detail = finalInfo.error?.message ? `: ${finalInfo.error.message}` : "";
  throw new Error(`Render ended with status ${finalInfo.status}${detail}`);
}

const response = await downloadRender(client, renderId);
await writeFile("output.mp4", Buffer.from(await response.arrayBuffer()));
console.log("Wrote output.mp4");

The API client receives the token explicitly. The CLI and this server example therefore use the same EF_TOKEN value. The render status moves through created, pending, rendering, complete, or failed; the final status check prevents a failed render from being downloaded as if it succeeded.

Troubleshooting

  • EF_TOKEN must be set or supplied as command line argument means the auth or cloud command did not receive a token. Export EF_TOKEN in the same shell, or pass -t ef_secret_exampleKey.
  • cloud-render expects index.html at the directory root. Run it from my-video, pass . explicitly, and check that the Vite build completed before investigating the render job.
  • A local render failure about Chrome or FFmpeg is local tool setup. The local command needs both; confirm Chrome is detected and ffmpeg -version succeeds on PATH.
  • If a project uses local media, keep the files under src/assets and let the scaffold's asset cache be generated before cloud rendering. The command syncs src/assets/.cache; missing source files cannot be uploaded.

Next steps