Skip to main content

ffman

Opinionated media conversion on ffmpeg: resize, effects, subtitles, encoding. One command, convert, transforms one media file; effects lists the video effects. Lossless by default: a resize keeps the source's codec and loses nothing.

Running it

On Linux or macOS; on Windows, in WSL (ffman refuses to run on Windows itself: it handles its tools as POSIX does). From its flake -- on Linux (x86_64, aarch64) or macOS (Apple silicon: not yet tested) -- the tools it runs come with it:

nix run github:veramachine/ffsuite -- convert -i in.mp4 -w 1280

Or as a container image, built from the flake on Linux, its ffmpeg with Fraunhofer's FDK AAC -- for your own use: ffmpeg's own build calls such an ffmpeg "nonfree and unredistributable", so no binary cache holds it either (it builds from source). Docker, from the folder of your files:

nix build github:veramachine/ffsuite#image && ./result | docker load
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/work" ffman:0.1.0 convert -i in.mp4 -w 1280

ffman convert --help lists every option; ffman effects, the effects and their values. --dry-run prints the plan and every ffmpeg command, and writes nothing. Without -o, the output is STEM.ffman.EXT beside the input; --in-place replaces the input.

What it needs

The Nix package and the image bring everything. Installed any other way, ffman needs ffmpeg (with ffprobe) on PATH; the rest only for what they serve:

Tool For Without it
ffmpeg-normalize (and env) --preset youtube, when the sound needs normalising that job is refused
metaflac (flac) a FLAC's cue sheet carried into a FLAC noted and left out; the job completes
oxipng, jpegoptim, gifsicle PNG, JPEG, GIF outputs optimised losslessly noted; written unoptimised
nproc (coreutils) the processor count: FFV1's slices past four, ffmpeg's threads past 16 Python's count of the processors, noted

ffman carries its fonts, IBM Plex Sans for burned captions and IBM Plex Mono for the camcorder's stamp (FFMAN_FONTS_DIR names another folder), and the ffmpeg-normalize presets --preset youtube uses (FFMAN_NORMALIZE_HOME names another: an XDG_CONFIG_HOME, its presets in ffmpeg-normalize/presets/). Converting metadata files alone (with meta or convert, no media) needs none of the tools.

Examples

