diff options
Diffstat (limited to '')
| -rw-r--r-- | README.md | 84 | ||||
| -rwxr-xr-x | transcode.sh | 345 | ||||
| -rw-r--r-- | transcode.sh.1 | 160 | ||||
| -rw-r--r-- | transcode.sh.bash-completion.sh | 119 |
4 files changed, 378 insertions, 330 deletions
@@ -153,11 +153,12 @@ An optional TOML configuration file can be placed at: ${XDG_CONFIG_HOME:-$HOME/.config}/transcode.sh/config.toml ``` -Use `--config-file FILE` to load an alternative path. CLI flags generally take -precedence over values in the config file. Skip codecs are additive by default: -configured codecs and CLI codecs are merged unless `--skip-codec-override` is -used. The file must be valid TOML — an unparseable file is a hard error. -Requires `tomlq` when the file is present. +Use `--config-file FILE` to load an alternative path, or `--no-config` to skip +configuration loading entirely. CLI flags generally take precedence over values +in the config file. Skip codecs are additive by default: configured codecs and +CLI codecs are merged unless `--skip-codec-override` is used. The file must be +valid TOML — an unparseable file is a hard error. Requires `tomlq` when the +file is present. **Example `config.toml`:** @@ -182,18 +183,18 @@ quiet = false | Section | Key | Type | CLI equivalent | |---------|-----|------|----------------| -| `[encoding]` | `backup_dir` | string | `--backup-dir` | -| `[encoding]` | `hwaccel` | string or boolean | `--hwaccel` / `--no-hwaccel` | -| `[encoding]` | `nice` | integer | `-N` | | `[encoding]` | `preset` | string | `-p` | -| `[encoding]` | `verify_output` | boolean | `--verify-output` | +| `[encoding]` | `nice` | integer | `-N` | +| `[encoding]` | `hwaccel` | string or boolean | `--hwaccel` / `--no-hwaccel` | | `[encoding]` | `video_stream` | string | `--video-stream` | -| `[output]` | `quiet` | boolean | `-q` | -| `[output]` | `verbose` | boolean | `-v` | -| `[output]` | `ffmpeg_loglevel` | string | `--ffmpeg-loglevel` | +| `[encoding]` | `backup_dir` | string | `--backup-dir` | +| `[encoding]` | `verify_output` | boolean | `--verify-output` | +| `[skip]` | `codecs` | array of strings | `-S` / `--skip-codec-override` | | `[size_report]` | `enabled` | boolean | `-s` / `--no-size-report` | | `[size_report]` | `file` | string | `--size-report-file` | -| `[skip]` | `codecs` | array of strings | `-S` / `--skip-codec-override` | +| `[output]` | `ffmpeg_loglevel` | string | `--ffmpeg-loglevel` | +| `[output]` | `quiet` | boolean | `-q` | +| `[output]` | `verbose` | boolean | `-v` | > **Note:** `[skip] codecs` from the config file and `--skip-codec` from the > CLI are **merged** by default — both sources contribute to the skip list. Use @@ -225,35 +226,68 @@ deprecation warning is printed at startup. Migrate its contents to transcode.sh [OPTION] [--] FILE... ``` +### Input options + | Option | Description | |--------|-------------| -| `-c`, `--continue` | Continue to next file if ffmpeg fails | -| `--no-continue` | Do not continue with the next file if ffmpeg fails | -| `--verify-output` | Probe output with ffprobe before replacing original (default) | -| `--no-verify-output` | Skip the post-encode integrity check | | `--config-file FILE`, `--config-file=FILE` | Load configuration from FILE instead of the default path | +| `--no-config` | Do not load any configuration file | | `-f PATH`, `--encode-file PATH`, `--encode-file=PATH` | Read file list from PATH (one per line) | -| `-n`, `--dry-run` | Show what would be done; don't run ffmpeg | -| `--backup-dir DIR`, `--backup-dir=DIR` | Copy originals to an existing backup directory before replacing them | + +### Encoding options + +| Option | Description | +|--------|-------------| +| `-p NAME`, `--preset NAME`, `--preset=NAME` | Preset to use (default: `default`) | | `-N VALUE`, `--nice VALUE`, `--nice=VALUE` | Nice adjustment for ffmpeg (default: 19) | | `--hwaccel [METHOD]`, `--hwaccel=METHOD` | Enable hardware acceleration; METHOD defaults to `auto` if omitted (e.g. `cuda`, `vaapi`, `videotoolbox`); enabled by default | | `--no-hwaccel` | Disable hardware acceleration (omit `-hwaccel` from ffmpeg invocation) | -| `-s`, `--size-report` | Print per-file size feedback and write a status TSV log | -| `--no-size-report` | Disable a size report enabled in `config.toml` | -| `--size-report-file PATH`, `--size-report-file=PATH` | Size report TSV path (default: `transcode_size_report`) | +| `--video-stream STREAM_SELECTOR`, `--video-stream=STREAM_SELECTOR` | Select the input video stream to probe for preset helper variables, e.g. `v:0` or `v:1` (default: `v:0`) | + +### Skip options + +| Option | Description | +|--------|-------------| | `-S LIST`, `--skip-codec LIST`, `--skip-codec=LIST` | Add codecs to the effective skip list (comma/space/colon separated) | | `--skip-codec-override` | Use only codecs from `--skip-codec`, ignoring `[skip].codecs` from config | + +### Processing options + +| Option | Description | +|--------|-------------| +| `-n`, `--dry-run` | Show what would be done; don't run ffmpeg | +| `--backup-dir DIR`, `--backup-dir=DIR` | Copy originals to an existing backup directory before replacing them | | `-l`, `--only-if-smaller` | Only replace original if new file is smaller | | `--no-only-if-smaller` | Do replace original even if new file is bigger | -| `-p NAME`, `--preset NAME`, `--preset=NAME` | Preset to use (default: `default`) | -| `--video-stream STREAM_SELECTOR`, `--video-stream=STREAM_SELECTOR` | Select the input video stream to probe for preset helper variables, e.g. `v:0` or `v:1` (default: `v:0`) | +| `--verify-output` | Probe output with ffprobe before replacing original (default) | +| `--no-verify-output` | Skip the post-encode integrity check | +| `-c`, `--continue` | Continue to next file if ffmpeg fails | +| `--no-continue` | Do not continue with the next file if ffmpeg fails | + +### Size report options + +| Option | Description | +|--------|-------------| +| `-s`, `--size-report` | Print per-file size feedback and write a status TSV log | +| `--no-size-report` | Disable a size report enabled in config | +| `--size-report-file PATH`, `--size-report-file=PATH` | Size report TSV path (default: `transcode_size_report`) | + +### Display options + +| Option | Description | +|--------|-------------| | `--ffmpeg-loglevel LEVEL`, `--ffmpeg-loglevel=LEVEL` | Specify the loglevel to pass to ffmpeg (default: `fatal`) | | `-q`, `--quiet` | Suppress all output (overrides `-v`) | | `-v`, `--verbose` | More detailed output | | `--color` / `--no-color` | Force or disable colored output | + +### General options + +| Option | Description | +|--------|-------------| +| `-h`, `-?`, `--help` | Show help and exit | | `--version` | Print version information | | `--list-presets` | List available presets (name + description) and exit | -| `-h`, `-?`, `--help` | Show help and exit | ### Examples diff --git a/transcode.sh b/transcode.sh index b9aee8b..fe18b0d 100755 --- a/transcode.sh +++ b/transcode.sh @@ -285,37 +285,39 @@ ${BOLD}${BLUE}Usage:${ALL_OFF} ${BOLD}${MAGENTA}%s${ALL_OFF} ${BOLD}${YELLOW}[OP Long options that take a value also accept ${BOLD}${YELLOW}--option${ALL_OFF}${BOLD}${CYAN}=${ALL_OFF}${BOLD}${GREEN}VALUE${ALL_OFF} syntax. +${BOLD}${BLUE}Input options:${ALL_OFF} + ${BOLD}${YELLOW}--config-file${ALL_OFF} ${BOLD}${GREEN}FILE${ALL_OFF} load configuration from FILE instead of the default path + ${BOLD}${YELLOW}--no-config${ALL_OFF} do not load any configuration file + ${BOLD}${YELLOW}-f, --encode-file${ALL_OFF} ${BOLD}${GREEN}FILE${ALL_OFF} file containing a list of files to encode + ${BOLD}${BLUE}Encoding options:${ALL_OFF} ${BOLD}${YELLOW}-p, --preset${ALL_OFF} ${BOLD}${GREEN}NAME${ALL_OFF} load ffmpeg arguments from a preset (default: ${BOLD}${RED}%s${ALL_OFF}) ${BOLD}${YELLOW}-N, --nice${ALL_OFF} ${BOLD}${GREEN}VALUE${ALL_OFF} nice adjustment for ffmpeg (default: ${BOLD}${RED}%d${ALL_OFF}) - ${BOLD}${YELLOW}-n, --dry-run${ALL_OFF} show what would be done, do not run ffmpeg - ${BOLD}${YELLOW} --backup-dir${ALL_OFF} ${BOLD}${GREEN}DIR${ALL_OFF} backup original files to DIR instead of overwriting them - ${BOLD}${YELLOW}--hwaccel${ALL_OFF} ${BOLD}${GREEN}[METHOD]${ALL_OFF} enable hardware acceleration; METHOD defaults to ${BOLD}${RED}%s${ALL_OFF} - if omitted + ${BOLD}${YELLOW}--hwaccel${ALL_OFF} ${BOLD}${GREEN}[METHOD]${ALL_OFF} enable hardware acceleration; METHOD defaults to ${BOLD}${RED}%s${ALL_OFF} if omitted + ${BOLD}${YELLOW}--no-hwaccel${ALL_OFF} disable hardware acceleration (do not pass ${BOLD}${YELLOW}-hwaccel${ALL_OFF} to ffmpeg) ${BOLD}${YELLOW}--video-stream${ALL_OFF} ${BOLD}${GREEN}STREAM_SELECTOR${ALL_OFF} video stream to probe for preset helper variables (default: ${BOLD}${RED}%s${ALL_OFF}) - ${BOLD}${YELLOW} --no-hwaccel${ALL_OFF} disable hardware acceleration (do not pass ${BOLD}${YELLOW}-hwaccel${ALL_OFF} to ffmpeg) + +${BOLD}${BLUE}Skip options:${ALL_OFF} + ${BOLD}${YELLOW}-S, --skip-codec${ALL_OFF} ${BOLD}${GREEN}LIST${ALL_OFF} skip files with these codecs; ${BOLD}${GREEN}LIST${ALL_OFF} is comma, space, or colon separated + ${BOLD}${YELLOW}--skip-codec-override${ALL_OFF} use only codecs from ${BOLD}${YELLOW}--skip-codec${ALL_OFF}, ignoring ${BOLD}${CYAN}[skip].codecs${ALL_OFF} from config + +${BOLD}${BLUE}Processing options:${ALL_OFF} + ${BOLD}${YELLOW}-n, --dry-run${ALL_OFF} show what would be done, do not run ffmpeg + ${BOLD}${YELLOW}--backup-dir${ALL_OFF} ${BOLD}${GREEN}DIR${ALL_OFF} backup original files to DIR instead of overwriting them ${BOLD}${YELLOW}-l, --only-if-smaller${ALL_OFF} only replace original if new file is smaller ${BOLD}${YELLOW}--no-only-if-smaller${ALL_OFF} do replace original even if new file is bigger - ${BOLD}${YELLOW}-c, --continue${ALL_OFF} continue with the next file even if ffmpeg fails - ${BOLD}${YELLOW}--no-continue${ALL_OFF} do not continue with the next file if ffmpeg fails ${BOLD}${YELLOW}--verify-output${ALL_OFF} probe output with ffprobe before replacing original (default) ${BOLD}${YELLOW}--no-verify-output${ALL_OFF} skip the post-encode integrity check - -${BOLD}${BLUE}Input options:${ALL_OFF} - ${BOLD}${YELLOW}--config-file${ALL_OFF} ${BOLD}${GREEN}FILE${ALL_OFF} load configuration from FILE instead of the default path - ${BOLD}${YELLOW}-f, --encode-file${ALL_OFF} ${BOLD}${GREEN}FILE${ALL_OFF} file containing a list of files to encode - ${BOLD}${YELLOW}-S, --skip-codec${ALL_OFF} ${BOLD}${GREEN}LIST${ALL_OFF} skip files with these codecs; - ${BOLD}${GREEN}LIST${ALL_OFF} is comma, space, or colon separated - ${BOLD}${YELLOW}--skip-codec-override${ALL_OFF} use only codecs from --skip-codec, - ignoring [skip].codecs from config + ${BOLD}${YELLOW}-c, --continue${ALL_OFF} continue with the next file even if ffmpeg fails + ${BOLD}${YELLOW}--no-continue${ALL_OFF} do not continue with the next file if ffmpeg fails ${BOLD}${BLUE}Size report options:${ALL_OFF} ${BOLD}${YELLOW}-s, --size-report${ALL_OFF} print size feedback and write a status TSV log - ${BOLD}${YELLOW}--no-size-report${ALL_OFF} disable size reporting from config.toml + ${BOLD}${YELLOW}--no-size-report${ALL_OFF} disable size reporting from config ${BOLD}${YELLOW}--size-report-file${ALL_OFF} ${BOLD}${GREEN}FILE${ALL_OFF} path for the size report log (default: ${BOLD}${RED}%s${ALL_OFF}) -${BOLD}${BLUE}Output options:${ALL_OFF} - ${BOLD}${YELLOW}--ffmpeg-loglevel${ALL_OFF} specify the loglevel to pass to ffmpeg (default: ${BOLD}${RED}%s${ALL_OFF}) +${BOLD}${BLUE}Display options:${ALL_OFF} + ${BOLD}${YELLOW}--ffmpeg-loglevel${ALL_OFF} ${BOLD}${GREEN}LEVEL${ALL_OFF} specify the loglevel to pass to ffmpeg (default: ${BOLD}${RED}%s${ALL_OFF}) ${BOLD}${YELLOW}-q, --quiet${ALL_OFF} suppress all output; takes precedence over ${BOLD}${YELLOW}-v${ALL_OFF} ${BOLD}${YELLOW}-v, --verbose${ALL_OFF} explain what is being done ${BOLD}${YELLOW}--color${ALL_OFF} force colored output @@ -336,7 +338,7 @@ ${BOLD}${BLUE}Configuration files:${ALL_OFF} ${BOLD}${GREEN}input_frame_rate${ALL_OFF} raw fraction from ffprobe (e.g. 30000/1001) ${BOLD}${GREEN}input_fps${ALL_OFF} input_frame_rate rounded to nearest integer ${BOLD}${GREEN}output_gop_size${ALL_OFF} ~5 s GOP derived from input_fps, capped at 300 - + ${BOLD}${RED}presets are sourced as shell code; only use trusted presets from trusted directories.${ALL_OFF} @@ -354,8 +356,8 @@ ${BOLD}${BLUE}Examples:${ALL_OFF} "$NICE_VALUE" \ "$HWACCEL_VALUE" \ "$VIDEO_STREAM" \ - "$SIZE_REPORT_FILE" \ "$FFMPEG_LOGLEVEL" \ + "$SIZE_REPORT_FILE" \ "$PRESET_DIR" \ "$CONFIG_FILE" \ "$SCRIPTNAME" \ @@ -1460,84 +1462,6 @@ fi # variables so load_config() can respect CLI-over-config precedence. while [[ $# -gt 0 ]]; do case "$1" in - -h | --help | -\?) - print_help - exit $EXIT_OK - ;; - --version) - print_version - exit $EXIT_OK - ;; - --list-presets) - list_presets - exit $EXIT_OK - ;; - -q | --quiet) - QUIET=1 - _CLI_QUIET=1 - shift - ;; - -v | --verbose) - VERBOSE=1 - _CLI_VERBOSE=1 - shift - ;; - --color) - ENABLE_COLOR=1 - # Propagate the explicit color choice to ffmpeg/libav subprocesses. - export AV_LOG_FORCE_COLOR=1 - setup_colors - shift - ;; - --no-color) - ENABLE_COLOR=0 - # Propagate the explicit color choice to ffmpeg/libav subprocesses. - export AV_LOG_FORCE_NOCOLOR=1 - setup_colors - shift - ;; - -c | --continue) - CONTINUE_ON_FAIL=1 - _CLI_CONTINUE=1 - shift - ;; - --no-continue) - CONTINUE_ON_FAIL=0 - _CLI_CONTINUE=1 - shift - ;; - --verify-output) - VERIFY_OUTPUT=1 - _CLI_VERIFY_OUTPUT=1 - shift - ;; - --no-verify-output) - VERIFY_OUTPUT=0 - _CLI_VERIFY_OUTPUT=1 - shift - ;; - --backup-dir) - if [[ $# -lt 2 ]]; then - error "Missing value for $1" - exit $EXIT_USAGE_ERROR - fi - if [[ -z "$2" ]]; then - error "Value for $1 must not be empty" - exit $EXIT_USAGE_ERROR - fi - BACKUP_DIR="$2" - _CLI_BACKUP_DIR=1 - shift 2 - ;; - --backup-dir=*) - if [[ -z "${1#*=}" ]]; then - error "Value for --backup-dir must not be empty" - exit $EXIT_USAGE_ERROR - fi - BACKUP_DIR="${1#*=}" - _CLI_BACKUP_DIR=1 - shift - ;; --config-file) if [[ $# -lt 2 ]]; then error "Missing value for $1" @@ -1585,8 +1509,26 @@ while [[ $# -gt 0 ]]; do ENCODE_FILE="${1#*=}" shift ;; - -n | --dry-run) - DRY_RUN=1 + -p | --preset) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + if [[ -z "$2" ]]; then + error "Value for $1 must not be empty" + exit $EXIT_USAGE_ERROR + fi + PRESET_NAME="$2" + _CLI_PRESET=1 + shift 2 + ;; + --preset=*) + if [[ -z "${1#*=}" ]]; then + error "Value for --preset must not be empty" + exit $EXIT_USAGE_ERROR + fi + PRESET_NAME="${1#*=}" + _CLI_PRESET=1 shift ;; -N | --nice) @@ -1603,36 +1545,62 @@ while [[ $# -gt 0 ]]; do _CLI_NICE=1 shift ;; - -s | --size-report) - SIZE_REPORT=1 - _CLI_SIZE_REPORT=1 + --hwaccel) + HWACCEL=1 + # Peek at the next argument: use it as the METHOD only if it is + # non-empty and does not look like an option flag. + if [[ $# -ge 2 && -n "$2" && "$2" != -* ]]; then + HWACCEL_VALUE="$2" + shift 2 + else + HWACCEL_VALUE="auto" + shift + fi + _CLI_HWACCEL=1 + ;; + --hwaccel=*) + HWACCEL=1 + HWACCEL_VALUE="${1#*=}" + if [[ -z "$HWACCEL_VALUE" ]]; then + error "Value for --hwaccel must not be empty" + exit $EXIT_USAGE_ERROR + fi + _CLI_HWACCEL=1 shift ;; - --no-size-report) - SIZE_REPORT=0 - _CLI_SIZE_REPORT=1 + --no-hwaccel) + HWACCEL=0 + _CLI_HWACCEL=1 shift ;; - --size-report-file) + --video-stream) if [[ $# -lt 2 ]]; then - error "Missing value for $1" + error "Missing value for:" "$1" exit $EXIT_USAGE_ERROR fi if [[ -z "$2" ]]; then error "Value for $1 must not be empty" exit $EXIT_USAGE_ERROR fi - SIZE_REPORT_FILE="$2" - _CLI_SIZE_REPORT_FILE=1 + if ! validate_stream_selector "$2"; then + error "Invalid stream selector:" "$2" + exit $EXIT_USAGE_ERROR + fi + VIDEO_STREAM="$2" + _CLI_VIDEO_STREAM=1 shift 2 ;; - --size-report-file=*) + --video-stream=*) if [[ -z "${1#*=}" ]]; then - error "Value for --size-report-file must not be empty" + error "Value for --video-stream must not be empty" exit $EXIT_USAGE_ERROR fi - SIZE_REPORT_FILE="${1#*=}" - _CLI_SIZE_REPORT_FILE=1 + if ! validate_stream_selector "${1#*=}"; then + error "Invalid stream selector:" "${1#*=}" + exit $EXIT_USAGE_ERROR + fi + VIDEO_STREAM="${1#*=}" + _CLI_VIDEO_STREAM=1 shift ;; -S | --skip-codec) @@ -1651,6 +1619,32 @@ while [[ $# -gt 0 ]]; do _CLI_SKIP_CODECS_OVERRIDE=1 shift ;; + -n | --dry-run) + DRY_RUN=1 + shift + ;; + --backup-dir) + if [[ $# -lt 2 ]]; then + error "Missing value for $1" + exit $EXIT_USAGE_ERROR + fi + if [[ -z "$2" ]]; then + error "Value for $1 must not be empty" + exit $EXIT_USAGE_ERROR + fi + BACKUP_DIR="$2" + _CLI_BACKUP_DIR=1 + shift 2 + ;; + --backup-dir=*) + if [[ -z "${1#*=}" ]]; then + error "Value for --backup-dir must not be empty" + exit $EXIT_USAGE_ERROR + fi + BACKUP_DIR="${1#*=}" + _CLI_BACKUP_DIR=1 + shift + ;; -l | --only-if-smaller) ONLY_IF_SMALLER=1 _CLI_ONLY_IF_SMALLER=1 @@ -1661,35 +1655,37 @@ while [[ $# -gt 0 ]]; do _CLI_ONLY_IF_SMALLER=1 shift ;; - --hwaccel) - HWACCEL=1 - # Peek at the next argument: use it as the METHOD only if it is - # non-empty and does not look like an option flag. - if [[ $# -ge 2 && -n "$2" && "$2" != -* ]]; then - HWACCEL_VALUE="$2" - shift 2 - else - HWACCEL_VALUE="auto" - shift - fi - _CLI_HWACCEL=1 + --verify-output) + VERIFY_OUTPUT=1 + _CLI_VERIFY_OUTPUT=1 + shift ;; - --hwaccel=*) - HWACCEL=1 - HWACCEL_VALUE="${1#*=}" - if [[ -z "$HWACCEL_VALUE" ]]; then - error "Value for --hwaccel must not be empty" - exit $EXIT_USAGE_ERROR - fi - _CLI_HWACCEL=1 + --no-verify-output) + VERIFY_OUTPUT=0 + _CLI_VERIFY_OUTPUT=1 shift ;; - --no-hwaccel) - HWACCEL=0 - _CLI_HWACCEL=1 + -c | --continue) + CONTINUE_ON_FAIL=1 + _CLI_CONTINUE=1 shift ;; - -p | --preset) + --no-continue) + CONTINUE_ON_FAIL=0 + _CLI_CONTINUE=1 + shift + ;; + -s | --size-report) + SIZE_REPORT=1 + _CLI_SIZE_REPORT=1 + shift + ;; + --no-size-report) + SIZE_REPORT=0 + _CLI_SIZE_REPORT=1 + shift + ;; + --size-report-file) if [[ $# -lt 2 ]]; then error "Missing value for $1" exit $EXIT_USAGE_ERROR @@ -1698,17 +1694,17 @@ while [[ $# -gt 0 ]]; do error "Value for $1 must not be empty" exit $EXIT_USAGE_ERROR fi - PRESET_NAME="$2" - _CLI_PRESET=1 + SIZE_REPORT_FILE="$2" + _CLI_SIZE_REPORT_FILE=1 shift 2 ;; - --preset=*) + --size-report-file=*) if [[ -z "${1#*=}" ]]; then - error "Value for --preset must not be empty" + error "Value for --size-report-file must not be empty" exit $EXIT_USAGE_ERROR fi - PRESET_NAME="${1#*=}" - _CLI_PRESET=1 + SIZE_REPORT_FILE="${1#*=}" + _CLI_SIZE_REPORT_FILE=1 shift ;; --ffmpeg-loglevel) @@ -1733,36 +1729,43 @@ while [[ $# -gt 0 ]]; do _CLI_FFMPEG_LOGLEVEL=1 shift ;; - --video-stream) - if [[ $# -lt 2 ]]; then - error "Missing value for:" "$1" - exit $EXIT_USAGE_ERROR - fi - if [[ -z "$2" ]]; then - error "Value for $1 must not be empty" - exit $EXIT_USAGE_ERROR - fi - if ! validate_stream_selector "$2"; then - error "Invalid stream selector:" "$2" - exit $EXIT_USAGE_ERROR - fi - VIDEO_STREAM="$2" - _CLI_VIDEO_STREAM=1 - shift 2 + + -q | --quiet) + QUIET=1 + _CLI_QUIET=1 + shift ;; - --video-stream=*) - if [[ -z "${1#*=}" ]]; then - error "Value for --video-stream must not be empty" - exit $EXIT_USAGE_ERROR - fi - if ! validate_stream_selector "${1#*=}"; then - error "Invalid stream selector:" "${1#*=}" - exit $EXIT_USAGE_ERROR - fi - VIDEO_STREAM="${1#*=}" - _CLI_VIDEO_STREAM=1 + -v | --verbose) + VERBOSE=1 + _CLI_VERBOSE=1 + shift + ;; + --color) + ENABLE_COLOR=1 + # Propagate the explicit color choice to ffmpeg/libav subprocesses. + export AV_LOG_FORCE_COLOR=1 + setup_colors + shift + ;; + --no-color) + ENABLE_COLOR=0 + # Propagate the explicit color choice to ffmpeg/libav subprocesses. + export AV_LOG_FORCE_NOCOLOR=1 + setup_colors shift ;; + -h | --help | -\?) + print_help + exit $EXIT_OK + ;; + --version) + print_version + exit $EXIT_OK + ;; + --list-presets) + list_presets + exit $EXIT_OK + ;; --) shift REMAINING_ARGS+=("$@") diff --git a/transcode.sh.1 b/transcode.sh.1 index 524ba68..caa4c1a 100644 --- a/transcode.sh.1 +++ b/transcode.sh.1 @@ -45,30 +45,7 @@ playable media file before the original is replaced. If the integrity check fails the temporary file is removed and the encode is treated as a runtime failure, leaving the original untouched. .SH OPTIONS -.TP -.BR \-c ", " \-\-continue -Continue processing the next file even if -.BR ffmpeg (1) -fails on the current one. Without this flag the script exits immediately -on the first failure. -.TP -.BR \-\-no\-continue -Do not continue processing next file even if -.BR ffmpeg (1) -fails on the current one. -.TP -.BR \-\-verify\-output -After encoding, probe the temporary output file with -.BR ffprobe (1) -to confirm it is a valid, playable media file before replacing the -original. Enabled by default. -.TP -.BR \-\-no\-verify\-output -Skip the post-encode integrity check. The original is replaced as long -as -.BR ffmpeg (1) -exits successfully. Useful for large batch jobs on trusted encoders -where the additional probe round-trip is undesirable. +.SS "Input options" .TP .BR \-\-config\-file " \fIPATH\fR, " \-\-config\-file= \fIPATH\fR Load configuration from \fIPATH\fR instead of the default location @@ -79,23 +56,26 @@ Requires .BR tomlq (1) when the file is present. .TP +.BR \-\-no\-config +Do not load any configuration file. +.TP .BR \-f " \fIPATH\fR, " \-\-encode-file " \fIPATH\fR, " \-\-encode-file= \fIPATH\fR Read the list of files to encode from \fIPATH\fR (one file per line) instead of taking files from the command line. +.SS "Encoding options" .TP -.BR \-n ", " \-\-dry\-run -Print what would be done without actually invoking -.BR ffmpeg (1). -Combine with -.B \-v -to see the selected video stream and detected codec, pixel format and frame -rate information. +.BR \-p " \fINAME\fR, " \-\-preset " \fINAME\fR, " \-\-preset= \fINAME\fR +Load the preset named \fINAME\fR from the preset directory. Defaults to +.BR default . .TP -.BR \-\-backup\-dir " \fIDIR\fR, " \-\-backup\-dir= \fIDIR\fR -Copy originals to \fIDIR\fR before replacing them after successful encoding. -\fIDIR\fR must already exist; the script exits with a usage error if it does -not. Backups preserve the source file's absolute path below \fIDIR\fR, and -existing backup files are not overwritten. +.BR \-N " \fIVALUE\fR, " \-\-nice " \fIVALUE\fR, " \-\-nice= \fIVALUE\fR +Run +.BR ffmpeg (1) +under +.BR nice (1) +with the given niceness value. Defaults to +.BR 19 +(lowest priority). .TP .BR \-\-hwaccel " [\fIMETHOD\fR], " \-\-hwaccel= \fIMETHOD\fR Pass @@ -138,31 +118,7 @@ or .BR v:1 . This option does not change ffmpeg stream mapping; presets remain responsible for selecting which stream to encode. -.TP -.BR \-N " \fIVALUE\fR, " \-\-nice " \fIVALUE\fR, " \-\-nice= \fIVALUE\fR -Run -.BR ffmpeg (1) -under -.BR nice (1) -with the given niceness value. Defaults to -.BR 19 -(lowest priority). -.TP -.BR \-s ", " \-\-size\-report -Print per-file size feedback after successful encodes and size-based skips, -then write a TSV status log for encoded, skipped and failed files. For runs -with more than one input file, print a final summary with encoded, skipped -and failed counts, total bytes saved and the overall saved percentage. -.TP -.BR \-\-no\-size\-report -Disable size reporting from the configuration file. -.TP -.BR \-\-size\-report\-file " \fIPATH\fR, " \-\-size\-report\-file= \fIPATH\fR -Path to the TSV status log written by -.BR \-\-size\-report . -Defaults to -.B transcode_size_report -in the current working directory. +.SS "Skip options" .TP .BR \-S " \fILIST\fR, " \-\-skip\-codec " \fILIST\fR, " \-\-skip\-codec= \fILIST\fR Comma-, space- or colon-separated list of video codec names to skip. @@ -182,6 +138,21 @@ and use only codecs provided through .BR \-S / \-\-skip\-codec for this run. The position of this flag on the command line does not matter; it changes how the final skip list is resolved after all options are parsed. +.SS "Processing options" +.TP +.BR \-n ", " \-\-dry\-run +Print what would be done without actually invoking +.BR ffmpeg (1). +Combine with +.B \-v +to see the selected video stream and detected codec, pixel format and frame +rate information. +.TP +.BR \-\-backup\-dir " \fIDIR\fR, " \-\-backup\-dir= \fIDIR\fR +Copy originals to \fIDIR\fR before replacing them after successful encoding. +\fIDIR\fR must already exist; the script exits with a usage error if it does +not. Backups preserve the source file's absolute path below \fIDIR\fR, and +existing backup files are not overwritten. .TP .BR \-l ", " \-\-only\-if\-smaller After encoding, replace the original only when the new file is strictly @@ -191,9 +162,47 @@ and the original is kept unchanged. .BR \-\-no\-only\-if\-smaller After encoding, replace the original also if the new file is bigger. .TP -.BR \-p " \fINAME\fR, " \-\-preset " \fINAME\fR, " \-\-preset= \fINAME\fR -Load the preset named \fINAME\fR from the preset directory. Defaults to -.BR default . +.BR \-\-verify\-output +After encoding, probe the temporary output file with +.BR ffprobe (1) +to confirm it is a valid, playable media file before replacing the +original. Enabled by default. +.TP +.BR \-\-no\-verify\-output +Skip the post-encode integrity check. The original is replaced as long +as +.BR ffmpeg (1) +exits successfully. Useful for large batch jobs on trusted encoders +where the additional probe round-trip is undesirable. +.TP +.BR \-c ", " \-\-continue +Continue processing the next file even if +.BR ffmpeg (1) +fails on the current one. Without this flag the script exits immediately +on the first failure. +.TP +.BR \-\-no\-continue +Do not continue processing next file even if +.BR ffmpeg (1) +fails on the current one. +.SS "Size report options" +.TP +.BR \-s ", " \-\-size\-report +Print per-file size feedback after successful encodes and size-based skips, +then write a TSV status log for encoded, skipped and failed files. For runs +with more than one input file, print a final summary with encoded, skipped +and failed counts, total bytes saved and the overall saved percentage. +.TP +.BR \-\-no\-size\-report +Disable size reporting from the configuration file. +.TP +.BR \-\-size\-report\-file " \fIPATH\fR, " \-\-size\-report\-file= \fIPATH\fR +Path to the TSV status log written by +.BR \-\-size\-report . +Defaults to +.B transcode_size_report +in the current working directory. +.SS "Display options" .TP .BR \-\-ffmpeg\-loglevel " \fILEVEL\fR, " \-\-ffmpeg\-loglevel= \fILEVEL\fR Pass @@ -203,9 +212,6 @@ to Defaults to .BR fatal . .TP -.BR \-h ", " \-\-help ", " \-? -Print a short help message and exit. -.TP .BR \-q ", " \-\-quiet Suppress all normal output. Takes precedence over .BR \-v / \-\-verbose . @@ -214,6 +220,18 @@ Suppress all normal output. Takes precedence over Emit additional informational messages, including the selected video stream and detected codec, pixel format and frame rate. .TP +.B \-\-color +Force colored output even when stdout is not a terminal or +.B NO_COLOR +is set. +.TP +.B \-\-no\-color +Disable colored output unconditionally. +.SS "General options" +.TP +.BR \-h ", " \-\-help ", " \-? +Print a short help message and exit. +.TP .B \-\-version Print version, author and license information and exit. .TP @@ -226,14 +244,6 @@ If the preset directory does not exist or contains no .B .sh files, a notice is printed instead. .TP -.B \-\-color -Force colored output even when stdout is not a terminal or -.B NO_COLOR -is set. -.TP -.B \-\-no\-color -Disable colored output unconditionally. -.TP .B \-\- End of options. All subsequent arguments are treated as file names even if they begin with diff --git a/transcode.sh.bash-completion.sh b/transcode.sh.bash-completion.sh index 2ae59d0..6e55970 100644 --- a/transcode.sh.bash-completion.sh +++ b/transcode.sh.bash-completion.sh @@ -52,19 +52,14 @@ function _transcode_sh() { _filedir return ;; - --backup-dir=*) - cur="${cur#*=}" - _filedir -d - return - ;; --encode-file=*) cur="${cur#*=}" _filedir return ;; - --size-report-file=*) + --preset=*) cur="${cur#*=}" - _filedir + COMPREPLY=($(compgen -W "$(_transcode_presets)" -- "$cur")) return ;; --nice=*) @@ -72,19 +67,29 @@ function _transcode_sh() { COMPREPLY=($(compgen -W "$nice_vals" -- "$cur")) return ;; + --hwaccel=*) + cur="${cur#*=}" + COMPREPLY=($(compgen -W "$hwaccel_methods" -- "$cur")) + return + ;; + --video-stream=*) + cur="${cur#*=}" + COMPREPLY=($(compgen -W "$video_streams" -- "$cur")) + return + ;; --skip-codec=*) cur="${cur#*=}" COMPREPLY=($(compgen -W "$codecs" -- "$cur")) return ;; - --preset=*) + --backup-dir=*) cur="${cur#*=}" - COMPREPLY=($(compgen -W "$(_transcode_presets)" -- "$cur")) + _filedir -d return ;; - --hwaccel=*) + --size-report-file=*) cur="${cur#*=}" - COMPREPLY=($(compgen -W "$hwaccel_methods" -- "$cur")) + _filedir return ;; --ffmpeg-loglevel=*) @@ -92,16 +97,11 @@ function _transcode_sh() { COMPREPLY=($(compgen -W "$ffmpeg_loglevels" -- "$cur")) return ;; - --video-stream=*) - cur="${cur#*=}" - COMPREPLY=($(compgen -W "$video_streams" -- "$cur")) - return - ;; esac # --------------------------------------------------------------------------- - # Handle VALUE after short form (-f, -N, -S, -p) and - # long space form (--encode-file, --nice, --size-report-file, --skip-codec, --preset). + # Handle VALUE after short and long space forms. + # The dispatch order mirrors the help output where practical. # $prev is the option word, $cur is the value being typed. # --------------------------------------------------------------------------- case "$prev" in @@ -109,40 +109,40 @@ function _transcode_sh() { _filedir return ;; - --backup-dir) - _filedir -d - return - ;; -f | --encode-file) _filedir return ;; + -p | --preset) + COMPREPLY=($(compgen -W "$(_transcode_presets)" -- "$cur")) + return + ;; -N | --nice) COMPREPLY=($(compgen -W "$nice_vals" -- "$cur")) return ;; - --size-report-file) - _filedir + --hwaccel) + COMPREPLY=($(compgen -W "$hwaccel_methods" -- "$cur")) return ;; - -S | --skip-codec) - COMPREPLY=($(compgen -W "$codecs" -- "$cur")) + --video-stream) + COMPREPLY=($(compgen -W "$video_streams" -- "$cur")) return ;; - -p | --preset) - COMPREPLY=($(compgen -W "$(_transcode_presets)" -- "$cur")) + --ffmpeg-loglevel) + COMPREPLY=($(compgen -W "$ffmpeg_loglevels" -- "$cur")) return ;; - --hwaccel) - COMPREPLY=($(compgen -W "$hwaccel_methods" -- "$cur")) + -S | --skip-codec) + COMPREPLY=($(compgen -W "$codecs" -- "$cur")) return ;; - --ffmpeg-loglevel) - COMPREPLY=($(compgen -W "$ffmpeg_loglevels" -- "$cur")) + --backup-dir) + _filedir -d return ;; - --video-stream) - COMPREPLY=($(compgen -W "$video_streams" -- "$cur")) + --size-report-file) + _filedir return ;; esac @@ -157,44 +157,45 @@ function _transcode_sh() { case "$cur" in --*) local longopts=' - --backup-dir - --backup-dir= - --color --config-file --config-file= - --continue - --dry-run + --no-config --encode-file --encode-file= - --ffmpeg-loglevel - --ffmpeg-loglevel= - --help - --hwaccel - --hwaccel= - --list-presets + --preset + --preset= --nice --nice= - --no-color - --no-continue + --hwaccel + --hwaccel= --no-hwaccel + --video-stream + --video-stream= + --skip-codec + --skip-codec= + --skip-codec-override + --dry-run + --backup-dir + --backup-dir= + --only-if-smaller --no-only-if-smaller - --no-size-report + --verify-output --no-verify-output - --only-if-smaller - --preset - --preset= - --quiet + --continue + --no-continue --size-report + --no-size-report --size-report-file --size-report-file= - --skip-codec - --skip-codec-override - --skip-codec= + --ffmpeg-loglevel + --ffmpeg-loglevel= + --quiet --verbose - --verify-output + --color + --no-color + --help --version - --video-stream - --video-stream= + --list-presets ' COMPREPLY=($(compgen -W "$longopts" -- "$cur")) # Suppress the trailing space when the only completion ends with '=' @@ -203,7 +204,7 @@ function _transcode_sh() { return ;; -*) - local shortopts='-c -f -n -N -s -S -l -p -h -? -q -v --' + local shortopts='-f -p -N -S -n -l -c -s -q -v -h -? --' COMPREPLY=($(compgen -W "$shortopts" -- "$cur")) return ;; |
