From d6b6cb1bfd71e95aeda2e784c214ddffcc777fd1 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Sun, 22 Feb 2026 08:41:04 +0100 Subject: feat: initial release of transcode.sh v1.0.0 Batch transcode helper for media files using ffmpeg. Encoding parameters are supplied by user-defined preset files (shell snippets that set an `ffargs` array) stored under ${XDG_CONFIG_HOME:-$HOME/.config}/transcode.sh/presets/. Key capabilities: - Probes input codec and pixel format via ffprobe; derives an output pixel format that preserves chroma subsampling and bit depth. - Per-user and per-invocation codec skip lists to leave already-encoded files untouched. - Atomic in-place replacement: encodes to a temp file in the same directory, then renames on success. - --only-if-smaller: discard the result if it is larger than the original. - --saving: append filename, original/new sizes and percentage saved to a log file after each successful encode. - --dry-run, --verbose, --quiet, --nice and --continue flags. - Respects the NO_COLOR standard. - Script hardening: strict PATH, safe IFS, errtrace, nounset, pipefail. Also included: - Man page (transcode.sh.1) - Bash completion script (transcode.sh.bash-completion) - README.md - .gitmessage commit message template License: BSD-3-Clause --- README.md | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 README.md (limited to 'README.md') diff --git a/README.md b/README.md new file mode 100644 index 0000000..65db49a --- /dev/null +++ b/README.md @@ -0,0 +1,176 @@ +# transcode.sh + +> Batch transcode helper for media files using [ffmpeg](https://ffmpeg.org/). + +`transcode.sh` re-encodes media files in place using user-defined *presets* — +small shell snippets that supply the ffmpeg arguments. It probes each input +file to detect the video codec and pixel format, skips files whose codec is on +the skip list, selects an appropriate output pixel format automatically, and +replaces the original atomically on success. + +## Features + +- **Preset-driven** — encoding parameters live in plain shell files, not + hard-coded flags. +- **Batch processing** — pass files on the command line or via a list file + (`-f`). +- **Codec skip list** — per-user and per-invocation lists of codecs to leave + untouched (e.g. skip files already encoded as AV1). +- **Only-if-smaller mode** (`-l`) — discard the re-encoded file if it is + larger than the original. +- **Savings log** (`-s`) — append filename, original size, new size and + percentage saved to a log file after each successful encode. +- **Dry-run** (`-n`) — preview what would happen without touching any files. +- **Nice** — runs ffmpeg at niceness 19 by default to avoid starving other + processes; configurable with `-N`. +- **Respects [NO\_COLOR](https://no-color.org/)**. + +## Requirements + +| Tool | Required | Notes | +|------|----------|-------| +| `ffmpeg` | always | encoding | +| `ffprobe` | always | codec/format detection | +| `nice` | always | process priority control | +| `bc` | only with `--saving` | percentage calculation | + +## Installation + +```sh +# Clone the repo +git clone https://codeberg.org/yourname/transcode.sh.git +cd transcode.sh + +# Make the script executable +chmod +x transcode.sh + +# Optional: install to a directory in your PATH +install -Dm755 transcode.sh ~/.local/bin/transcode.sh + +# Optional: install the man page +install -Dm644 transcode.1 ~/.local/share/man/man1/transcode.1 + +# Optional: install bash completion +install -Dm644 transcode.sh.bash-completion \ + /etc/bash_completion.d/transcode.sh +# or for your user only (requires bash-completion ≥ 2.2): +install -Dm644 transcode.sh.bash-completion \ + ~/.local/share/bash-completion/completions/transcode.sh +``` + +> **PATH note:** the script resets `PATH` to `/bin:/usr/bin:/usr/local/bin` +> for security. If your `ffmpeg` lives elsewhere (e.g. Homebrew on macOS, +> Nix), prepend its directory: +> ```sh +> PATH="/opt/homebrew/bin:$PATH" transcode.sh input.mp4 +> ``` + +## Configuration + +### Presets + +Presets live in: + +``` +${XDG_CONFIG_HOME:-$HOME/.config}/transcode.sh/presets/.sh +``` + +Each preset is sourced as Bash and must define an array named `ffargs`. +The variable `output_pixel_format` is available and contains the +automatically selected pixel format (derived from the input file). + +**Example — `~/.config/transcode.sh/presets/default.sh`:** + +```sh +ffargs=( + -c:v:0 libsvtav1 + -crf 30 + -preset 6 + -pix_fmt "$output_pixel_format" +) +``` + +> **Security:** presets are executed as shell code. Only use presets from +> trusted sources. + +### Codec skip list + +To permanently skip files that are already in a particular codec, add codec +names (one per line) to: + +``` +${XDG_CONFIG_HOME:-$HOME/.config}/transcode.sh/skip.conf +``` + +**Example — skip files already encoded as AV1 or HEVC:** + +``` +av1 +hevc +``` + +## Usage + +``` +transcode.sh [OPTION] [--] FILE... +``` + +| Option | Description | +|--------|-------------| +| `-c`, `--continue` | Continue to next file if ffmpeg fails | +| `-f PATH`, `--encodefile PATH`, `--encodefile=PATH` | Read file list from PATH (one per line) | +| `-n`, `--dry-run` | Show what would be done; don't run ffmpeg | +| `-N VALUE`, `--nice VALUE`, `--nice=VALUE` | Niceness value for ffmpeg (default: 19) | +| `-s`, `--saving` | Log filesize savings after each encode | +| `--saving-file PATH`, `--saving-file=PATH` | Savings log path (default: `transcode_savings`) | +| `-S LIST`, `--skip-codec LIST`, `--skip-codec=LIST` | Codecs to skip (comma/space/colon separated) | +| `-l`, `--only-if-smaller` | Only replace original if new file is smaller | +| `-p NAME`, `--preset NAME`, `--preset=NAME` | Preset to use (default: `default`) | +| `-q`, `--quiet` | Suppress all output (overrides `-v`) | +| `-v`, `--verbose` | More detailed output | +| `--color` / `--no-color` | Force or disable colored output | +| `--version` | Print version information | +| `-h`, `-?`, `--help` | Show help and exit | + +### Examples + +```sh +# Transcode a single file with the default preset +transcode.sh video.mp4 + +# Transcode a list of files and record size savings +transcode.sh --saving --encodefile list.txt + +# Dry-run with verbose output to inspect detected formats +transcode.sh --dry-run --verbose my_movie.mkv + +# Use a custom preset, only keep result if smaller, skip AV1 inputs +transcode.sh --preset av1_fast --only-if-smaller --skip-codec av1 /media/films/*.mkv + +# Run at a moderate priority and continue past failures +transcode.sh --nice 10 --continue *.mp4 +``` + +## Debugging + +```sh +# High-level state messages +DEBUG=1 transcode.sh input.mkv + +# Full bash execution trace +TRACE=1 transcode.sh input.mkv +``` + +## Exit codes + +| Code | Meaning | +|------|---------| +| 0 | Success | +| 1 | Runtime failure (ffmpeg error on one or more files) | +| 2 | Usage error (unknown option, missing argument) | +| 3 | Configuration error (missing or invalid preset) | +| 127 | Missing dependency | + +## License + +[BSD-3-Clause](LICENSES/BSD-3-Clause.txt) © 2025 Dennis Fink \ -- cgit v1.3.1