Skip to content

Exporting your video

Pick what the render writes: an MP4, a GIF, an image sequence, or an alpha-capable overlay. Set Video.export to one of the four modes and Fluvie encodes that container. Here are all four:

Export sharable() => const Export.mp4(quality: Quality.max); // H.264 MP4, CRF 14
Export loopingThumb() => const Export.gif(fps: 12); // animated GIF at 12 fps
Export forCompositing() => const Export.imageSequence(); // one PNG per frame
Export overlay() => const Export.transparent(); // WebM with an alpha channel

With no export, a render writes an MP4 at the default quality. The rest of this page covers the four modes, the poster frame, and the command-line renderer.

Export.mp4(quality:) writes an H.264 MP4. The quality picks the encoder’s constant-rate factor (CRF), where a lower CRF means a bigger file and less compression:

Export.mp4(quality: Quality.low), // CRF 28, smallest file, visible compression
Export.mp4(quality: Quality.medium), // CRF 23, a rough-cut trade-off
Export.mp4(quality: Quality.high), // CRF 18, the default for published videos
Export.mp4(quality: Quality.max), // CRF 14, near-lossless, the largest file

Quality.high is the default, so const Export.mp4() writes a published-grade file. Reach for Quality.low for quick draft renders and Quality.max for an archival master.

Export.gif(fps:) writes an animated GIF. The fps samples the frames, since a GIF rarely needs the full frame rate. A lower fps makes a smaller file:

Export.gif(fps: 15), // the default sample rate
Export.gif(fps: 12), // a smaller, choppier loop

The encoder builds an optimized 256-color palette from your frames in one pass, then maps the frames onto it with dithering, so a GIF keeps its color and stays small. A GIF carries no audio.

Export.imageSequence() writes one lossless PNG per frame, named frame_000000.png, frame_000001.png, and so on. Reach for it when a compositing pipeline downstream wants individual frames rather than a container:

const Export.imageSequence(); // one PNG per frame, into the output directory

The sequence carries no audio. Each still is lossless, so the pipeline starts from the exact captured pixels.

Export.transparent() writes a WebM with an alpha channel, so the video can layer over other footage. The captured RGBA alpha is preserved end to end:

const Export.transparent(); // VP9 WebM with a yuva420p alpha plane

Reach for it when you render a lower-third, a logo sting, or a caption pass that sits on top of a clip in another editor. An alpha-capable overlay carries no audio. ProRes .mov with alpha is forthcoming; WebM ships today.

Video.poster names a Time, and the render grabs that one frame as a still thumbnail alongside the main output. Set it on the same Video as the export:

Video exportedReel() => Video(
size: VideoSize.reels,
export: const Export.mp4(quality: Quality.max), // near-lossless, CRF 14
poster: const Time.seconds(1.5), // the thumbnail frame
scenes: [
Scene.centered(
duration: const Time.seconds(3),
background: Background.color(const Color(0xFF0E1116)),
child: const Text('Exported', style: TextStyle(fontSize: 72, color: Color(0xFFE6EDF3))),
),
],
);

The poster is a second output from the same frames, so it costs one extra encode of one frame. Pick a Time that lands on a representative moment, for example 1.5 seconds into a 3 second card.

fluvie render captures a composition and encodes it, with no app to open. Point it at the file and name an output:

Terminal window
fluvie render ./lib/my_video.dart --out hello.mp4

It calls the file’s top-level Video build(), generates a capture harness under <project>/.fluvie/, and encodes the frames. The flags map onto the export modes above:

Terminal window
fluvie render ./lib/my_video.dart --out reel.mp4 --aspect reels --quality high
fluvie render ./lib/my_video.dart --out clip.gif --format gif
fluvie render ./lib/my_video.dart --out frames/ --format imageSequence
fluvie render ./lib/my_video.dart --out overlay.webm --format transparent
fluvie render ./lib/my_video.dart --out hero.mp4 --poster 1.5s

The flags:

  • --out <file> sets the output path. It is required.
  • --entry <name> names the top-level function returning the Video. It defaults to build.
  • --aspect <name> picks the aspect: reels, square, landscape, or portrait45. With no --aspect the composition renders at its declared size; pass an aspect to re-frame it.
  • --quality <name> picks the MP4 quality: low, medium, high, or max.
  • --format <name> picks the export mode: mp4, gif, imageSequence, or transparent. It defaults to mp4.
  • --poster <time> writes a poster still from a Time string, for example 1.5s, 30f, or 500ms.

A bad enum value exits with code 64 and names the valid set, so a typo fails fast rather than rendering the wrong thing. The rest: --frames N for a draft render, --project <dir>, --ffmpeg <path>, --keep-temp, and --verbose.

Rendering a .dart file captures every frame fresh. Pass --cache to reuse cached frames instead:

Terminal window
fluvie render ./lib/my_video.dart --out hello.mp4 --cache

It is off by default for a reason. The render digest keys on the config and the composition key, never on the composition itself, so an edited file with the same size and frame count would replay its old frames and you would render yesterday’s video. Reach for --cache when you are re-rendering an unchanged file at a different quality or format, and leave it off while you are editing.

A project that still keeps a registry-based capture harness renders by key:

Terminal window
fluvie render 01_hello_video --out hello.mp4

That path is unchanged, and --no-cache still bypasses the cache for it. To see every key such a project can render:

Terminal window
fluvie list

It prints one key per line. A file-based project needs no keys, so it needs no list.

  • Templates: render one definition per data row.
  • Multi-aspect: one definition rendered to reels, square, landscape, and portrait.