#-------------------------------- # filename: /zsh/ffmpeg #-------------------------------- # Original script: https://yohanes.gultom.me/2016/05/21/bash-script-to-batch-convert-mkv-to-mp4-linux/ # Rewritten with ChatGPT 🙈 function ff-mp4 () { local findpath="${1:-.}" local file_list=() local temp_file=$(mktemp) # Find all video files and write them to a temporary file find "$findpath" \( -iname '*.mkv' -o -iname '*.flv' -o -iname '*.mov' -o -iname '*.mp4' \) -print0 > "$temp_file" # Read the file contents into the file_list array while IFS= read -r -d $'\0' file; do file_list+=("$file") done < "$temp_file" rm "$temp_file" # Delete the temporary file # Process each file in the file_list array local num_files=${#file_list[@]} local counter=1 for file in "${file_list[@]}"; do local dir=$(dirname "$file") local file_name=$(basename "$file") local name="${file_name%.*}" local ext="${file_name##*.}" echo "Processing file [$counter/$num_files]: $file_name" counter=$((counter+1)) # Re-container the video file to mp4 using ffmpeg ffmpeg -hide_banner -loglevel error -i "$file" -map 0 -c copy -pix_fmt yuv420p -movflags faststart "$dir/temp_$name.mp4" # Rename the original file and move the new mp4 file to its place mv -n "$file" "$dir/_$file_name" mv -n "$dir/temp_$name.mp4" "$dir/$file_name.mp4" done } # Recompress input MP4 to 720p MP4 (copy audio) ff-recompress720p() { for input in *.mp4; do if [[ -f "$input" ]]; then tempfile="temp_${input%.mp4}" ffmpeg -hide_banner -i "$input" -c:v libx264 -crf 18 -vf scale=1280:-2 -preset slow -tune film -x264-params "ref=5:bframes=5:crf-max=25:qpmax=34:level=3.1:b-adapt=2:direct=auto:deblock=-1,-1:analyse=all:me=umh:subme=9:trellis=2:psy-rd=1,0.15:vbv-bufsize=17500:vbv-maxrate=17500:rc-lookahead=60" -c:a copy -movflags faststart "$tempfile.mp4" if [[ $? -eq 0 ]]; then mv "$input" "_$input" mv "$tempfile.mp4" "$input" echo "Conversion successful: $input" else echo "Conversion failed for: $input" fi fi done } # Recompress input MP4 to 540p MP4 (copy audio) ff-recompress540p() { for input in *.mp4; do if [[ -f "$input" ]]; then tempfile="temp_${input%.mp4}" ffmpeg -hide_banner -i "$input" -c:v libx264 -crf 18 -vf scale=960:-2 -preset slow -tune film -x264-params "ref=5:bframes=5:crf-max=25:qpmax=34:level=3.1:b-adapt=2:direct=auto:deblock=-1,-1:analyse=all:me=umh:subme=9:trellis=2:psy-rd=1,0.15:vbv-bufsize=17500:vbv-maxrate=17500:rc-lookahead=60" -c:a copy -movflags faststart "$tempfile.mp4" if [[ $? -eq 0 ]]; then mv "$input" "_$input" mv "$tempfile.mp4" "$input" echo "Conversion successful: $input" else echo "Conversion failed for: $input" fi fi done } # ffmpeg-convert # source: https://yohanes.gultom.me/2016/05/21/bash-script-to-batch-convert-mkv-to-mp4-linux/ function ff-ac3-to-stereo() { findpath=$1 : "${findpath:="."}" find "$findpath" \( -iname '*.mkv' -o -iname '*.flv' -o -iname '*.mov' -o -iname '*.mp4' \) | while read -r f ; do dir=$(dirname "$f"); file=$(basename "$f"); name="${file%.*}"; ext="${file##*.}"; ffmpeg -hide_banner -loglevel error -i "$f" -map 0 -c:v copy -c:a libfdk_aac -b:a 192k -ac 2 -af volume=2 -movflags faststart "$dir/temp_$name.mp4"; mv "$f" "$dir/_$file"; mv "$dir/temp_$name.mp4" "$dir/$file"; done } # ffmpeg audio-to-ac3 function ff-input-to-ac3() { ffmpeg -hide_banner -loglevel error -i "$1" -movflags faststart -map 0 -c:v copy -c:s copy -c:a ac3 -b:a 448k "temp_$1" mv "$1" "_$1" && mv "temp_$1" "$1" } # ffmpeg fix 16:9 AR function ff-ar16-9() { ffmpeg -hide_banner -loglevel error -i "$1" -c copy -map 0 -bsf:v "h264_metadata=sample_aspect_ratio=4/3" -aspect 16:9 -pix_fmt yuv420p -movflags faststart "temp_$1" mv "$1" "_$1" && mv "temp_$1" "$1" } # ffmpeg fix 5:4 AR function ff-ar5-4() { ffmpeg -hide_banner -loglevel error -i "$1" -c copy -map 0 -bsf:v "h264_metadata=sample_aspect_ratio=1/1" -aspect 5:4 -pix_fmt yuv420p -movflags faststart "temp_$1" mv "$1" "_$1" && mv "temp_$1" "$1" } # ffmpeg fix 4:3 AR function ff-ar4-3() { ffmpeg -hide_banner -loglevel error -i "$1" -c copy -map 0 -bsf:v "h264_metadata=sample_aspect_ratio=1/1" -aspect 4:3 -pix_fmt yuv420p -movflags faststart "temp_$1" mv "$1" "_$1" && mv "temp_$1" "$1" } # ffmpeg fix AR ($1 = file, $2 1/1, $4:3) function ff-ar-custom() { if [ $# -lt 3 ]; then >&2 echo "Not enough arguments (\$1 = 'file', \$2 '1/1', \$3 '4:3')" return 0 else ffmpeg -hide_banner -loglevel error -i "$1" -c copy -map 0 -bsf:v "h264_metadata=sample_aspect_ratio=$2" -aspect $3 -pix_fmt yuv420p -movflags faststart "_$1" fi } # ffmpeg fix Non-monotonous DTS function ff-dts() { ffmpeg -hide_banner -loglevel error -fflags +igndts -i "$1" -c copy -pix_fmt yuv420p -movflags faststart "temp_$1" mv "$1" "_$1" && mv "temp_$1" "$1" } ## ffmpeg wma-to-m4a function ff-wma-m4a() { findpath=$1 : "${findpath:="."}" find "$findpath" -name '*.wma' | while read -r f ; do dir=$(dirname "$f"); file=$(basename "$f"); name="${file%.*}"; ext="${file##*.}"; ffmpeg -hide_banner -loglevel error -i "$f" -map 0 -vn -b:a 192k -c:a libfdk_aac "$dir/temp_$name.mp4"; mv "$f" "$dir/_$file"; mv "$dir/temp_$name.mp4" "$dir/$file"; done } ## ffmpeg cut X seconds from start function ff-cutstart { local time="${2:-00:00:08.590}" mv "$1" "_$1" ffmpeg -hide_banner -loglevel error -ss $time -i "_$1" -map 0 -c copy -movflags faststart "$1" } ## ffmpeg cut X seconds from start function ff-cutend { local time="${2:-24.250}" duration=`ffprobe -v error -show_entries format=duration -of csv=p=0 "$1"` duration=`bc --expression=$duration-$time` mv "$1" "_$1" ffmpeg -hide_banner -loglevel error -ss 00:00:00 -to $duration -i "_$1" -map 0 -c copy -movflags faststart "$1" }