ffmpres (6073B)
1 #!/usr/bin/env bash 2 # ffmpeg wrapper with various presets. 3 4 if ! command -v ffmpeg &> /dev/null; then echo "ffmpeg not found" && exit 1; fi 5 main() { 6 case "$1" in 7 *.gif) 8 if ! [ -f "$1" ] ; then echo "$1 not found." && exit 1; fi 9 echo "GIF: $1" 10 process_gif "$1" 11 ;; 12 *.mp4|*.mov|*.webm|*.m4v|*.mkv) 13 if ! [ -f "$1" ] ; then echo "$1 not found." && exit 1; fi 14 echo "VIDEO: $1" 15 process_video "$@" 16 ;; 17 *.mp3|*.wav|*.ogg|*.flac|*.m4a) 18 if ! [ -f "$1" ] ; then echo "$1 not found." && exit 1; fi 19 echo "AUDIO: $1" 20 process_audio "$@" 21 ;; 22 "") 23 process_misc 24 ;; 25 *) 26 echo "File type not supported." 27 ;; 28 esac 29 } 30 31 process_misc() { 32 echo "For other functionality, please add the filename as the first argument." 33 select operation in "Record audio" "List devices"; do 34 case "$operation" in 35 "Record audio") 36 echo -n "Devices to record (format n:n): "; 37 read -r record_src; 38 echo -n "Output filename: "; 39 read -r out_name; 40 ffmpeg -f avfoundation -i "$record_src" "${out_name:-output.mkv}" 41 break;; 42 "List devices") 43 ffmpeg -f avfoundation -list_devices true -i ""; 44 break;; 45 *) 46 break;; 47 esac 48 done 49 } 50 51 process_gif() { 52 select to_fmt in "MP4"; do 53 case "$to_fmt" in 54 "MP4") 55 ffmpeg -i "$1" -r 30 -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" "${1%%.gif}.mp4" 56 break;; 57 *) 58 break;; 59 esac 60 done 61 } 62 63 process_audio() { 64 select operation in "VOLUME" "CLIP"; do 65 case "$operation" in 66 "VOLUME") 67 read -rp "Amount or percent: " vol; 68 read -rp "Enter output filename: " outfile 69 ffmpeg -i "$1" -filter:a "volume=$vol" "${outfile:-out-$1}" 70 break;; 71 "CLIP") 72 read -rp "From time (blank if from start): " starttime 73 read -rp "To time (blank if till end): " endtime 74 read -rp "Save as: " outfile 75 if [ -z "$endtime" ]; then 76 ffmpeg -i "$1" -ss "$starttime" "$outfile" 77 elif [ -z "$starttime" ]; then 78 ffmpeg -i "$1" -to "$endtime" "$outfile" 79 else 80 ffmpeg -i "$1" -ss "$starttime" -to "$endtime" "$outfile" 81 fi 82 break;; 83 *) 84 break;; 85 esac 86 done 87 } 88 89 process_video() { 90 select to_fmt in "MP4" "MP3" "GIF" "NO AUDIO" "CONCAT" "CLIP" "VOLUME" "FAST" "SLOW" "SCREENSHOT" "OPTIMISE"; do 91 case "$to_fmt" in 92 "MP4") 93 ffmpeg -i "$1" -vcodec copy -qscale 0 -c:s mov_text "${1%%.*}.mp4" 94 break;; 95 "MP3") 96 ffmpeg -i "$1" "${1%%.*}.mp3" 97 break;; 98 "GIF") 99 printf "FPS (default 24): " 100 read -r fps 101 printf "Scale (default unchanged): " 102 read -r scale 103 if [ -n "$scale" ]; then 104 local filters="fps=${fps:-24},scale=$scale:flags=lanczos" 105 else 106 local filters="fps=${fps:-24},scale=0:-1:flags=lanczos" 107 fi 108 echo "Creating gif" 109 local palette="/tmp/palette.png" 110 ffmpeg -v warning -i "$1" -vf "$filters,palettegen" -y "$palette" 111 ffmpeg -v warning -i "$1" -i "$palette" -lavfi "$filters [x]; [x][1:v] paletteuse" -y "${1%%.*}.gif" 112 break;; 113 "NO AUDIO") 114 ffmpeg -i "$1" -an "silent-$1" 115 break;; 116 "CONCAT") 117 if [ $# -le 1 ]; then echo "Only one file supplied, need at least two." && exit 1; fi 118 read -rp "Enter output filename: " outfile 119 set -x 120 tempfile="./ffmpeg-list-$RANDOM" 121 for f in "$@"; do echo "file '$f'" >> "$tempfile"; done 122 ffmpeg -f concat -safe 0 -i "$tempfile" -c copy "$outfile" 123 rm "$tempfile" 124 break;; 125 "CLIP") 126 read -rp "From time: " starttime 127 read -rp "To time: " endtime 128 read -rp "Save as: " outfile 129 if [ -z "$outfile" ]; then 130 if [ -z "$endtime" ]; then 131 ffmpeg -i "$1" -ss "$starttime" -acodec copy -vcodec copy "out-$1" 132 elif [ -z "$starttime" ]; then 133 ffmpeg -i "$1" -to "$endtime" -acodec copy -vcodec copy "out-$1" 134 else 135 ffmpeg -i "$1" -ss "$starttime" -to "$endtime" -acodec copy -vcodec copy "out-$1" 136 fi 137 else 138 if [ -z "$endtime" ]; then 139 ffmpeg -i "$1" -ss "$starttime" "$outfile" 140 elif [ -z "$starttime" ]; then 141 ffmpeg -i "$1" -to "$endtime" "$outfile" 142 else 143 ffmpeg -i "$1" -ss "$starttime" -to "$endtime" "$outfile" 144 fi 145 fi 146 break;; 147 "VOLUME") 148 read -rp "Amount or percent: " vol; 149 read -rp "Enter output filename: " outfile 150 ffmpeg -i "$1" -filter:a "volume=$vol" "${outfile:-out-$1}" 151 break;; 152 "FAST") 153 read -rp "Enter output filename: " outfile 154 ffmpeg -i "$1" -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" "${outfile:-out-$1}" 155 break;; 156 "SLOW") 157 read -rp "Enter output filename: " outfile 158 ffmpeg -i "$1" -filter_complex "[0:v]setpts=1.5*PTS[v];[0:a]atempo=0.67[a]" -map "[v]" -map "[a]" "${outfile:-out-$1}" 159 break;; 160 "SCREENSHOT") 161 read -rp "Timestamp to extract: " ts 162 ffmpeg -ss "$ts" -i "$1" -frames:v 1 -q:v 2 "$1.jpg" 163 break;; 164 "OPTIMISE") 165 codec="$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$1")" 166 read -rp "Enter output filename: " outfile 167 if [ "$codec" = "h264" ]; then 168 read -rp "Use h265? [Y/n] " -n 1 conf 169 echo 170 if [ "$conf" = "Y" ] || [ "$conf" = "y" ]; then 171 read -rp "CRF value (24..30, lower == higher bitrate): " crf 172 ffmpeg -i "$1" -vcodec libx265 -crf "$crf" "${outfile:-optimised-$1}" 173 return 174 fi 175 fi 176 read -rp "CRF value (18..24, lower == higher bitrate): " crf 177 ffmpeg -i "$1" -vcodec libx264 -crf "$crf" "${outfile:-optimised-$1}" 178 break;; 179 *) 180 ;; 181 esac 182 done 183 } 184 main "$@"