Created
April 24, 2026 19:42
-
-
Save chiliec/63a0cfc02c2695d00fbff2b9143fa73a to your computer and use it in GitHub Desktop.
Convert video to MP4 with optional quality presets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| usage() { | |
| cat <<'EOF' | |
| convert-video — convert video to MP4 with optional quality presets | |
| Usage: | |
| convert-video [--quality small|tiny] [--force] <input> | |
| convert-video --help | |
| Options: | |
| -q, --quality PRESET Re-encode with preset (small, tiny). Omit for remux. | |
| -f, --force Overwrite existing output file. | |
| -h, --help Show this help. | |
| Presets: | |
| (default) Stream-copy remux. Fast, lossless. Requires H.264+AAC source. | |
| small 960x540, CRF 26, ~35-50% of source size. | |
| tiny 854x480 @ 15fps, CRF 30, mono audio, ~15-25% of source size. | |
| Output: <input-stem>.mp4 (same directory as input). | |
| EOF | |
| } | |
| die() { | |
| echo "convert-video: $*" >&2 | |
| exit 1 | |
| } | |
| quality="" | |
| force=0 | |
| input="" | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -q|--quality) | |
| [[ $# -ge 2 ]] || die "missing value for $1" | |
| quality="$2" | |
| shift 2 | |
| ;; | |
| -f|--force) | |
| force=1 | |
| shift | |
| ;; | |
| -h|--help) | |
| usage | |
| exit 0 | |
| ;; | |
| --) | |
| shift | |
| break | |
| ;; | |
| -*) | |
| die "unknown flag: $1" | |
| ;; | |
| *) | |
| [[ -z "$input" ]] || die "only one input file allowed (got '$input' and '$1')" | |
| input="$1" | |
| shift | |
| ;; | |
| esac | |
| done | |
| if [[ -z "$input" ]]; then | |
| usage >&2 | |
| exit 1 | |
| fi | |
| case "$quality" in | |
| ""|small|tiny) ;; | |
| *) die "invalid --quality: '$quality' (expected: small, tiny)" ;; | |
| esac | |
| command -v ffmpeg >/dev/null 2>&1 \ | |
| || die "ffmpeg not found. Install with: brew install ffmpeg" | |
| [[ -f "$input" ]] || die "input file not found: $input" | |
| output="${input%.*}.mp4" | |
| if [[ -e "$output" && "$force" -ne 1 ]]; then | |
| die "output exists: $output | |
| (input: $input) | |
| Use --force to overwrite." | |
| fi | |
| success=0 | |
| trap '[[ $success -eq 1 ]] || rm -f "$output"' EXIT | |
| ffmpeg_common=(-hide_banner -loglevel warning -stats -y -i "$input") | |
| faststart=(-movflags +faststart) | |
| case "$quality" in | |
| "") | |
| ffmpeg "${ffmpeg_common[@]}" -map 0 -c copy "${faststart[@]}" "$output" | |
| ;; | |
| small) | |
| ffmpeg "${ffmpeg_common[@]}" \ | |
| -c:v libx264 -preset veryfast -crf 26 -vf scale=960:540 -pix_fmt yuv420p \ | |
| -c:a aac -b:a 128k \ | |
| "${faststart[@]}" "$output" | |
| ;; | |
| tiny) | |
| ffmpeg "${ffmpeg_common[@]}" \ | |
| -c:v libx264 -preset veryfast -crf 30 -vf scale=854:480 -r 15 -pix_fmt yuv420p \ | |
| -c:a aac -b:a 96k -ac 1 \ | |
| "${faststart[@]}" "$output" | |
| ;; | |
| esac | |
| success=1 | |
| echo "done: $output" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment