wembify.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. #!/usr/bin/env bash
  2. set -euo pipefail # bash strict mode
  3. echo "
  4. _ _ ______________ ________________ __
  5. | | | | ___| ___ \ \/ |_ _| ___\ \ / /
  6. | | | | |__ | |_/ / . . | | | | |_ \ V /
  7. | |/\| | __|| ___ \ |\/| | | | | _| \ /
  8. \ /\ / |___| |_/ / | | |_| |_| | | |
  9. \/ \/\____/\____/\_| |_/\___/\_| \_/
  10. VERSION: 1.5 CREATED: 1/1/2021 BY: ANON
  11. Use "'"-h"'" for help
  12. "
  13. # I would highly reccomend placing this script in /home/username/scripts
  14. # and adding the following to your .bashrc (without the # of course)
  15. #
  16. # alias webmify='~/scripts/webmify.sh'
  17. #
  18. # Change this option to where you store your converted webms. if you leave it blank, it will output converted webms to the same directory as this script
  19. # You must have a / at the end of the path, eg. "home/use/Videos/"
  20. default_path="/mnt/melchior-3/Videos/created_webms/"
  21. # Option flags, in case the user wants to skip the prompts
  22. while getopts i:o:n:f:r:s:e:m:a:k:hy flag
  23. do
  24. case "${flag}" in
  25. i) input=${OPTARG} ;;
  26. o) output=${OPTARG} ;;
  27. n) filename=${OPTARG} ;;
  28. f) fps=${OPTARG} ;;
  29. r) resolution=${OPTARG} ;;
  30. s) beginning=${OPTARG} ;;
  31. e) end=${OPTARG} ;;
  32. m) max_size=${OPTARG} ;;
  33. a) audio_set=${OPTARG} ;;
  34. k) keyframe=${OPTARG} ;;
  35. h) help="true" ;;
  36. y) skip="true" ;;
  37. esac
  38. done
  39. if [ -z "$help" ]
  40. then
  41. if ([ -z "$max_size" ] && [ -z "$audio_set" ]) || (! [ -z "$max_size" ] && ! [ -z "$audio_set" ])
  42. then
  43. true
  44. else
  45. echo "Error! if -a is specified, -m must also be specified, and vice versa!"
  46. exit
  47. fi
  48. #getting the input file, if one wasn't specified when running the script
  49. if [ -z "$input" ]
  50. then
  51. read -r -p "Path to input file: " input_file
  52. input_file="$input_file"
  53. else
  54. input_file="$input"
  55. fi
  56. echo
  57. #get the source video information
  58. default_resolution=$(ffprobe -i $input_file -v quiet -show_entries stream=height -hide_banner -of default=noprint_wrappers=1:nokey=1)
  59. default_length=$(ffprobe -i $input_file -v quiet -show_entries format=duration -hide_banner -of default=noprint_wrappers=1:nokey=1)
  60. #split up the full path to extract just the filename, sans extension
  61. xpath=${input_file%/*}
  62. xbase=${input_file##*/}
  63. xfext=${xbase##*.}
  64. xpref=${xbase%.*}
  65. #determine max file size
  66. if ! [ -z "$max_size" ]
  67. then
  68. max_file_size=$max_size
  69. if [ $audioset == "y" ]
  70. then
  71. audioset="-c:a libvorbis "
  72. else
  73. audioset="-an "
  74. fi
  75. else
  76. #ask the user for target filesize based on 4chan limits
  77. #they are slightly below to limit to account for ffmpeg using average bitrates and usually being slightly over-size
  78. read -r -p "Posting to WSG/GIF (audio and higher filesize)? [y/N]
  79. Or type 'c' for a custom value " response
  80. case "$response" in
  81. [yY][eE][sS]|[yY])
  82. max_file_size=4950
  83. audioset="-c:a libvorbis "
  84. ;;
  85. [cC])
  86. read -r -p "Enter max filesize in bytes: " max_file_size
  87. read -r -p "Would you like audio? " response
  88. case "$response" in
  89. [yY][eE][sS]|[yY])
  90. audioset="-c:a libvorbis "
  91. ;;
  92. *)
  93. audioset="-an "
  94. ;;
  95. esac
  96. ;;
  97. *)
  98. max_file_size=2950
  99. audioset="-an "
  100. ;;
  101. esac
  102. echo
  103. fi
  104. #determine output location
  105. if ! [ -z "$output" ]
  106. then
  107. output_filename=$output$xpref.gif
  108. else
  109. # Ask the user for the output path, or use default if not provided
  110. if [ -z "$skip" ]
  111. then
  112. echo Please enter the destination path.
  113. echo Example: '$HOME/Videos/'
  114. echo Leave Blank: Default path "($default_path)"
  115. read -r -p "Destination path: " path
  116. fi
  117. if [ -z "$path" ]
  118. then
  119. path=$default_path
  120. else
  121. true
  122. fi
  123. if [ -z "$skip" ]
  124. then
  125. echo Please enter the output filename.
  126. echo Example: 'My_Movie'
  127. echo Leave Blank: Default filename "($xpref)"
  128. read -r -p "output filename: " filename
  129. fi
  130. if [ -z "$filename" ]
  131. then
  132. filename=$xpref
  133. else
  134. true
  135. fi
  136. output_filename=$path$filename.webm
  137. echo
  138. fi
  139. if [ ! -d $path ]; then
  140. mkdir -p $path;
  141. fi
  142. #determine the output framerate
  143. if [ -z $fps ]
  144. then
  145. if [ -z "$skip" ]
  146. then
  147. echo Please enter webm framerate '(fps)'.
  148. echo Example: 30
  149. echo Leave Blank: Source video framerate
  150. read -r -p "Framerate: " fps
  151. echo
  152. fi
  153. if [ -z $fps ]; then fps=$default_fps; fi;
  154. elif [ $fps == "d" ]
  155. then
  156. fps=$default_fps
  157. fi
  158. #determine the keyframe interval
  159. if [ -z $keyframe ]
  160. then
  161. if [ -z "$skip" ]
  162. then
  163. echo Please enter keyframe interval in frames.
  164. echo "If you don't know what this means it's best to leave it blank."
  165. echo Example: 30
  166. echo Leave Blank: Source keyframe interval.
  167. read -r -p "Keyframe interval: " keyframe
  168. echo
  169. fi
  170. if ! [ -z $keyframe ]
  171. then
  172. keyframe=" -g $keyframe "
  173. fi
  174. fi
  175. #determine the output resolution
  176. if [ -z $resolution ]
  177. then
  178. if [ -z "$skip" ]
  179. then
  180. echo Please enter webm vertical render resolution.
  181. echo Example: 720
  182. echo Leave Blank: Source video resolution.
  183. read -r -p "Resolution: " resolution
  184. echo
  185. fi
  186. if [ -z $resolution ]; then resolution=$default_resolution; fi;
  187. elif [ $resolution == "d" ]
  188. then
  189. resolution=$default_resolution
  190. fi
  191. #determine where to start the clip
  192. if ! [ -z "$beginning" ]
  193. then
  194. start=$beginning
  195. else
  196. if [ -z "$skip" ]
  197. then
  198. #ask the user where the encode should start (in seconds offset from the beginning of the source)
  199. echo Please enter webm rendering offset in SECONDS.
  200. echo Example: 31
  201. echo Leave Blank: Start of source video.
  202. read -r -p "Offset: " start
  203. echo
  204. fi
  205. fi
  206. if ! [ -z "$start" ] && ! [ "$start" == "0" ]
  207. then
  208. startset="-ss $start "
  209. else
  210. start="Start of video"
  211. fi
  212. #determine where to end the clip
  213. if ! [ -z "$end" ]
  214. then
  215. [[ "$end" == "end" ]] && length=$default_length || true
  216. length=$end
  217. else
  218. if [ -z "$skip" ]
  219. then
  220. #ask the user where the encode should end (in seconds offset from the beginning of the source)
  221. echo Please enter webm rendering length in SECONDS.
  222. echo Example: 15
  223. echo Leave Blank: Entire source video.
  224. read -r -p "Length: " length
  225. echo
  226. fi
  227. fi
  228. #determine the target bitrate
  229. #the calculation for this is: (8 [number of bits in a byte] * maximum file sile [in kilobytes]) / total legnth
  230. #ffmpeg caluclates bitrate in kilobits per second, hence the converion from kilobytes to kilobits
  231. if ! [ -z "$length" ] && ! [ "$length" == "end" ]
  232. then
  233. lengthset="-t $length "
  234. bitrate=$(echo "8*$max_file_size/$length" | bc)'K'
  235. else
  236. length=$default_length
  237. bitrate=$(echo "8*$max_file_size/$length" | bc)'K'
  238. length="End of Video"
  239. fi
  240. #tell the user what we've just done, and ask them if these settings are ok
  241. echo "Creating webm with the following settings:
  242. Resolution: $resolution
  243. Framerate: $fps
  244. Start at: $start
  245. End at: $length
  246. Bitrate: $bitrate
  247. Output to: $output_filename
  248. "
  249. # i totally nabbed this from github
  250. # https://github.com/fearside/ProgressBar/blob/master/progressbar.sh
  251. function ProgressBar {
  252. # Process data
  253. let _progress=(${1}*100/${2}*100)/100
  254. let _done=(${_progress}*4)/10
  255. let _left=40-$_done
  256. # Build progressbar string lengths
  257. _done=$(printf "%${_done}s")
  258. _left=$(printf "%${_left}s")
  259. # 1.2 Build progressbar strings and print the ProgressBar line
  260. # 1.2.1 Output example:
  261. # 1.2.1.1 Progress : [########################################] 100%
  262. printf "\rProgress : [${_done// /#}${_left// /-}] ${_progress}%%"
  263. }
  264. function DoTheThing {
  265. #two-pass encoding for best quality and to limit filesize to the desired limit
  266. ProgressBar 10 100
  267. ffmpeg -i $input_file $startset$lengthset-c:v libvpx -b:v $bitrate $audioset$keyframe-sn -threads 0 -hide_banner -loglevel error -f webm -pass 1 -y null
  268. ProgressBar 50 100
  269. ffmpeg -i $input_file $startset$lengthset-c:v libvpx -b:v $bitrate -vf fps=$fps,scale=-1:$resolution $audioset$keyframe -sn -threads 0 -hide_banner -loglevel error -pass 2 -y "$output_filename"
  270. ProgressBar 75 100
  271. sleep 0.1
  272. ProgressBar 100 100
  273. sleep 0.1
  274. echo "
  275. All done!
  276. ⣿⡇⣿⣿⣿⠛⠁⣴⣿⡿⠿⠧⠹⠿⠘⣿⣿⣿⡇⢸⡻⣿⣿⣿⣿⣿⣿⣿
  277. ⢹⡇⣿⣿⣿⠄⣞⣯⣷⣾⣿⣿⣧⡹⡆⡀⠉⢹⡌⠐⢿⣿⣿⣿⡞⣿⣿⣿
  278. ⣾⡇⣿⣿⡇⣾⣿⣿⣿⣿⣿⣿⣿⣿⣄⢻⣦⡀⠁⢸⡌⠻⣿⣿⣿⡽⣿⣿
  279. ⡇⣿⠹⣿⡇⡟⠛⣉⠁⠉⠉⠻⡿⣿⣿⣿⣿⣿⣦⣄⡉⠂⠈⠙⢿⣿⣝⣿
  280. ⠤⢿⡄⠹⣧⣷⣸⡇⠄⠄⠲⢰⣌⣾⣿⣿⣿⣿⣿⣿⣶⣤⣤⡀⠄⠈⠻⢮
  281. ⠄⢸⣧⠄⢘⢻⣿⡇⢀⣀⠄⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠄⢀
  282. ⠄⠈⣿⡆⢸⣿⣿⣿⣬⣭⣴⣿⣿⣿⣿⣿⣿⣿⣯⠝⠛⠛⠙⢿⡿⠃⠄⢸
  283. ⠄⠄⢿⣿⡀⣿⣿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⡾⠁⢠⡇⢀
  284. ⠄⠄⢸⣿⡇⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏⣫⣻⡟⢀⠄⣿⣷⣾
  285. ⠄⠄⢸⣿⡇⠄⠈⠙⠿⣿⣿⣿⣮⣿⣿⣿⣿⣿⣿⣿⣿⡿⢠⠊⢀⡇⣿⣿
  286. ⠒⠤⠄⣿⡇⢀⡲⠄⠄⠈⠙⠻⢿⣿⣿⠿⠿⠟⠛⠋⠁⣰⠇⠄⢸⣿⣿⣿
  287. ⠄⠄⠄⣿⡇⢬⡻⡇⡄⠄⠄⠄⡰⢖⠔⠉⠄⠄⠄⠄⣼⠏⠄⠄⢸⣿⣿⣿
  288. ⠄⠄⠄⣿⡇⠄⠙⢌⢷⣆⡀⡾⡣⠃⠄⠄⠄⠄⠄⣼⡟⠄⠄⠄⠄⢿⣿⣿
  289. You can find the finished file at: $output_filename
  290. "
  291. }
  292. read -r -p "Start the conversion? [Y/n]: " continue
  293. echo
  294. case "$continue" in
  295. [yY][eE][sS]|[yY])
  296. DoTheThing
  297. ;;
  298. *)
  299. exit
  300. ;;
  301. esac
  302. #Thanks for using my script! <3
  303. #Below is the help text
  304. else
  305. cat <<EOF
  306. NAME
  307. webmify - convert a video file into a webm using ffmpeg
  308. SYNOPSIS
  309. webmify [OPTIONS]
  310. webmify
  311. DESCRIPTION
  312. Designed to get the best quality WEBM for psoting on 4chan. Options for various board file sizes and audio restrcitions.
  313. Convert a single INPUT file to an OUTPUT directory. The output file will use the same name as the source.
  314. Arguments are optional. If no arguments are specified, the user is prompted for conversion settings.
  315. I highly reccomend placing this script in $HOME/Scripts and creating an alias
  316. alias wbm='$HOME/Scripts/webmify.sh"
  317. OPTIONS
  318. -i
  319. INPUT file.
  320. -o
  321. OUTPUT directory. Cannot be a filename.
  322. Must end in /
  323. -n
  324. Output FILENAME. Should not comtain spaces.
  325. -f
  326. Desired output FRAMERATE in frames per second
  327. -r
  328. Desired output vertical RESOLUTION.
  329. Example: 720 for 720p
  330. -s
  331. Time to START the encode, in seconds from the beginning of the video.
  332. This will trim off N number of seconds from the beginning of the video.
  333. -e
  334. When the output file should END, in seconds from the beginning of the video.
  335. Cannot be longer than the source length.
  336. -m
  337. Specify the MAX FILE SIZE in bytes.
  338. Because of how FFMPEG works, this should be a little under the actual desired file size.
  339. Example: 4900 for ~5MB
  340. If -m is specified, -a MUST ALSO e specified.
  341. -a
  342. Specify if the output should have AUDIO or not.
  343. 'y' for audio, anything else for no audio.
  344. If -a is specified, -m MUST ALSO e specified.
  345. -y
  346. Will skip all user prompts. If a certain value is not specified, the default will be used.
  347. User is still prompted for INPUT file, and for which 4chan board to post on (determines MAX FILE SIZE/AUDIO).
  348. AUTHOR
  349. Just a guy trying to make some webms
  350. COPYRIGHT
  351. You can use this shit however you want. I give you permission.
  352. The above copyright notice, this permission notice and the word "NIGGER" shall be included in all copies or substantial portions of the Software.
  353. SEE ALSO
  354. GIFY (probably in the same folder as this script)
  355. EOF
  356. fi