# a 9:16 story, the bars filled with the picture, blurred
ffman convert -i trip.mp4 -a 9:16 -w 1080 -b -o trip.story.mp4
# burned subtitles, the spoken word highlighted (word timings: whisper-cli -ojf, WhisperX)
ffman convert -i talk.mp4 --burn-subs talk.json --overlay-mode chunk-word --highlight-mode pop
# the same, the spoken word in a colour of your own
ffman convert -i talk.mp4 --burn-subs talk.json --overlay-mode chunk-word --highlight-colorize '#00BFFF'
# ...or by name, any case: gold, red, orange, amber, yellow, lime, green, emerald, teal, cyan
# (aqua), sky, blue, indigo, violet, purple, fuchsia (magenta), pink, rose, slate, gray (grey),
# zinc, neutral, stone, white, black
ffman convert -i talk.mp4 --burn-subs talk.json --overlay-mode chunk-word --highlight-colorize teal
# the text in a colour, outlined by contrast (black or white) unless --outline-color says
ffman convert -i talk.mp4 --burn-subs talk.srt --font-color amber
# the spoken word boxed in reverse video: the box the text's colour, the word its outline's
ffman convert -i talk.mp4 --burn-subs talk.json --overlay-mode chunk-word --highlight-colorize rectangle
# ...or the text itself in motion, outlines too
ffman convert -i talk.mp4 --burn-subs talk.srt --font-color iridescent --outline-color lsd
# ...or its letters in hues that turn: rainbow, lsd, iridescent
ffman convert -i talk.mp4 --burn-subs talk.json --overlay-mode chunk-word --highlight-colorize rainbow
# a subtitle track, nothing re-encoded
ffman convert -i film.mkv --add-subs film.srt --language eng --in-place
# for YouTube: H.264 High, two passes, AAC
ffman convert -i clip.mov -p youtube -o clip.mp4
# a cue sheet as Vorbis comments (a .txt: -p ffmetadata, the default, or vorbiscomment)
ffman convert -i album.cue -o album.txt -p vorbiscomment
# a media file's tags and chapters, as ffmetadata (or a .txt, a .cue)
ffman convert -i film.mkv -o film.ffmeta
# a metadata file edited (keys: ffmpeg's generic ones, any case), or written anew
ffman meta -i album.cue --in-place --set genre='Alt Rock' --set date=1991
ffman meta -o tags.txt -p vorbiscomment --set title=Song --add artist=A --add artist=B
# chapters (a cue's tracks): TIME as 62.5, 1:02.5, 1:01:02.5 or 4650f (frames)
ffman meta -i book.ffmeta --in-place --chapter 12:30=Road --retitle 1=Departure
# a cue sheet's own: its media, a track's flags and pregap (INDEX 00)
ffman meta -i album.cue --in-place --file album.flac --flags 2=PRE --pregap 2=4:15
# to stdout: a file's tags and chapters, as read (or -p ffmetadata, vorbiscomment, cue)
ffman meta -i film.mkv -o -
# a metadata file's tags and chapters, applied: alone (streams copied), or with any job
ffman convert -i film.mkv -o tagged.mkv --metadata chapters.cue
# another container: a remux, each stream copied (or encoded, when asked)
ffman convert -i clip.webm -o clip.mp4
ffman convert -i clip.mp4 -o clip.webm --video-codec vp9 --audio-codec opus
# effects, in any combination
ffman convert -i home.mp4 --vfx vhs --vfx camcorder:date=1998-07-04 -o home.vhs.mp4
# a GIF that loops
ffman convert -i trip.mp4 -w 480 --loop -o trip.gif

What a conversion keeps

Every stream an input carries is kept where the output holds it, and named where it does not (ffman: ... left out) -- never dropped without a word:

  • subtitles, copied or turned into the output's own text (mov_text in MP4, WebVTT in WebM);
  • tags and chapters (into Ogg and FLAC, as CHAPTERxxx comments);
  • attachments into Matroska; elsewhere an attached cue, ffmetadata or Vorbis comments file is applied as --metadata would apply it;
  • the cover, copied, or into Matroska attached as cover.png (cover_land when wider than tall).

The rules, each measured: ffman-spec.md 3.12 to 3.15.

More

It replaced a bash ffman (retired in phase 5 of ffman-python.md), after equalling it on every invocation of the bash suites; what it changed on purpose: ffman-from-bash.md.

Licence

Part of ffsuite, beside its libraries ffmeta and subverter. Licensed under either of MIT or Apache-2.0, at your option; its fonts, IBM Plex, under the OFL.

Metadata

Release files for ffman 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ffman 0.1.0
File Size Uploaded
ffman-0.1.0.tar.gz 498.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ffman 0.1.0
File Interpreter ABI Platform
ffman-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 854.0 kB

Release files / ffman-0.1.0.tar.gz

Download URL ffman-0.1.0.tar.gz
Size 498.1 kB
Tags Source
SHA-256 checksum
How to use checksums
dfbfc5604e63548f56d4f4f24be659e28eadbf3953036a74753b452f1cf53013
BLAKE2b-256 checksum
How to use checksums
8e3b84c5da7a7a7f22253912c1618463e8b0045a47a09eafc96b3ebaa82c6ee5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.05","id":"yarara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / ffman-0.1.0-py3-none-any.whl

Download URL ffman-0.1.0-py3-none-any.whl
Size 355.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
abc9b17ebf7b007d96fe81475f20f0f116c6f726254b0a7983ee931a86fb54a1
BLAKE2b-256 checksum
How to use checksums
593dffb8c08eddb2ef314675b3603ea2309f08e009e23669672db18a614f29cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.05","id":"yarara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page