Skip to main content
The API supports all 26 node types with the same execution semantics as the visual editor. Composition-heavy nodes (voiceover, captions, audio mixing, clip selection) accumulate composition metadata server-side, and a single render at the end of the run assembles the final MP4.
One render per run, no matter how many audio/caption/clip layers are present. You pay for the generations that produce the assets, plus a single final render.

Full support matrix

How DOM-dependent nodes work server-side

These seven node types rendered inline in the browser. In the API they accumulate layer metadata that gets consumed by the final render:
The executor calls ElevenLabs TTS, polls until done, and appends the audio URL to the artifact’s audioTracks array with the correct offset/duration. At final render, every track is mixed over the video.Options:ElevenLabs voice IDs (work with both fal-elevenlabs-v3 and fal-elevenlabs-turbo):Roger, Sarah, Laura, Charlie, George, Callum, River, Harry, Liam, Alice, Matilda, Will, Jessica, Eric, Bella, Chris, Brian, Daniel, Lily, Adam, Bill.MiniMax Speech voice IDs (work with fal-minimax-speech):male-qn-qingse, male-qn-jingying, male-qn-badao, presenter_male, audiobook_male_1, female-shaonv, female-yujie, female-chengshu, presenter_female, audiobook_female_1.Any unrecognized voice ID is silently rejected and the node no-ops — the rest of the run still executes but the voiceover track is missing from the final mix.
The executor transcribes the video (word-level timestamps) and stores the word array + caption style on the artifact. Animated captions are rendered as a text layer at the final composition step — no rasterization at the node level.Two ways to style captions — both go under model_overrides[step]. Mix and match: overrides win field-by-field over a style ID.
  1. _caption_style_id — a cs_… blob produced by the Caption Designer. Self-contained, no DB lookup, no expiry. The fastest path when you’ve already designed a look you want to reuse.
  2. _caption_style_overrides — a partial CaptionStyle object (see fields below). Any field you omit falls back to the default style.
Available fonts — the renderer preloads a fixed set of fonts. Any other value falls back to a system font (usually unreliable), so stick to this list unless you self-host a font:Display: Anton, Bebas Neue, Oswald, Archivo Black, Bowlby One, Bangers, Luckiest Guy, Permanent Marker. Sans: TikTok Sans, Inter, Poppins, Montserrat, Nunito, Open Sans, Raleway, DM Sans, Space Grotesk, Fredoka. Serif: Lora. Mono: Geist Mono, Courier New. Script: Comic Neue, Pacifico, Caveat.The font-family string may include fallbacks, e.g. "Anton, Impact, sans-serif".Example:
The executor searches the royalty-free track library, picks the first matching track, and stores it in the artifact’s audioOverlay.backgroundAudio field. It’s added as a background bed at final render.Options (under model_overrides[step]):
Generates music, polls for completion, and appends the track to audioTracks. Same plumbing as voiceover — consumed at final render.Engine — set via engine_1 on the step. Treat engine IDs as opaque tokens; the canonical list is returned by GET /flows/:id for any saved flow. Today’s IDs:Options:
Takes a user-supplied audio URL (from inputs.media[step] with type: "audio", an upstream media_input, or the literal _audio_url field) and adds it as a track. No generation, no polling.Options:
The source video is transcribed, then an LLM picks the top-N viral segments from the timestamped transcript and emits a clipTrims array. At final render, the source video is trimmed to exactly these windows and stitched.Options:The LLM is hard-pinned to clips of 15–60 seconds; values outside that range are dropped before stitching. If transcription fails or the LLM returns nothing parseable, the node falls back to a single 60 s clip from the start of the source video.
Runs image generation N times with angle-prefixed prompts and the same reference image. Emits a sceneImages array identical in shape to what a split → image_generation → collect would produce, so downstream image_to_video nodes see a uniform input.Options:Suggested _selected_angles values (these are the chips the visual editor exposes — server treats them as free-text suffixes, so any descriptive string works):Front, Left Side, Right Side, Back, Top, Bottom, Isometric, Close-up.The executor templates each angle into "<base prompt> — <angle> angle, consistent subject and lighting." so values that read naturally in that sentence give the best results.

Final render composition

After the last step executes, the worker assembles the final composition by walking every step’s artifact in reverse order:
1

Pick clips

Last-written clipTrims. Falls back to stitching sceneVideos if no explicit trims. Falls back to a 60-second slice of the last videoUrl if neither is present.
2

Pick caption words and style

Last-written captionWords + captionStyle.
3

Pick audio overlay

Last-written audioOverlay — the background music bed.
4

Union of audio tracks

All audioTracks arrays concatenated. Voiceover + music + user overlays all layer together.
5

One POST /api/render call

The worker POSTs the composition spec to the Vercel render endpoint, which triggers Remotion Lambda. Polls /api/render-progress until the MP4 is ready, stores the URL on the run.
This is exactly the logic the browser’s export step uses — same code path, same output MP4.

Checking which nodes a flow uses

Unsupported node types

The only way to get a node-support error is with an unknown node type (one not in the list above). This fails with error_code: "unknown_node_type" at validation time, before credits are reserved:
This only happens if you pass an inline flow_schema with a handwritten node type. Every type produced by the visual editor is supported.