Skip to content

About

Twenty commands for building and keeping a media library: transcoding video, audio, images and comics, ingesting films, music and books, cleaning names, and a census of what is in it

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

577 Commits

Folders and files

Repository files navigation

Media management commands

Command-line tools for ingesting, transcoding and tidying up personal media libraries — audiobooks, music, movies, comics and image galleries. Every one that renames files follows the same "never clobber, never lose a file" rules, described under File safety. What they print, and the -v and -q that set how much, is described under What a run prints.

Each is an installed command. From a checkout, pip install . puts all twenty on your PATH; pip install -e . does the same and keeps them running the checkout, which is what you want while editing it. Under a plain pip install . the per-machine files — the data/ tables, the logs/ logs — live under ~/.local/share/medialib (or $XDG_DATA_HOME/medialib if it is set); the environment variable CLI_SCRIPT_DIR points them somewhere else.

Built to use the whole machine

These commands are written for an enthusiast desktop, and try to keep all of it busy — a many-core CPU, a large NVIDIA GPU, plenty of RAM, fast disks and a network connection — rather than leaving most of it idle while one part works:

  • GPU first, CPU as the fallback. Where a job has a GPU road, it takes it: AVIF pages and images go to the card through av1gpu, video can encode on NVENC and upscale on TensorRT, whisper transcribes on CUDA. Without the GPU, or for the pieces it declines, the same job runs on the CPU and still finishes.
  • Different resources at the same time. Work that leans on different parts of the machine is overlapped instead of queued: GPU transcription beside CPU transcodes, remuxes to disk while the next film is still encoding, slow network lookups on a background thread while the local work carries on (see how ingest-movies does it).
  • Parallel where it pays. CPU-bound work is spread over the cores in jobs sized to them, and kept narrower where it would only fight a GPU job or another encoder for the same cores.
  • RAM before disk. Heavy intermediate work is kept in RAM (/dev/shm / tmpfs) wherever possible, so only final outputs are written back to disk. Each run gets a scratch directory of its own in there, so several can run at once without sharing one.

A smaller machine runs them too — just with the CPU roads and less overlap.

Platform: these target Linux. macOS support is aspirational: everything is written to work there, but no macOS machine has run it yet, so treat it as untested rather than as broken (see Running on a Mac). On a Windows machine WSL2 is the way to run them. Native Windows is experimental for now: the tool-free cases import and run there, but the commands that drive the media tools and POSIX coreutils expect a POSIX host. Neither Windows nor macOS has a RAM-backed filesystem, so the RAM scratch described below lands in %TEMP% / $TMPDIR on a normal disk; a RAM disk mounted by hand works if ramScratchBase points at it.

At a glance

Each command has a page of its own under docs/commands/, laid out the same way: what it does and its usage line, an at a glance table (what it takes and writes, whether it changes the input, what a rerun does, whether it reaches the network), then the details, and at the foot the shared rules that apply to it.

Audio

Command Does
concat-audio One audiobook file per input subfolder, with chapters
convert-audio Spoken-word audio → low-bitrate Opus or xHE-AAC
convert-and-concat The two above chained, intermediate tree in RAM
transcribe-audio Audio and video → whisper transcripts in a mirrored folder
ingest-music Downloads → clean lossless FLAC library
ytdlp Download tables of podcast feeds as audio or video, Windows or Linux

Video

Command Does
convert-video Re-encode a video library (AV1/x265 + Opus)
ingest-movies Sort, clean and improve a movie library in place
plex-letterboxd-sync Sync watched films between Plex and Letterboxd

Books, comics and images

Command Does
ingest-books E-books → clean, uniform epub/pdf library
read-library E-books → audiobooks (Opus + lossless), read aloud by a TTS engine
convert-comics .cbr/.cbz/.cb7 and comic PDFs → .cbz of AVIF pages
convert-images Batch image → AVIF / WebP / JPEG XL (or back to JPEG)

Names and folder structure

Command Does
clean-folder-structure Apply the shared name cleaners across a tree
find-fragment-candidates Report the recurring name fragments a library still carries
find-gaps A tree of what is missing from the numbered, episode and dated runs
cue-to-chapters A .cue sheet → an OGM chapter file

Library census

Command Does
content-census Census one or more libraries into one CSV per content type
content-census-bi Roll those reports up into DuckDB hypercubes and a pivot-table page

Every command prints its arguments, options and defaults with -h (or --help), which needs none of the media tools installed — so these pages are about what the commands do and the rules they all follow, and name a flag only where it changes what a command does. cue-to-chapters is the one exception: it takes two file names and no options, so any argument list but those two prints its usage and fails.

Every option has both forms: -j 8 and --jobs 8 (or --jobs=8) are the same option. Abbreviations are not accepted — --job is not --jobs — so a new option can never change what a command you already type means.

Requirements

  • Python 3.11.4+, and one package with it: mutagen, which the install brings in
  • A UTF-8 locale (accented/multibyte filenames are handled character-wise)
  • Per-tool external dependencies (see each command's -h output). Across the set: ffmpeg, mkvtoolnix, dovi_tool, hdr10plus_tool, mediainfo, ImageMagick, rsync, yt-dlp, fdupes, unrar/unzip/7z/tar/zstd, zip, poppler-utils (pdftoppm, pdfinfo, pdfimages, pdftotext), whisper-ctranslate2, ffsubsync, tree, beets, Calibre's ebook-convert, Ghostscript (gs), duckdb, subcleaner, curl (for TheMovieDB, Plex and Letterboxd) and wc — that last one being the only piece of coreutils anything here still shells out to.
  • convert-audio -o xheaac additionally needs exhale, which ffmpeg cannot stand in for: it decodes the codec but does not encode it. No distribution packages exhale, so it has to be built (see convert-audio).
  • read-library additionally needs a local ebook2audiobook checkout and a Python 3.10–3.12 to build its environment from; everything inside that environment is installed by the checkout itself (see read-library).
  • convert-video -u additionally needs an NVIDIA GPU and a VapourSynth + TensorRT environment of its own, one piece of which has to be built (see convert-video).
  • The GPU road for AVIF in convert-images and convert-comics is av1gpu, which has to be built (see convert-images); without it they take the CPU road described under Built to use the whole machine.

What a run does when one of these is missing, what does not work on a Mac yet, and which ffmpeg build a run picks are in Requirements in detail. How to keep all of them up to date with one command is under Keeping them up to date.

Settings

Logins, API keys and the knobs the commands are tuned with are environment variables, read from the environment a command starts in or from one settings file, ~/.config/medialib/settings, written the way a shell profile writes them. A file that holds a secret has to be private (chmod 600). Every setting, what it does and which commands read it is listed in Settings.

File safety

Renaming never overwrites an existing file and never writes outside the input and output folders you gave, and the renames skipped for safety are listed at the end of the run. A run can be stopped at any point and still reports what it did. The full rules, including which commands reach the network, are in File safety.

License / credits

MIT — see LICENSE. Use it, change it, ship it; there is no warranty.

Authored by David Ernst, qwen and claude opus.

About

Twenty commands for building and keeping a media library: transcoding video, audio, images and comics, ingesting films, music and books, cleaning names, and a census of what is in it

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages