167 lines
4.2 KiB
Bash
167 lines
4.2 KiB
Bash
#!/bin/bash
|
|
|
|
debug() { echo "🛠️ DEBUG: $*" >&2; }
|
|
|
|
# Convert .avi and .mkv files to .mp4
|
|
# Supports --dry-run to simulate actions
|
|
# --source is required; --archive is optional
|
|
|
|
set -euo pipefail
|
|
|
|
# --- Defaults ---
|
|
DRY_RUN=false
|
|
DEBUG=false
|
|
SRC_DIR=""
|
|
ARCHIVE_DIR=""
|
|
LOG_FILE="log.convert"
|
|
QUALITY="23"
|
|
|
|
SRC_TYPES=()
|
|
|
|
# --- Help Message ---
|
|
show_help() {
|
|
echo "Usage: $0 --source <src_dir> [--archive <archive_dir>] [--quality ] [--dry-run] [--debug]"
|
|
echo
|
|
echo " --source Directory to scan for .avi and .mkv files"
|
|
echo " --archive Directory to move originals after conversion (optional)"
|
|
echo " If omitted, originals will be deleted"
|
|
echo " --quality Quality of the video 18-28 (18 is high quality, 23 is default, 28 is low)"
|
|
echo " --dry-run Show actions without performing them"
|
|
echo " --debug Output debug statements"
|
|
echo
|
|
exit 1
|
|
}
|
|
|
|
# --- Parse Arguments ---
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--source)
|
|
SRC_DIR="$(realpath "$2")"
|
|
shift 2
|
|
;;
|
|
--archive)
|
|
ARCHIVE_DIR="$(realpath "$2")"
|
|
shift 2
|
|
;;
|
|
--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
--debug)
|
|
DEBUG=true
|
|
shift
|
|
;;
|
|
--src-type)
|
|
SRC_TYPES+=("${2,,}") # normalize to lowercase
|
|
shift -2
|
|
;;
|
|
--help|-h)
|
|
show_help
|
|
;;
|
|
--quality)
|
|
QUALITY="$2"
|
|
if ! [[ "$QUALITY" =~ ^[0-9]+$ ]] || ((QUALITY < 18 || QUALITY > 28)); then
|
|
echo "❌ Error: --quality must be an integer between 18 and 28." >&2
|
|
exit 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
show_help
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ "${#SRC_TYPES[@]}" -eq 0 ]]; then
|
|
SRC_TYPES=("avi" "mkv") # default id none specified
|
|
fi
|
|
|
|
# --- Validate Source Directory ---
|
|
if [[ -z "$SRC_DIR" ]]; then
|
|
echo "❌ Error: --source is required." >&2
|
|
show_help
|
|
fi
|
|
|
|
if [[ ! -d "$SRC_DIR" ]]; then
|
|
echo "❌ Error: Source directory does not exist: $SRC_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "🔍 Scanning: $SRC_DIR"
|
|
$DRY_RUN && echo "🧪 Dry-run mode enabled"
|
|
|
|
# --- Gather file list once ---
|
|
mapfile -d '' FILE_LIST < <(find "$SRC_DIR" \( -iname '*.avi' -o -iname '*.mkv' \) -print0)
|
|
|
|
# --- Preview list if in debug mode ---
|
|
if [[ "${DEBUG:-false}" == "true" ]]; then
|
|
echo "🗂️ DEBUG: File list to process:"
|
|
for file in "${FILE_LIST[@]}"; do
|
|
echo " - $file"
|
|
done
|
|
fi
|
|
|
|
|
|
# --- Find and Process Files ---
|
|
# Using process substitution instead of a pipe, so the while loop runs in the current shell
|
|
for src_file in "${FILE_LIST[@]}"; do
|
|
# abs_src_file="$(realpath "$src_file")"
|
|
# rel_path="${abs_src_file#$SRC_DIR/}"
|
|
|
|
# Use absolute path If the source file path is not absolute
|
|
# (doesn't start with '/'), prepend the source directory to
|
|
# make it an absolute path.
|
|
[[ "$src_file" != /* ]] && src_file="$SRC_DIR/$src_file"
|
|
|
|
rel_path="${src_file#$SRC_DIR/}"
|
|
|
|
base_name="${rel_path%.*}"
|
|
dst_file="$SRC_DIR/$base_name.mp4"
|
|
|
|
echo "▶️ Converting: $rel_path"
|
|
|
|
if $DRY_RUN; then
|
|
echo " [dry-run] Would convert to: $dst_file"
|
|
[[ -n "$ARCHIVE_DIR" ]] && echo " [dry-run] Would move original to: $ARCHIVE_DIR/$rel_path" || echo " [dry-run] Would delete original"
|
|
continue
|
|
fi
|
|
|
|
# Create output directory if needed
|
|
mkdir -p "$(dirname "$dst_file")"
|
|
|
|
if [[ "${DEBUG:-false}" == "true" ]]; then
|
|
debug "dirname dst_file: $(dirname "$dst_file")"
|
|
debug "src_file: $src_file"
|
|
# debug "abs_src_file: $abs_src_file"
|
|
debug "rel_path: $rel_path"
|
|
debug "base_name: $base_name"
|
|
debug "dst_file: $dst_file"
|
|
debug ""
|
|
debug "command:"
|
|
debug "ffmpeg -i \"$src_file\" -c:v libx264 -preset slow -crf $QUALITY -c:a aac -b:a 128k -movflags +faststart \"$dst_file\" -y >> $LOG_FILE 2>&1"
|
|
fi
|
|
|
|
# Convert video with ffmpeg and log output
|
|
ffmpeg \
|
|
-i "$src_file" \
|
|
-c:v libx264 \
|
|
-preset slow \
|
|
-crf "$QUALITY" \
|
|
-c:a aac \
|
|
-b:a 128k \
|
|
-movflags +faststart \
|
|
"$dst_file" \
|
|
-y >> "$LOG_FILE" 2>&1
|
|
|
|
# Archive or delete original
|
|
if [[ -n "$ARCHIVE_DIR" ]]; then
|
|
archive_file="$ARCHIVE_DIR/$rel_path"
|
|
mkdir -p "$(dirname "$archive_file")"
|
|
mv "$src_file" "$archive_file"
|
|
else
|
|
rm "$src_file"
|
|
fi
|
|
done
|
|
|
|
echo "✅ Done."
|