# 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 \