fframes README

The project's README from github.com/dmtrKovalenko/fframes. As one markdown file: README.md.

fframes

Video vibe coding framework that is actually fast.
Write your video in Rust and SVG, render it on the GPU.

crates.io docs.rs MIT license @fframes_rust on X

The fframes launch video, made with fframes

This 128 second video was vibed in 48 minutes and rendered in 36 seconds.
It is an fframes project: examples/fframes-intro.


Ask your agent for a video

fframes ships a skill for coding agents. Add it once:

npx skills add dmtrKovalenko/fframes

Then describe the video you want, the way you would brief a motion designer. The skill takes your agent from an empty folder to a rendered .mp4: it installs fframes, creates a project, designs the motion, places the sound, and checks the result before handing it to you.

The fframes API is explicit and verbose, and that is why it stayed unreleased for years. Writing explicit, verbose code is exactly what an agent with the right skill is good at.

Built for an author that cannot watch

A coding agent cannot watch a video or hear a soundtrack. Every generated project comes with a command line that turns a video into things an agent can read: PNGs, text and numbers.

Your agent You
Checks every frame without rendering pixels.
inspect reports missing fonts or images, text cut off by the canvas, invalid SVG and panics, each with its time and scene.

Looks at the motion.
strip lays evenly spaced frames out on one contact sheet, onion blends frames to show a movement's path and easing, frame writes full-size PNGs.

Measures the sound.
audio analyze reports loudness (LUFS), true peak, clipping and silence, per scene.
Watch it in real time, with sound.
preview opens a GPU window to play, pause, seek and step through frame by frame.

Scrub it in the browser.
The editor runs the video compiled to WebAssembly, with a timeline.

Ship it.
render writes the final file; render --draft encodes one scene at half size in about a second.

Every command runs as cargo run --release -- <command> inside the project:

command output
timeline the scenes with their frame and second ranges, and every audio track with its mix settings
inspect problems in a frame every 0.25 s and the first and last frame of every scene; exit code 2 on errors
strip <scene> -n 12 strip.png, a labelled contact sheet
frame <scene>@end,<scene>@50% full-size PNGs in frames/
onion "<scene>@0..<scene>@1s" -n 6 onion.png, the blended movement
audio analyze --waveform w.png the loudness report and a waveform with scene lines and cue ticks
snapshot a comparison with approved PNGs, .diff.png marks what changed
preview the real-time window, for a human
render [--draft] the video, or a part of it

<scene> is the name of a scene struct in your video. Times read as 120 (frame), 3.2s, 50%, <scene>@1.2s, and ranges like <scene>@0..<scene>@1s. Add --json to parse the output.

Why it is fast

What your agent writes

Every 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>
        )
    }
}

The skill's guides are plain Markdown and worth reading as a human too: the workflow, the API cheat sheet, design and sound. The full API reference is on docs.rs/fframes.

Examples

example what it shows
fframes-intro the 128 second launch video, everything placed on the beat grid of its soundtrack
signal-lab a 24 second motion study: product UI, data storytelling and a technical explainer
motion-graphics spring "punch in" motion and monospace text fitted to its box
shaders GPU shader layers composed with SVG: an SkSL background and a Shadertoy raymarcher clipped into a card
neon-triangle a minimal shader clip built to make banding and motion artifacts easy to spot
hello-world a simple "hello world" video
beta a complicated multi-scene example (our beta announce video)
marketing our marketing video
audio-announce an automated workflow to create audio visualisation with automated subtitles
podcast an audio visualization for a podcast placeholder video
teej-podcast teej's podcast with video and chapters visualization
tiktok a TikTok-like vertical video
conference-splash-screen one splash screen per conference talk, rendered in batch
low-poly-art a renderer stress test: animal art with a lot of polygons
pixel-memory my dog's memorial video generator (totally randomized)

From the repository root, just run podcast opens an example in the editor with live reload and just render podcast writes it to a file.

Without an agent

cargo install --locked cargo-fframes
cargo fframes new my-video
cd my-video && cargo run --release -- preview

cargo fframes new takes --template single-scene|multi-scene, --format landscape|portrait|square|uhd, --fps, --title and --backend. The first build compiles Skia and ffmpeg from source and takes a while; later builds take seconds. --backend cpu skips the Skia build (no preview window, slower renders). To track main, install with --git https://github.com/dmtrKovalenko/fframes.

Requirements

Rust and, for working on the editor, NodeJS. fframes compiles ffmpeg's libav libraries during the build, so the system encoders they link against have to be installed.

macOS
brew install pkg-config ffmpeg x264 x265 opus nasm ninja
Linux

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-dev

for arch based distros:

sudo pacman -S ninja yasm nasm ffmpeg x264 x265 opus clang

for nix users:

nix-shell
Windows

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-next: 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: point LIBCLANG_PATH at a working libclang, on macOS Xcode's: export LIBCLANG_PATH=$(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib.
  • Text renders in the wrong font: inspect reports No match for ... font-family; put the font file in the project's media/ folder and use its exact family name.

Working on fframes

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 editor

License

fframes is released under the MIT License.

fframes (dmtrKovalenko/fframes)

Searching Database…

2.9K ·GitHub
这是什么?fframes 是一个用代码书写视频的 Rust 框架:你用 Rust 和 SVG 组合场景,GPU 把它们渲染成 MP4。它围绕“真正快”这一目标构建,不同于许多代码优先的视频工具。
这是图形界面的视频编辑器,还是需要我写代码?你用 Rust 创作视频:每一帧都是由用 svgr! 宏编写的 Rust 函数返回的 SVG 树。没有用于创作的时间轴 GUI,不过有一个带实时重载的浏览器版 WASM 编辑器,可以预览和逐帧拖动。
如何创建新项目?运行 cargo fframes new,选择 --template(single-scene 或 multi-scene)、--format(landscape、portrait、square、uhd)、--fps、--title 和 --backend。首次构建会从源码编译 Skia 和 ffmpeg,因此耗时较长;之后的构建只需几秒。
构建之前需要安装什么?你需要 Rust;如果打算开发 WASM 编辑器,还需要 Node.js。fframes 在构建期间会编译 ffmpeg 的 libav 库,因此必须预先安装对应的系统编码器软件包(macOS 用 Homebrew,Linux 用 apt/pacman/nix,Windows 用 LLVM 加预构建的 FFmpeg zip)。
安装上有哪些坑需要提前知道?首次构建会从源码编译 Skia 和 ffmpeg,需要一段时间。在 Windows 上,ffmpeg 改为链接预构建的共享版本,因此必须放弃 h264/h265 等编解码特性,因为它们需要从源码构建,而 Windows 上不支持。
fframes 真正面向谁?面向熟悉 Rust、想要程序化动态图形的开发者,尤其面向编程智能体:fframes 附带一个可安装的技能,能让智能体从空文件夹一路自动走到渲染完成的 .mp4。
fframes 可以在哪些平台上运行?支持 macOS、Linux 和 Windows,每个平台都有自己的一套 ffmpeg 构建说明(macOS 用 Homebrew,Linux 用发行版软件包或 nix,Windows 用预构建的 FFmpeg zip 加 LLVM)。
渲染需要特定的 GPU 或后端吗?默认的 Skia 后端在 macOS 上使用 Metal,在 Linux/Windows 上使用 Vulkan,渲染速度约是 CPU 后端的 10 倍;传入 --backend cpu 可以完全跳过 Skia 构建,代价是速度和实时预览窗口。
fframes 为什么比 Remotion 之类的工具或普通 CPU 渲染器更快?它通过 Skia 在 GPU 上渲染(macOS 用 Metal,Linux/Windows 用 Vulkan),速度约为 CPU 后端的 10 倍;编译时会缓存不含 {expressions} 的静态标记;并且直接链接 ffmpeg 的 libav 库,而不是派生一个单独的进程。
编程智能体没法观看视频,那它怎么检查视频是否正确?fframes 把视频转换成智能体能读取的东西:inspect 会逐帧标记缺失字体、被裁切的文本和无效 SVG;strip 和 onion 会生成带标注的运动缩略图集;audio analyze 则以数字形式报告响度、削波和静音。
我能在不每次都完整渲染的情况下迭代视频吗?可以:preview 会打开一个实时 GPU 窗口,可以逐帧拖动查看;WASM 浏览器编辑器支持实时重载;render --draft 则以一半尺寸在约一秒内编码一个场景。
fframes 的智能体技能到底做什么?添加到编程智能体后,它会带着项目从空文件夹一路走到最终的 .mp4:安装 fframes、搭建项目脚手架、设计动效和声音布局,并在交还给你之前检查渲染结果。
Size
1.5 GB
Stars
2.9K
Age
4y
Commits · 90 Days