#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DEFAULT_FFMPEG="$SCRIPT_DIR/ffmpeg" FFMPEG="" QUALITY="2" ENCLIB="libmp3lame" DELETE_ORIG=1 DRY_RUN=0 EXTRA_ARGS=() print_help() { cat <<'EOF' Usage: ogg_to_mp3 [OPTIONS] [-- EXTRA_FFMPEG_ARGS] Converts all .ogg files in the current directory to .mp3 using ffmpeg. Options: -q, --quality <0-9> Set VBR quality (default: 2) -l, --enclib Specify MP3 encoder (default: libmp3lame) -b, --binary Use a specific ffmpeg binary instead of ./ffmpeg or $PATH -d, --no-delete Keep original .ogg files after conversion -r, --dry-run Show what would be done without executing -h, --help Display this help message Extra ffmpeg options: Anything after '--' is passed directly to ffmpeg before the output filename. Examples: Convert with default settings: ./ogg_to_mp3 Dry run, showing commands without executing: ./ogg_to_mp3 -r Use custom encoder and quality: ./ogg_to_mp3 -q 0 -l libmp3lame Pass extra ffmpeg flags: ./ogg_to_mp3 -- -loglevel info -map_metadata 0 EOF } # Parse arguments while [[ $# -gt 0 ]]; do case "$1" in -h|--help) print_help exit 0 ;; -q|--quality) [[ $# -lt 2 ]] && { echo "Error: $1 requires a value."; exit 1; } QUALITY="$2" shift 2 ;; -l|--enclib) [[ $# -lt 2 ]] && { echo "Error: $1 requires a value."; exit 1; } ENCLIB="$2" shift 2 ;; -b|--binary) [[ $# -lt 2 ]] && { echo "Error: $1 requires a value."; exit 1; } FFMPEG="$2" shift 2 ;; -d|--no-delete) DELETE_ORIG=0 shift ;; -r|--dry-run) DRY_RUN=1 shift ;; --) shift EXTRA_ARGS=("$@") break ;; *) echo "Unknown option: '$1'." print_help exit 1 ;; esac done # Resolve ffmpeg binary if [[ -n "$FFMPEG" ]]; then if [[ ! -x "$FFMPEG" ]]; then echo "Error: specified ffmpeg binary '$FFMPEG' not executable" exit 1 fi else if [[ -x "$DEFAULT_FFMPEG" ]]; then FFMPEG="$DEFAULT_FFMPEG" elif command -v ffmpeg >/dev/null 2>&1; then FFMPEG="$(command -v ffmpeg)" else echo "Error: ffmpeg not found (no ./ffmpeg, no --binary, nothing in PATH)" exit 1 fi fi shopt -s nullglob OGG_FILES=(*.ogg) if [[ ${#OGG_FILES[@]} -eq 0 ]]; then echo "No .ogg files found in current directory." exit 0 fi if [[ $DRY_RUN -eq 1 ]]; then echo "DRY RUN:" fi for f in "${OGG_FILES[@]}"; do out="${f%.ogg}.mp3" cmd=( "$FFMPEG" -y -loglevel error -i "$f" -c:a "$ENCLIB" -q:a "$QUALITY" "${EXTRA_ARGS[@]}" "$out" ) echo "Converting: '$f' -> '$out'" if [[ $DRY_RUN -eq 1 ]]; then printf ' ffmpeg ' for arg in "${cmd[@]:1}"; do printf '%q ' "$arg" done echo if [[ $DELETE_ORIG -eq 1 ]]; then echo "Script would delete original file ('$f')." fi continue fi "${cmd[@]}" if [[ $DELETE_ORIG -eq 1 ]]; then rm -f "$f" echo "Deleted: $f" fi done echo "Done."