Video vibe coding framework that is actually fast.
fframes-intro-1080p.mp4
fframes is a framework for rendering videos from code. Assuming you are not going to write the thousands lines of code fora video yourself our goal is quick and efficient iteration speed for your AI agent, great and useful real time preview for you, and fastest in industry rendering speed (we are over 30x faster than remotion).
Start with a skill and ask your favorite AI agent to make something you want. Then iterate.
npx skills add https://fframes.studioEvery frame is an SVG tree returned by a Rust function, written with the svgr! macro. From
examples/hello-world, shortened: a square moves along a timeline and a line
of text prints the current frame.
Show the code
impl Video for HelloWorldVideo<'_> {
const FPS: usize = 30;
const WIDTH: usize = 1920;
const HEIGHT: usize = 1080;
fn duration(&self) -> fframes::Duration<'_> {
fframes::Duration::Seconds(30.)
}
fn audio(&self) -> AudioMap<'_> {
AudioMap::none()
}
fn render_frame(&self, frame: Frame, ctx: &FFramesContext) -> fframes::Svgr<'_> {
fframes::svgr!(
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1920 1080"
width={ctx.current_video_size.width}
height={ctx.current_video_size.height}
>
<rect
x="400"
y="400"
width="200"
height="200"
fill="blue"
transform={frame.animate(fframes::timeline!(
at 0., animate Transform::translate(0, 0) => Transform::translate(200, 480), Easing::Linear,
at 2. => 6.0, animate Transform::translate(200, 480) => Transform::translate(750, -400), Easing::Linear,
at 6.0 => 10.0, animate Transform::translate(750, -400) => Transform::translate(1310, 480), Easing::Linear,
))}
/>
<text
x="100"
y="440"
font-family="JetBrains Mono"
font-size="74"
font-weight="500"
fill="#3b5563"
>
{format!("This frame index: {}, second: {:.2}", frame.index, frame.seconds())}
</text>
</svg>
)
}
}Here is a list of some of the examples we store in the repo. Feel free to inspire steal them for your videos. Click an example name to browse its source, or a poster for a preview.
The 128 second launch video, everything placed on the beat grid of its soundtrack.
A 20 second promo with pixel objects, a perspective carousel, thermal shaders and per-exposure vector ink, an adaptation of a reference film.
A simple "hello world" video. A good start if you want to really read the code.
An animated robo arm movement video using 3D capabilities.
A 24 second motion study: product UI, data storytelling and a technical explainer.
A complicated multi-scene example (our beta announce video).
Our announcement video from 2021. With audio visualization.
GPU shader layers composed with SVG: an SkSL background and a Shadertoy raymarcher clipped into a card.
A 31-second shader promo with reference audio, a moving panel wall, native preview footage and 18 GPU shader programs, rendered with Skia on Metal or Vulkan.
The preview is silent: its soundtrack is not in the repository.
A minimal shader clip built to make banding and motion artifacts easy to spot.
An svgr UI on the screen of a turning 3D monitor, showing a 3D cube with the svgr logo: four nested levels of SVG and 3D that never leave the GPU.
A showcase of different effects available for Captions module in fframes
Beautiful sound waves audio visualization + subtitles for your video.
An audio visualization for a podcast placeholder video.
Teej's podcast with 2 speakers video and chapters visualization.
A TikTok-like vertical video with audio visualization
An 18 second vertical launch video for Lottie support: every animation is a Lottie file and the music is synthesized in Rust.
One splash screen per conference talk, rendered in batch.
A renderer stress test: animal art with a lot of polygons.
My dog's memorial video generator (totally randomized).
cargo install --locked cargo-fframes
cargo fframes new my-video
cd my-video && cargo run --release -- previewThe preview timeline sits below landscape and square videos and to the left of portrait videos.
Drag the filmstrip to scrub, or click a scene marker to pause on its first frame. Use [ and ]
to jump between scenes and , and . to step one frame. Press Space to play or pause, or T
to hide the timeline and expand the video.
On macOS the studio tries VideoToolbox for supported source videos and falls back to software
for unsupported formats. preview --software-decode uses the CPU for decoding while keeping
the selected drawing backend. Playback and filmstrip workers release idle source decoders.
The GPU preview draws each scene through Skia directly into the window drawable or swapchain.
The default buffer holds up to four prepared scene trees, and only the frame under the pointer
is prepared while you drag the timeline. Decoders reuse the pixel buffers of frames that no
scene tree holds any more. The CPU backend draws directly into the window buffer.
cargo fframes new takes --template single-scene|multi-scene, --format landscape|portrait|square|uhd, --fps,
--title and --backend. On macOS and Linux (arm64, x86_64) the first build downloads prebuilt Skia and ffmpeg
libraries and takes under a minute on a fast machine; other targets and feature combinations
compile them from source (up to ~20 minutes). Later builds take seconds. --backend cpu skips Skia (no preview window, slower renders). To track main, install with
--git https://github.com/dmtrKovalenko/fframes.
Rust and, for working on the editor, NodeJS.
fframes links ffmpeg's libav libraries statically. A prebuilt build is downloaded for macOS and Linux (arm64 and x86_64) and
compiled from source for other targets or FFMPEG_FORCE_BUILD=1; either way the system encoders they link against have to be installed.
The examples enable fframes/build-portable on native non-Windows targets. CI builds the
whole workspace, combining the examples' x264, x265, VPX and Opus features; no published
FFmpeg archive currently matches that combination, so it falls back to a source build.
Without build-portable, that build uses -march=native -mtune=native. Caching it and
restoring it on a runner with a different CPU can cause SIGILL (illegal instruction).
The feature omits those flags for source builds while keeping matching prebuilt downloads
enabled, and also applies to FFmpeg used by the compile-time media macro.
Within this workspace, use the same setting for native builds that will be cached or run on other machines:
[target.'cfg(not(any(target_arch = "wasm32", windows)))'.dependencies]
fframes = { workspace = true, features = ["build-portable"] }build-portable also enables FFmpeg's source-build support, so the examples exclude Windows
(which links a shared FFmpeg installation) and browser targets. Setting FFMPEG_MARCH or
FFMPEG_MTUNE, even to an empty string, bypasses prebuilt downloads; prefer the feature when
you want portable source fallbacks and prebuilt downloads.
macOS
brew install pkg-config ffmpeg x264 x265 opus nasm ninjaLinux
for debian based distros:
sudo apt-get install -y yasm nasm ffmpeg libx264-dev libx265-dev libopus-dev libclang-dev clang ninja-build libvpx-dev libasound2-devfor arch based distros:
sudo pacman -S ninja yasm nasm ffmpeg x264 x265 opus clangfor nix users:
nix-shellWindows
On Windows ffmpeg is not compiled from source. Instead fframes links a prebuilt FFmpeg 9.0 shared build
(for example ffmpeg-n9.0-latest-win64-gpl-shared-9.0.zip from BtbN/FFmpeg-Builds)
and needs LLVM for bindgen:
winget install LLVM.LLVM
# unzip the ffmpeg build somewhere, then point the build to it:
$env:FFMPEG_DIR = "C:\ffmpeg-n9.0-latest-win64-gpl-shared-9.0"
$env:LIBCLANG_PATH = "C:\Program Files\LLVM\bin"
# the ffmpeg DLLs must be reachable when building (proc macros load them) and running
$env:PATH = "$env:FFMPEG_DIR\bin;$env:PATH"vcpkg install ffmpeg works as well instead of FFMPEG_DIR. Codecs come from the prebuilt build, so leave the
codec features (h264, h265, ...) off: they request a from-source ffmpeg build which is not supported on Windows.
Codecs
Cargo features of the fframes crate choose which codecs and hardware acceleration libraries are linked:
[dependencies]
# this will enable and try to link libx264 during the build
fframes = { version = "1", features = ["h264", "libav-agree-gpl"] }All the build and linking of codecs and other system libs are leveraging the ffmpeg build system, so for troubleshooting please refer the ffmpeg compilation guide.
Troubleshooting
- Build fails in
ffmpeg-sys-fframes: a system library from the list above is missing (nasm,pkg-config, the codec packages). - Build fails in the Skia bindings with a bindgen or libclang error (only when Skia is compiled from source, e.g. with
both
metalandvulkanenabled): pointLIBCLANG_PATHat a working libclang, on macOS Xcode's:export LIBCLANG_PATH=$(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib. - Text renders in the wrong font:
inspectreportsNo match for ... font-family; put the font file in the project'smedia/folder and use its exact family name.
Agents working on fframes itself should start from AGENTS.md. For humans, install the just command runner and init the repo:
npm install --global pnpm # the package manager for the nodejs based editor
cargo install --locked just cargo-watch wasm-bindgen-cli wasm-pack
just init-repo
just watch-editor # in a separate terminal, to work on the editorfframes is released under the MIT License.