No description
  • C++ 91.2%
  • Nix 4.7%
  • CMake 1.9%
  • C 1.8%
  • Python 0.4%
Find a file
2026-07-13 16:29:37 -04:00
kernels more stuff 2026-06-25 09:08:37 -04:00
scripts more stuff 2026-06-25 09:08:37 -04:00
src feat: macos support 2026-07-13 16:29:37 -04:00
.envrc cleanup 2026-06-24 22:26:05 -04:00
.gitignore cleanup 2026-06-24 22:26:05 -04:00
CMakeLists.txt more stuff 2026-06-25 09:08:37 -04:00
flake.lock cleanup 2026-06-24 22:26:05 -04:00
flake.nix feat: macos support 2026-07-13 16:29:37 -04:00
README.md feat: macos support 2026-07-13 16:29:37 -04:00
shell.nix feat: macos support 2026-07-13 16:29:37 -04:00

blended

blended converts high-frame-rate video into lower-frame-rate video by blending decoded frames in groups sized by the number of configured weights. The default uses four equal weights, so the default behavior still targets 240 fps input and 60 fps output.

On Linux, it prefers an ffmpeg OpenCL filtergraph path for fast end-to-end processing and falls back to a native streaming engine when needed. On macOS, auto uses the native engine: hardware decode and encode run through VideoToolbox, while blending runs on the GPU through Apple's OpenCL framework. The threaded CPU blender remains the fallback when OpenCL is unavailable.

Quick Start

nix develop
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build

./build/blended input.mp4

With flakes:

nix run . -- input.mp4
nix build
./result/bin/blended input.mp4

Usage

blended <input> [output] [options]

Useful examples:

blended input.mp4
blended input.mp4 output.mp4
blended input.mp4 output.mp4 --weights 1,3,3,1
blended input.mp4 output.mp4 --weights 1,1
blended input.mp4 output.mp4 --scale 0.5
blended input.mp4 output.mp4 --engine native --encoder h264_vaapi --qp 20
blended input.mp4 output.mp4 --engine native --encoder hevc_videotoolbox --crf 20
blended input.mp4 output.mp4 --engine ffmpeg-opencl --encoder libx264 --crf 16 --preset faster

Inspection commands:

blended --help
blended --version
blended --list-opencl
clinfo
ffmpeg -hwaccels

Options

  • --weights w1,...,wN: N non-negative values, where N is the number of decoded input frames blended into one output frame. Supports 1..64 weights. They are normalized automatically, so --weights 1,3,3,1 is valid. If omitted, four frames are weighted evenly.
  • --scale factor: uniformly scale output dimensions after blending and before encoding. Values below 1 downscale and values above 1 upscale. Scaling uses ffmpeg Lanczos3, and dimensions are rounded to the nearest even pixel count for encoder compatibility.
  • --engine auto|ffmpeg-opencl|native: on macOS, auto uses the native Apple OpenCL path directly. On Linux, it tries ffmpeg-opencl first and falls back to native.
  • --encoder auto|h264_vaapi|hevc_vaapi|h264_videotoolbox|hevc_videotoolbox|libx264|libx265: on macOS, auto selects hardware H.264 through VideoToolbox. On Linux, the native engine uses h264_vaapi when the VAAPI render node exists and otherwise uses libx264; the ffmpeg OpenCL engine defaults to libx264.
  • --crf 0..51: quality for software and VideoToolbox encoders. Lower is higher quality and larger output. For VideoToolbox it is mapped onto ffmpeg's 0..100 quality scale. Defaults are 18 for H.264/x264 and 20 for HEVC/x265.
  • --qp 0..51: quality for VAAPI encoders. Lower is higher quality and larger output. Defaults are 18 for H.264 VAAPI and 20 for HEVC VAAPI.
  • --preset name: software encoder speed/compression preset. Defaults are veryfast for x264 and fast for x265.
  • --vaapi-device path: render node used by VAAPI encoders. Defaults to /dev/dri/renderD128.
  • --fps n: explicit output frame rate. Accepts positive integers and rational rates such as 30000/1001. If omitted, the output frame rate is input fps / N, where N is the number of weights; if the input rate cannot be probed, it falls back to 60.
  • output: optional output path. If omitted, the output is written next to the input as <input name without extension>-blended.mp4.

Build Details

Local CMake build:

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install build --prefix "$PWD/dist"

The CPU fallback is portable by default. To optimize it for the local machine:

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBLENDED_NATIVE_ARCH=ON

The Nix package wraps the installed binary so ffmpeg and ffprobe are available on PATH at runtime.

On Apple Silicon, both the regular CMake build and the flake use the macOS SDK's OpenCL framework; no third-party OpenCL ICD is required. The default encoder is h264_videotoolbox, and ffmpeg requests VideoToolbox hardware decoding as well.

Runtime Notes

  • The output frame count is based on complete groups of N decoded input frames, where N is the number of weights. Any incomplete trailing group is dropped.
  • ffmpeg-opencl blends in NV12 through ffmpeg's OpenCL filter path and avoids piping raw RGBA frames through this process.
  • On the tested AMD ffmpeg stack, direct OpenCL-to-VAAPI zero-copy mapping is not available. If VAAPI is requested with ffmpeg-opencl, blended uses libx264 for that engine.
  • The native engine decodes and encodes with ffmpeg, blends with OpenCL if an OpenCL device is available, and falls back to threaded CPU blending otherwise.
  • On macOS, auto uses VideoToolbox for hardware video decode/encode. Explicit libx264 and libx265 remain available when software encoding is desired.
  • On NixOS, OpenCL device discovery depends on the installed GPU runtime and ICD files under /etc/OpenCL/vendors. For AMD, configure ROCm OpenCL or another OpenCL ICD.

Repository Hygiene

Generated build outputs, Nix result links, logs, object files, and local .mp4 scratch videos are ignored. Keep large sample videos outside Git unless they are intentionally published as release assets.