Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vidgen

A Rust CLI tool for generating algorithmic art videos. Create dynamic backgrounds, B-roll footage, and experimental visuals using procedural generation.

Preview

Features

  • Layer-based compositing - Everything is a layer, composited with alpha blending
  • Parallel rendering - Uses all CPU cores for fast frame generation
  • Hardware encoding - M1/Apple Silicon accelerated H.264/HEVC via VideoToolbox
  • Reproducible output - Same seed always produces identical results
  • iMovie compatible - Output works directly in Apple video editors

Installation

Requires Rust and ffmpeg:

# Install ffmpeg (macOS)
brew install ffmpeg

# Build the project
cargo build --release

# The binary is at ./target/release/vidgen

Quick Start

# Simple gradient background
vidgen render -d 5 -p '{"background":"#1a1a2e","layers":[{"type":"linear","properties":{"colors":["#e94560","#0f3460"],"angle":45},"animate":{"offset":{"cycles":1}}}]}'

# Preview frames (no video encoding)
vidgen preview -c 5 -p config.json

# From config file
vidgen render -p config.json -o background.mp4

Usage

Generate a Video

# Basic usage - 10 second 1080p video
vidgen render -p config.json -o my_video.mp4

# Quick test at SD resolution
vidgen render -r sd -d 3 -p config.json -o test.mp4

# 4K video with custom duration
vidgen render -r uhd4k -d 30 -p config.json -o background_4k.mp4

Preview Frames Before Rendering

# Generate 5 sample frames as PNGs
vidgen preview -r hd1080 -c 5 -p config.json -o preview/

Options

Option Description Default
-o, --output Output file path output.mp4
-r, --resolution sd, hd720, hd1080, uhd4k hd1080
-d, --duration Duration in seconds 10
--fps Frames per second 30
-s, --seed Random seed for reproducibility 42
-q, --quality Quality (18-28, lower=better) 23
-w, --workers Parallel workers (reduces memory usage) CPU cores
-p, --params Layer config (JSON file or inline) ""
--codec Video codec: h264 (faster) or h265 (smaller) h264
--fast Prioritize encoding speed over compression false
--software-encode Use libx264/libx265 instead of VideoToolbox false

Speed Tips

# Default (H.264) is already fast; add --fast for maximum speed
vidgen render --fast -p config.json -o fast.mp4

# Use H.265 for smaller files (slower encoding)
vidgen render --codec h265 -p config.json -o smaller.mp4

# Reduce memory usage on machines with limited RAM (e.g., 8GB Mac)
vidgen render -r hd1080 -w 2 -p config.json -o video.mp4

Layer Types

Type Purpose Key Properties
solid Flat color fill color, opacity
linear Directional gradient colors, angle, length, offset, opacity
radial Circular gradient colors, center, length, offset, opacity
blur Gaussian blur of layers below radius, amount
flowfield Perlin noise particle trails particles, scale, cycles, opacity

Configuration

JSON Structure

{
  "background": "#0a0a12",
  "layers": [
    {
      "type": "linear",
      "properties": {
        "colors": ["#1a1a2e", "#16213e", "#0f3460", "#1a1a2e"],
        "angle": 45,
        "length": 0.8
      },
      "animate": {
        "offset": { "cycles": 2 }
      }
    },
    {
      "type": "radial",
      "properties": {
        "colors": ["#e9456050", "#53348350", "#e9456050"],
        "center": [0.3, 0.5],
        "length": 0.5
      },
      "animate": {
        "offset": { "cycles": -1, "curve": "sine" }
      }
    }
  ]
}

Each layer has three top-level keys:

  • type - Layer type (see table above)
  • properties - Static properties
  • animate - Animation modifiers for properties

Properties Reference

All layers:

Property Description Default
opacity Layer opacity 0.0-1.0 1.0

Solid:

Property Description Default
color Fill color: "#RRGGBB" or "#RRGGBBAA" #000000

Linear gradient:

Property Description Default
colors Color stops (see below) []
angle Gradient angle in degrees, 0=right, 90=down 0
length Gradient cycle length (1.0 = larger image dimension) 1.0
offset Position within gradient (0.0-1.0, wraps) 0.0

Radial gradient:

Property Description Default
colors Color stops (see below) []
center Center point [x, y], 0.5=middle [0.5, 0.5]
length Gradient radius (1.0 = larger image dimension) 1.0
offset Position within gradient (0.0-1.0, wraps) 0.0

Blur:

Property Description Default
radius Blur radius as fraction of width 0.02
amount Blur blend amount 0.0-1.0 1.0

Flowfield:

Property Description Default
particles Number of particles per frame 50000
scale Noise scale, lower = larger patterns 0.004
cycles Animation cycles over video duration 2.0

Color Format

  • #RRGGBB - 6-digit hex (opaque)
  • #RRGGBBAA - 8-digit hex with alpha
  • #RRGGBB@30% - with gradient position (0-100%)

Animation

The animate dict specifies which properties to animate:

"animate": {
  "offset": { "cycles": 1.0, "curve": "linear" },
  "opacity": { "cycles": 0.5, "curve": "sine" }
}
Field Description Default
cycles Complete cycles per video duration (negative = reverse) 0
curve Easing: linear, sine, ease-in, ease-out, ease-in-out linear

Animatable properties: offset, angle, length, opacity, radius, amount, cycles

Examples

Animated Linear Gradient

vidgen render -d 10 -p '{
  "background": "#0a0a12",
  "layers": [{
    "type": "linear",
    "properties": {"colors": ["#ff6b6b", "#4ecdc4", "#ff6b6b"], "angle": 30, "length": 0.6},
    "animate": {"offset": {"cycles": 2, "curve": "sine"}}
  }]
}'

Pulsing Radial Glow

vidgen render -d 10 -p '{
  "background": "#1a1a2e",
  "layers": [{
    "type": "radial",
    "properties": {"colors": ["#e9456080", "#e9456000"], "center": [0.3, 0.4], "length": 0.5},
    "animate": {"offset": {"cycles": -1, "curve": "sine"}}
  }]
}'

Flow Field with Background

vidgen render -d 10 -p '{
  "background": "#0a0a14",
  "layers": [
    {"type": "flowfield", "properties": {"particles": 40000, "scale": 0.003}},
    {"type": "blur", "properties": {"radius": 0.005, "amount": 0.3}}
  ]
}'

Multi-Layer Composition

{
  "background": "#0a0a12",
  "layers": [
    {
      "type": "linear",
      "properties": {"colors": ["#1a1a2e", "#16213e"], "angle": 45, "length": 1.0},
      "animate": {"offset": {"cycles": 0.5}}
    },
    {
      "type": "radial",
      "properties": {"colors": ["#e9456040", "#e9456000"], "center": [0.2, 0.3], "length": 0.4},
      "animate": {"offset": {"cycles": -1, "curve": "sine"}}
    },
    {
      "type": "radial",
      "properties": {"colors": ["#4ecdc440", "#4ecdc400"], "center": [0.8, 0.7], "length": 0.5},
      "animate": {"offset": {"cycles": 0.7, "curve": "sine"}}
    },
    {
      "type": "blur",
      "properties": {"radius": 0.01, "amount": 0.4}
    }
  ]
}

Reproducibility

Videos are fully deterministic. Running the same command with the same seed produces byte-identical output:

# These produce identical videos
vidgen render -s 42 -p config.json -o video1.mp4
vidgen render -s 42 -p config.json -o video2.mp4

# Different seed = different video
vidgen render -s 123 -p config.json -o video3.mp4

Adding Custom Layer Types

Layers are defined in src/layers/. To add a new layer type:

  1. Create src/layers/mylayer.rs with a render() function
  2. Add mod mylayer; to src/layers/mod.rs
  3. Add any new properties to the Properties struct
  4. Add the type to the match statement in render_layers()
  5. Document the layer type

The RenderContext provides timing and config info:

impl RenderContext {
    // Seamless looping: completes n cycles over video duration
    pub fn loop_phase(&self, cycles: f64) -> f64;

    // Fixed period animation (may not loop seamlessly)
    pub fn periodic_phase(&self, period_secs: f64) -> f64;

    // Per-frame seed for reproducible randomness
    pub fn frame_seed(&self) -> u64;
}

License

MIT

About

A Rust CLI tool for generating algorithmic art videos. Create dynamic backgrounds, B-roll footage, and experimental visuals using procedural generation.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages