Skip to content

Cloud rendering

View .mdllms.txt

framefields renders your project on its own GPUs, straight from git: no GPU, Docker or render farm on your side. Name a render once in framefields.json, then start it from the terminal, from code or from the dashboard. Long films split across several GPUs and come back as one file.

Terminal window
npx framefields render film --cloud --plan # Plan: 4 workers, 1 h 50 min of render work, ready in about 35 min, estimated $1.20.
npx framefields render film --cloud # Done in 34 min: output/film.mp4 (412.3 MB), 6620 GPU seconds, $1.18.
  • Push. The cloud renders the pushed commit. Uncommitted changes are not rendered (the CLI warns), and a commit that isn’t on the remote is refused.
  • An API key. Renders bill the account behind FRAMEFIELDS_API_KEY, the same key as the AI gateway. Create one at framefields.dev/dashboard/keys and add credit under Billing.
  • Private repos: connect GitHub once under Settings → Connections. Install the framefields GitHub App on all repositories, so repos you create later render without another step. It only gets read access, and each render gets a token for its own repo that expires in an hour. Public repos need nothing.
  • A render-ready project: a committed lockfile, assets pinned with framefields assets (or in Git LFS), and an entry that only builds the film. A project made with framefields init already is one; the full list is the project checklist.
  • Run from the project folder (where framefields.json is). In a monorepo, that folder is what renders.

framefields.json at the project root names what the project renders. npx framefields init writes film; add an entry for each cut.

{
"components": "src/components",
"renders": {
"film": {
"title": "Launch film",
"entry": "src/film.ts",
"export": "buildFilm",
"workers": "auto",
"output": "output/film.mp4"
},
"teaser": {
"title": "15 s teaser",
"description": "Vertical cut for socials",
"entry": "src/film.ts",
"export": "buildTeaser",
"codec": "vp9"
}
}
}
Field
entry The module that builds the composition, relative to the project root. Required.
export A Composition, or a function returning one. Default buildFilm.
title, description Shown in the dashboard and framefields renders.
args Passed to the export when it is a function.
select When the export returns several compositions, the one to render.
workers 1 (default), a number, or "auto" to split long films.
maxWorkers Upper bound for "auto".
codec h264 (default, MP4) or vp9 (WebM).
quality very_low, low, high or very_high (default).
output Where the CLI downloads the video.

Names use letters, digits, -, _ and .. npx framefields renders lists them; npx framefields check checks every one, npx framefields check teaser one.

Terminal window
npx framefields render film --cloud --plan # workers, time and estimated cost; renders nothing
npx framefields render film --cloud # render, then download to the render's output

Without --cloud, npx framefields render film renders the same named render on this machine, to the same file, and npx framefields preview film plays it in the browser: switching is the flag. Flags override the render’s fields (--workers 4, --codec vp9, --output). With a single named render, npx framefields render --cloud needs no name. A module renders without a manifest too: npx framefields render src/film.ts --cloud --export buildFilm.

--plan probes the film and prints the GPUs, time and estimated cost, then the command that renders it; it renders nothing. While rendering, the CLI prints one line per phase and progress every 10 seconds with the cost so far. --json prints the final status as JSON. Ctrl-C cancels the render; GPU time already used is charged.

import { renderCloud } from "framefields/cloud";
const result = await renderCloud({
render: "film",
outputPath: "output/film.mp4",
onProgress: (s) => console.log(s.status, s.progress.frames),
});

framefields/cloud needs no GPU. Options passed here override the named render’s; dryRun: true returns the plan and estimate, and signal cancels. A failed render throws a CloudRenderError with the worker’s code.

The CLI and renderCloud call the same API, with Authorization: Bearer $FRAMEFIELDS_API_KEY:

Terminal window
curl https://api.framefields.dev/v1/render \
-H "Authorization: Bearer $FRAMEFIELDS_API_KEY" -H "Content-Type: application/json" \
-d '{
"source": { "repo": "https://github.com/acme/launch-film", "ref": "main" },
"target": { "entry": "src/film.ts", "export": "buildFilm" },
"render": { "codec": "h264" },
"workers": "auto",
"dry_run": false
}'

GET /v1/render/:id returns its status (probing, rendering, stitching, then completed with output.url, or planned, failed, cancelled), progress, plan and cost so far. DELETE /v1/render/:id cancels it. Optional source.commit pins a commit and source.workdir a folder; optional name and title label it in the dashboard.

Connect GitHub once, on all repositories, then Renders → New render: pick a repo and branch, and the dialog lists the renders its framefields.json names, with their titles and descriptions. Picking one applies its GPUs and format. Plan shows GPUs, time and cost before anything renders. Repos without named renders still render: choose Another file in this repo and pick the module and export.

The Renders page lists every render, from the dashboard, the CLI or the API: live progress, cost so far against the estimate, Cancel, and the finished video.

workers: "auto" measures frame costs on one GPU first, then splits the film into as many chunks as stay efficient: a 5-minute film stays on one GPU, a 3-hour film spreads across up to 10. Each chunk renders on its own GPU, the audio renders once, and the chunks are joined without re-encoding. Effects with state (trails, datamosh, particles) replay earlier frames, so every chunk renders the same picture as a single render.

You pay for GPU seconds actually used. When a render starts, a credit hold is placed on your balance; once the film is planned the hold is raised to the estimate, and when it finishes you are charged the GPU time used and the rest is released. Failed and cancelled renders charge the GPU time they used. --plan (or Plan) costs the few seconds of GPU time the probe takes.

The error names the worker’s code. Fix the project, commit, push and render again; network errors, stalled workers and lost machines are retried by the API, and a straggling chunk gets a backup worker.

Code Cause Fix
REPO_NOT_FOUND, GIT_AUTH_FAILED A private repo the GitHub App can’t reach Connect GitHub with access to this repo
REF_NOT_FOUND, COMMIT_MISMATCH The branch or commit isn’t on the remote git push
LOCKFILE_MISSING, INSTALL_FAILED No committed lockfile, or it doesn’t install Commit a pnpm, npm or yarn lockfile matching package.json
ENTRY_NOT_FOUND, EXPORT_NOT_FOUND entry or export is wrong npx framefields check <name>
EXPORT_SIDE_EFFECT, COMPOSITION_BUILD_FAILED The entry renders or writes while building, or throws Keep film.ts to building; framefields check reproduces it
ASSET_NOT_FOUND, LFS_OBJECT_MISSING, LFS_POINTER_UNRESOLVED An asset wasn’t committed or its LFS object wasn’t pushed git lfs ls-files, git lfs push --all origin
ASSET_NOT_UPLOADED, ASSET_PRIVATE, ASSET_HASH_MISMATCH A pinned asset isn’t on the bucket, or the worker can’t read it Assets: when something fails
ENGINE_UNSUPPORTED The project’s framefields is too old to split Upgrade framefields, or use --workers 1
RENDER_TIMEOUT, RENDER_OOM One GPU can’t finish its part --workers auto, or more workers
insufficient_credits The balance doesn’t cover the hold Add funds under Billing

All worker codes: Render on a server.