A minimal, fully reproducible, and highly optimized OCI container image for ffmpeg built with Nix. It is specifically designed for containerized cloud workflows (like Argo Workflows) and supports multi-architecture (linux/amd64 and linux/arm64) deployments.
- Overview
- Key Features
- How It Works
- Repository & Container Utilities
- Usage Examples
- Local Development
- CI/CD & Publishing
This repository uses Nix Flakes to build deterministic, minimal OCI images containing ffmpeg and the argo-ffmpeg-progress utility. By leveraging Nix, we eliminate extra system libraries, keeping the final container lightweight, secure, and reproducible. The resulting image is ideal for cloud-native transcoding pipelines.
- Minimal & Secure: Built using Nix's
dockerTools, packaging onlyffmpeg, a few dependencies (bash,jq,coreutils,gawk), and the progress tracker script. No package manager or unnecessary base-image clutter. - Multi-Architecture Support: Built and published for both
linux/amd64andlinux/arm64. - Seamless Argo Workflows Integration: Features an integrated stream parser to format transcoding progress updates for Argo's UI.
- Reproducible Environment: Pins dependency versions via Nix Flakes, ensuring the build is identical every time.
argo-ffmpeg-progress consumes the -progress stream of ffmpeg via standard input, calculates the percentage completed based on the total video duration, and outputs it to a specified file.
graph LR
FFmpeg[ffmpeg -progress ...] -->|Pipes stderr/progress| ProgressScript[argo-ffmpeg-progress]
ProgressScript -->|Calculates percentage| ProgFile[Progress File /tmp/argo-progress]
ProgFile -->|Read by| Argo[Argo Workflows UI / Agent]
Utilities defined in nix/scripts serve different roles within the container and development environment:
argo-ffmpeg-progress: The only utility packaged directly into the final container image. It readsffmpeg's progress updates fromstdin, converts the current processed time to a percentage, and writes<percent>/100to a target file.
push-multiarch: A CI helper script used to assemble and push multi-architecture OCI manifests (foramd64andarm64) usingregctl.dive-archive: A local development helper script loaded bynix developto rundiveon built container tarballs.
To log the transcoding progress of a 120-second video into /tmp/argo-progress:
ffmpeg -i input.mp4 \
-c:v libx264 \
-progress >(argo-ffmpeg-progress 120 /tmp/argo-progress) \
output.mp4In an Argo Workflows template, you can capture progress tracking by specifying the progressFile field:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: transcode-video-
spec:
entrypoint: transcode-step
templates:
- name: transcode-step
# Argo tracks percentage read from this file
progressFile: "/tmp/argo-progress"
container:
image: ghcr.io/kevinastone/ffmpeg:latest
command: [bash, -c]
args:
- |
# Query duration of input (e.g., using ffprobe or preset value)
DURATION=3600 # 1 hour in seconds
ffmpeg -i input.mkv \
-c:v libx264 -c:a aac \
-progress >(argo-ffmpeg-progress "$DURATION" /tmp/argo-progress) \
output.mp4Enter the development shell to load utility packages (dive, skopeo, dive-archive) automatically:
nix developTo build the OCI container tarball locally for your host architecture:
nix build .#ffmpeg
# or simply:
nix buildThis creates a symlink result pointing to the output tarball.
Use the custom dive-archive script loaded by nix develop to inspect the container layers of your local build:
dive-archive ./resultThis repository uses treefmt-nix to enforce unified formatting. Before making a pull request, run:
nix fmtThe GitHub Actions workflow defined in .github/workflows/ci.yaml automates validation and deployment:
- Linting & Validation: Runs
nix flake checkto validate formatting and package outputs. - Build Matrix: Spawns runners to build both
amd64andarm64image tarballs. - Upstream Tagging: Extracts the version of
ffmpegdirectly from Nixpkgs (e.g.,7.1) to use as the image tag. - Multi-Arch Push: Combines build targets into a multi-arch manifest using
push-multiarchand publishes it to GitHub Container Registry (GHCR).