Skip to content

SimonErich/fluvie

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

269 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fluvie

You write widgets. Fluvie shoots the film.

pub package CI coverage License: MIT maintained with melos

Fluvie is a Flutter package that turns widget code into real video files. You build a video the way you build a screen, with Scenes and the Flutter widgets you already know, you say how long each thing lasts, and Fluvie renders every frame and encodes it into an MP4 (or a GIF, or an image sequence) with FFmpeg. No video editor, no manual timeline, no After Effects.

Think of it as a tiny film studio that already speaks Flutter: you direct, Fluvie handles continuity, and FFmpeg runs the projector. No timeline to scrub, no keyframe spreadsheet, no 2am debugging because frame 412 is one pixel off.

  • Declarative. Compose Scenes and elements like any Flutter screen.
  • Cacheable. The frame cache keys on content, so caching, golden tests, and batch rendering just work.
  • Headless. Render from the CLI, an HTTP API, or an MCP server. No display needed.
  • Conversational. Describe a video in plain language; a model writes editable Fluvie code (or a spec) and renders it.

Quick start

This is lesson 01, in full: about 16 lines of widgets become a 4 second clip.

The Hello, Fluvie clip Fluvie renders from this code
import 'package:flutter/material.dart' hide Animation, Clip, Image, Tween;
import 'package:fluvie/fluvie.dart';

Video helloVideo() => Video(
  size: VideoSize.square,
  poster: 1.seconds,
  scenes: [
    Scene(
      duration: 4.seconds,
      background: Background.gradient(
        const [Color(0xFF1A2980), Color(0xFF26D0CE)],
      ),
      children: [
        const Text(
          'Hello, Fluvie',
          style: TextStyle(color: Colors.white, fontSize: 72),
        ).animate([Animation.fadeIn(), Animation.pop()]),
      ],
    ),
  ],
);
dart pub global activate fluvie_cli
fluvie init --dir my_reel                          # a composition, an assets/ folder, a pubspec
cd my_reel && flutter pub get
fluvie preview ./lib/example_video.dart                # live, hot-reloading
fluvie render ./lib/example_video.dart --out reel.mp4  # the file

A Fluvie project is a composition file, an assets/ folder, and a pubspec. There is no app, no harness, and no registry: preview and render take the .dart file and generate whatever they need. The file exposes a top-level Video build(). You do not need to install FFmpeg: the first render downloads a pinned, checksum-verified build and caches it (run fluvie ffmpeg install to fetch it ahead of time, or point --ffmpeg / FLUVIE_FFMPEG at your own). The getting started guide walks through it. Full source: examples/gallery/lib/lessons/01_hello_video.dart.

See what it can do

These snippets are trimmed to the shape of the thing; each links to its full, runnable lesson. The clips beside them were rendered by Fluvie.

Charts that reveal themselves

A counter, then a bar, line, and donut chart animating in
Video chartsVideo() => Video(
  size: VideoSize.square,
  scenes: [
    Scene(duration: 3.seconds, children: [
      Chart.bar(
        data: {'Q1': 42, 'Q2': 58, 'Q3': 71, 'Q4': 96},
        reveal: 1.seconds,
      ),
    ]),
    Scene(duration: 3.seconds, children: [
      Chart.line(data: {'W1': 12, 'W2': 26, /* ... */}, reveal: 1500.ms),
    ]),
    Scene(duration: 2500.ms, children: [
      Chart.donut(
        data: {'Search': 48, 'Social': 27, /* ... */},
        reveal: 1.seconds,
      ),
    ]),
  ],
);

Full source: examples/gallery/lib/lessons/07_charts.dart.

Layers and scenes, set to a beat

Several scenes play one after another with a cross-fade. Each scene stacks layers: a full-frame effect under the content, a chip that pops on the music beat, captions over the top.

A vertical reel: layered scenes, a beat-synced pop, captions, an outro
Video reel() => Video(
  size: VideoSize.reels, // 9:16
  transition: Transition.crossFade(0.4.seconds),
  audio: [Audio.music('beat.wav', track: music)],
  captions: const Captions.fromSrt('captions.srt'),
  scenes: [
    Scene(children: [
      Box(/* ... */).animate([
        Animation.pop(at: Trigger.beat(track: music)),
      ]),
      const Text('On the beat').animate([Animation.fadeIn()]),
    ]),
    Scene(children: [
      const ColoredBox(/* ... */).animate([Animation.grain(0.12)]),
      Counter(to: 12000, duration: 1500.ms),
    ]),
    Scene.centered(child: /* ... outro ... */),
  ],
);

Full source: examples/gallery/lib/lessons/12_the_kitchen_sink.dart.

Examples

Thirteen runnable lessons live in examples/gallery/lib/lessons/, from "Hello, Fluvie" to the kitchen sink. Try them at demo.fluvie.dev: write and render a Video in the Playground, or describe one in the AI Assistant and let a model write and render the code. Or run the gallery locally:

flutter run --enable-impeller   # from the repo root; Impeller for the live preview

Beyond the gallery, examples/ has a small kitten-themed app for each rendering path: a CLI quickstart, a Linux desktop studio, an Android on-device app, an in-browser maker, and a server-render studio. See Example apps.

Use Impeller (--enable-impeller) whenever you run or preview Fluvie on the desktop. It is Flutter's current renderer and draws shaders, grain, and blends the way the final video does. The headless render pipeline already handles this for you. See Troubleshooting.

Packages

Most people only need fluvie. The rest are there when you want to render in CI, on a server, or from an AI assistant.

Package Role pub.dev
fluvie The library. Describe a video, render an MP4. pub
fluvie_cli Headless renderer. Capture with flutter test, encode with FFmpeg. pub
fluvie_lints Lint rules that catch timing and layering mistakes. pub
fluvie_validate Check a Video snippet before you render it: the analyzer plus the lint rules, in-process, never executed. pub
fluvie_ai Author a video from a prompt. A model writes a spec. Built on ai_abstracted. pub
fluvie_server One self-hostable server: render API (local or S3), MCP server, and a docs helper, plus a web-safe client. pub
fluvie_mobile_encoder Render to MP4 fully on-device on Android and iOS, no FFmpeg. pub
fluvie_web_encoder Render to MP4 fully in the browser with ffmpeg.wasm, opt-in. pub

Rendering modes by platform

The same Video renders three ways. Pick by where the encode should run: on your own machine, on a server you call, or on the user's own device.

Platform Local (FFmpeg binary) Server API On-device
Desktop (Linux/macOS/Windows) fluvie_cli fluvie_server client ✅ local FFmpeg (the CLI itself)
Android fluvie_server client fluvie_mobile_encoder (native)
iOS fluvie_server client fluvie_mobile_encoder (native)
Web (browser) fluvie_server client fluvie_web_encoder (ffmpeg.wasm, opt-in)
  • Local runs FFmpeg on your own machine. It is the full feature set (audio, GIF, transparency) and the reference platform for golden images. This is the CLI and CI path.
  • Server API keeps the client thin: the app sends a spec, a render server runs FFmpeg, the app gets a file back. It works on every platform and keeps app bundles small. Use it when you do not want to ship an encoder.
  • On-device renders without a server, so the video never leaves the device. Mobile uses the platform's native encoder; web uses ffmpeg.wasm. The frames are captured by Fluvie's own pipeline, so they match a desktop render; only the encode edge differs (see each guide for the trade-offs).

Combining platforms. One Flutter app can run on mobile and web and render on-device on both: choose the renderer per platform behind a conditional import (fluvie_mobile_encoder on mobile, fluvie_web_encoder on web), passing the same Video. On the web you trade bundle size for the ffmpeg.wasm payload; choose the Server API instead to keep the bundle light.

Audio works everywhere too. Declare Audio.music/Audio.sfx once and it mixes on every renderer — looping beds, fades, trims, and multi-track amix — with audio opt-in on-device. The web has no local-file source (bundle as an asset or fetch from an allowlisted URL). See the full audio support by platform table.

The ecosystem

The library is the whole show. These hosted pieces are the lobby, the trailers, and the box office.

Where What you get
fluvie.dev The front of house: what Fluvie is, in one screen.
docs.fluvie.dev The manual: getting started, guides, a cookbook, and the full reference.
demo.fluvie.dev The screening room: try Fluvie live in the browser and render a clip.
mcp.fluvie.dev The hosted MCP server, so an AI assistant can make videos with Fluvie.

Documentation

Start at docs.fluvie.dev:

  • Getting started: install, your first video, the core ideas.
  • Guides: animation, audio, charts, code scenes, theming, exporting.
  • Cookbook: short, copy-paste recipes for one task each.
  • AI and MCP: author from a prompt, run it locally, or point Claude at it.
  • Reference: the whole public surface on one page.

What goes in a video

Everything you can paint with Flutter, plus the things a video needs:

Kind What you get
Text Text, Typewriter, Counter, Markdown
Code Code, CodeReveal (animated diffs), Terminal
Media Image, Clip (embedded video), Snapshot, DeviceFrame
Data Chart (bar, line, area, pie, donut, scatter), Bars
Diagrams and web Mermaid, WebView, Html
Annotations Shape, Arrow, Connector, Callout, Spotlight, LowerThird, TitleCard
Motion and effects 60+ animation presets, Stagger, Camera, shaders, particles, grain
Audio Audio (music and sfx), beat detection, Captions (SRT and VTT)
Look Background (color, gradient, image), FluvieTheme, multi-aspect export

What you can make with it

Use case For example
Product demos feature walkthroughs, onboarding clips, changelog videos
Social reels 9:16 vertical shorts for TikTok, Reels, and Shorts
Explainers tutorials and concept animations
Data stories stat highlight reels and animated reports
Developer content code walkthroughs, terminal demos, release notes
Branding title cards, intros, and lower thirds

Troubleshooting

Text renders as solid white boxes. That is Flutter's Ahem test font, which draws every glyph as a filled box, so each word looks like a bar. It means the real fonts were not loaded before the frames were captured. Fluvie's own render pipeline (the CLI, the API, and the Docker image) loads them for you, including the harness it generates for each render. If you host renderVideo yourself, load the app fonts and pass defaultFontFamily before rendering.

Shaders, grain, or blends look off in the rendered file. Capture with Impeller, Flutter's current renderer:

fluvie render ./lib/my_video.dart --out out.mp4 --enable-impeller

The flag passes --enable-impeller to flutter test, so the capture rasterizes with Impeller instead of the default tester backend. An ordinary render does not need it; reach for it when a shader or a blend mode looks wrong.

Contributing

Pull up a chair. Read CONTRIBUTING.md, install the hooks once, and keep the gate green:

dart pub get && dart run melos bootstrap
bash .githooks/install.sh
CI=true dart run melos run gate

Community

License

MIT © 2026 Simon Auer.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages