Skip to content

CLI

This content is for v0.4. Switch to the latest version for up-to-date documentation.

alpha2’s native programs come as one archive per platform. After reading this page you can install them, export a project from a shell, check a project’s media before rendering, and probe, transcode, thumbnail and inspect media files.

There are two programs:

Both use FFmpeg 8 to decode and encode. This page covers common tasks; CLI reference lists every flag.

Each GitHub release has an archive per target and kind, alpha2-<version>-<target>-<kind>.tar.gz (.zip on Windows), and checksums.sha256 with the SHA-256 of every archive.

Target Kinds
linux-x64, linux-arm64 bundled, thin
macos-arm64 bundled, thin
win-x64 bundled
  • bundled carries the LGPL FFmpeg shared libraries and loads them from the archive.
  • thin carries no FFmpeg and loads an FFmpeg 8 installed on the system: on Linux from the system loader’s search path, on macOS from /opt/homebrew/lib, /usr/local/lib or /opt/local/lib, in that order.
  1. Download the archive for your platform from the release page.
  2. Check it against checksums.sha256.
  3. Unpack it and put its bin/ on your PATH, or call the programs by path.

An archive unpacks into one directory:

alpha2-<version>-<target>-<kind>/
bin/alpha2 the media command (alpha2.exe on Windows)
bin/alpha2-host the project renderer (alpha2-host.exe on Windows)
lib/ the FFmpeg libraries (bundled, Linux and macOS)
compliance/ FFmpeg runtime lock, build configuration, source location, notices
licenses/ license texts of FFmpeg, its libraries and the Rust crates
LICENSE.md

npx @alpha2-sh/node install and python -m alpha2 install download the same archive into a shared cache, checked against the release’s checksums.sha256. cargo install alpha2-host (or alpha2-native for alpha2) builds the programs against the FFmpeg 8 on your machine instead.

alpha2-host export exports one project. It prints the result as JSON on standard output and progress on standard error.

Terminal window
alpha2-host export --project project.json --asset image-1=image.png --out tutorial.mp4
  • --asset <source-id>=<path> gives the file of one source. Repeat it for each source.
  • The output must not exist yet, unless you pass --overwrite. The export writes <stem>.alpha2-partial.<ext> beside it and renames that into place when it is finished.
  • --start-ticks and --end-ticks choose the range (the whole timeline by default), and --frame-rate <num>/<den> the output rate (the project’s by default). Times are ticks, 120,000 per second.
  • The output’s extension (.mp4, .mov, .mkv, .webm) or --container picks the container.
  • --video-codec and --audio-codec pick the codecs. By default each container’s: H.264 and AAC, or VP9 and Opus for WebM.
  • --video-quality takes a level (very-low, low, medium, high, very-high) or a bitrate in bits per second. --audio-quality works the same way.
  • --no-audio leaves the audio out.
Terminal window
# Seconds 2 to 5 of a project, as 1080p WebM at 30 fps, high quality, no audio
alpha2-host export --project project.json \
--asset clip-a=a.mov --asset clip-b=b.mov \
--start-ticks 240000 --end-ticks 600000 --frame-rate 30/1 \
--out excerpt.webm --video-quality high --no-audio

Other export options:

Flag Does
--loudness-target <LUFS> [--true-peak-ceiling <dBTP>] Normalizes the audio to an integrated loudness.
--proxy <source-id>=<path>, --media proxies Exports from proxies where there are some.
--strategy prefer-copy Copies untouched source packets instead of rendering, where it can.
--video-encoder <ffmpeg-name> Pins an encoder.

alpha2-host conform reports what each source would read and what is missing or unusable, without rendering and without a GPU. It exits with status 1 when something blocks the export.

Terminal window
alpha2-host conform --project project.json --asset image-1=image.png
{"ok":false,"result":{"catalog":{...},"report":{"purpose":"export_original","ready":false,"sources":[{"issues":[{"blocking":true,"kind":"offline"}],"selection":{"media":"unavailable"},"source_id":"image-1"}]}}}

--purpose chooses what the media is read for: preview, preview-proxy, thumbnail, remote-edit, export-original (the default) or export-proxy. An export runs the same check first and fails with CONFORM_FAILED when the media is not ready.

Text in captions, text generators, layouts and SVG draws with the fonts you give. Pass font files with --font, in fallback order. A project that shows text needs them.

Terminal window
alpha2-host export --project titles.json --font fonts/HankenGrotesk.ttf --font fonts/NotoSansKR.otf --out titles.mp4

Give the browser preview the same files (addFont in alpha2) and preview text matches exported text pixel for pixel.

The built-in effects and transitions need nothing extra (see effects and compositions). Two flags supply the rest:

  • --effects <effects.json> gives a JSON array of runtime effect definitions the project uses besides the built-in ones.
  • --effect-asset <resource-id>=<path> gives the file of an effect resource, such as a .cube 3D LUT.
Terminal window
alpha2-host export --project graded.json --asset clip=clip.mov \
--effect-asset film-look=luts/film.cube --out graded.mp4

--renderer chooses what draws the frames:

  • auto (the default) renders on a hardware GPU when the machine has one, and otherwise on the CPU. It never takes a software GPU adapter (lavapipe, llvmpipe, WARP, SwiftShader).
  • cpu renders on the CPU and opens no graphics driver at all. A CPU-only server, a container or a serverless function needs nothing but the archive.
  • gpu renders on whatever GPU adapter it finds, software ones included, and fails with GPU_INIT_FAILED when there is none.

The CPU renderer draws the same render graph as the GPU, and its pictures are the same bytes on every machine for any number of threads (see determinism). ALPHA2_RENDER_THREADS sets its thread count.

--video-decode chooses how export and conform decode video:

Mode Does
software Decodes every frame on the CPU. The default on macOS and Windows.
auto Decodes on the GPU where the device and the stream allow it, on the CPU otherwise. The default on Linux.
hardware-required Fails instead of decoding a frame on the CPU.

ALPHA2_VIDEO_DECODE sets the mode for serve. Every export result reports the mode it ran (videoDecodeMode) and how frames reached the encoder (videoPipeline: readback, gpu-resident or packet-copy).

--render-cache <dir> keeps rendered frames in a directory, so a later export of the same project, files and effects, by the same host build on the same GPU, takes them instead of rendering them again.

Terminal window
alpha2-host export --project project.json --asset clip=clip.mov --out v1.mp4 \
--render-cache .alpha2-cache --render-cache-quota 8000000000

--render-cache-quota is in bytes (4 GiB by default). --render-cache-backlog is skip (the default) or wait.

The archives’ FFmpeg is LGPL and has no software H.264 encoder. H.264 comes from a hardware encoder (NVENC, VideoToolbox, Media Foundation, Vulkan Video or D3D12 Video) or from Cisco’s OpenH264, which you install yourself:

Terminal window
python -m alpha2 install --openh264 # or: npx @alpha2-sh/node install --openh264

The command downloads Cisco’s OpenH264 2.7.0 from https://ciscobinary.openh264.org, checks it against pinned SHA-256s, and puts it in the host cache, where alpha2-host finds it. --video-encoder openh264 pins it, and ALPHA2_OPENH264=0 turns it off. VP9 (libvpx-vp9) and AV1 (libsvtav1) always encode in software, so a host without an H.264 encoder can still write WebM. A thin archive also uses libx264 when the system FFmpeg has it.

alpha2 works on one file. Run it without arguments to print every command.

Terminal window
alpha2 probe clip.mp4
format: mov,mp4,m4a,3gp,3g2,mj2
duration_ticks: 240000
selected_video: Some(0)
selected_audio: None
stream 0 Video codec=mpeg4 duration_ticks=240000 dimensions=Some((1280, 720)) rate=Some(FrameRate { num: 30, den: 1 }) color=Some(...)

It prints the container, its duration and its streams: codec, size, frame rate and color.

Terminal window
alpha2 thumbnail clip.mp4 poster.png # the sharpest of nine frames
alpha2 thumbnail clip.mp4 frame.png --at 1.5 # the frame at 1.5 s of the source

Without --at, it picks the sharpest of nine frames spread over the video that is neither black nor white.

Terminal window
alpha2 transcode camera.mov edit.mp4
alpha2 transcode camera.mov proxy.mp4 --proxy half
alpha2 transcode camera.mov web.webm --video-codec vp9

transcode encodes the video again at its own size, or at half or a quarter of it with --proxy half|quarter, into the container the output’s extension names. Without --video-codec it uses the container’s default codec when the runtime has an encoder for it, and otherwise another codec the container offers; it prints which.

Terminal window
alpha2 export-audio interview.mp4 interview.wav # 48 kHz WAV from the source's time zero
alpha2 waveform interview.mp4 10 6 # JSON: min, max and RMS per 10 ms bucket, 6 levels

The commands that decode take --decode-policy strict|tolerant. strict (the default) fails at the first damaged input; tolerant skips damaged input and reports what it skipped.