init
This commit is contained in:
commit
a10c8f0e74
853
webmify.sh
Normal file
853
webmify.sh
Normal file
@ -0,0 +1,853 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf "
|
||||
_ _ ______________ ________________ __
|
||||
| | | | ___| ___ \ \/ |_ _| ___\ \ / /
|
||||
| | | | |__ | |_/ / . . | | | | |_ \ V /
|
||||
| |/\| | __|| ___ \ |\/| | | | | _| \ /
|
||||
\ /\ / |___| |_/ / | | |_| |_| | | |
|
||||
\/ \/\____/\____/\_| |_/\___/\_| \_/
|
||||
|
||||
VERSION: 2.0 CREATED: 1/1/2021 BY: ANON
|
||||
Use '-h' for help, or type 'help' at any time
|
||||
"
|
||||
|
||||
# I would highly reccomend placing this script in ~/scripts
|
||||
# and adding the following alias to your .bashrc
|
||||
#
|
||||
# alias webmify='~/scripts/webmify.sh'
|
||||
#
|
||||
# You can also place this script in your file browser's scripts folder (eg. Nemo: ~/.local/share/nemo/scripts) to add it as a context menu item
|
||||
|
||||
##################################
|
||||
# Change this option to where you store your converted webms.
|
||||
#
|
||||
default_path="$HOME/Videos/webms/"
|
||||
#
|
||||
# If you leave it blank, it will output converted webms to the same directory as this script
|
||||
##################################
|
||||
|
||||
# Before anything else, let's make sure the user actually has ffmpeg and bc installed
|
||||
bc_installed=true
|
||||
ffmpeg_installed=true
|
||||
command -v ffmpeg >/dev/null 2>&1 || { $'\n '"Requirement \"ffmpeg\" is not installed. Aborting."; bc_installed=false; }
|
||||
command -v bc >/dev/null 2>&1 || { $'\n '"Requirement \"bc\" is not installed. Aborting."; ffmpeg_installed=false; }
|
||||
|
||||
if [ ! $bc_installed ] || [ ! $ffmpeg_installed ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set up our user variables
|
||||
SETTINGS=(input_file output_directory filename fps resolution start end max_file_size audio_set keyframe title codec debug help flag fails input OPTARG OPTIND)
|
||||
for i in ${SETTINGS[@]}; do
|
||||
unset $i
|
||||
done
|
||||
|
||||
prompt=true
|
||||
|
||||
# You can change this to output the debug log to a file, if required
|
||||
debug_echo() {
|
||||
if [ "$debug" ]; then
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
trap ctrl_c INT
|
||||
|
||||
function ctrl_c() {
|
||||
echo
|
||||
echo "Interrupt signal received! Aborting..."
|
||||
for i in ${SETTINGS[@]}; do
|
||||
unset $i
|
||||
done
|
||||
killall ffmpeg > /dev/null 2>&1
|
||||
exit
|
||||
}
|
||||
|
||||
show_hint() {
|
||||
hints=("
|
||||
|
||||
Usage:
|
||||
webmify [OPTIONS]
|
||||
webmify
|
||||
|
||||
List of available options:
|
||||
-i Input file (file)
|
||||
-o Output path (path or file)
|
||||
-n Output filename (string)
|
||||
-f Output fps (integer)
|
||||
-r Output vertical resolution (integer)
|
||||
-s Encoding start (integer)
|
||||
-e Encoding end (integer)
|
||||
-m Max file size (integer)
|
||||
-a Audio enable (y/n)
|
||||
-t Set the metadata title (string)
|
||||
-c Specify VP8 or VP9 codec (8/9)
|
||||
-v View debug messages
|
||||
-h Display help
|
||||
-y Skip all prompts"
|
||||
"
|
||||
Please type the full path to the file you wish to convert.
|
||||
Example: /home/user/Videos/my_movie.mp4
|
||||
You can press 'TAB' to autocomplete a path."
|
||||
"
|
||||
Destination path is the FOLDER you want the converted video
|
||||
to. If the folder doesn't exist it will be created.
|
||||
Output filename is the name of the FILE that will be created."
|
||||
"
|
||||
Specify the FPS (Frames Per Second) you want for the output
|
||||
video. The most common FPS values are 24, 30 (or 29) and 60."
|
||||
"
|
||||
Specify the VERTICAL resolution of the video. The width will
|
||||
be automatically calculated by ffmpeg. Common values are
|
||||
480, 720, 1080, 2160. Bear in mind most 4chan boards have a
|
||||
resolution limit of 2000x2000, although /HR/ has a MINIMUM
|
||||
resolution of 2560x2520."
|
||||
"
|
||||
The START value will determine how many seconds will be cut off
|
||||
from the beginning of the video.
|
||||
Th END value determines how long the clip will run for, from
|
||||
the specified START value.
|
||||
Eg. a START value of 5 and an END value of 20 will result in a
|
||||
video that is 20 seconds long, starting from the 5 second mark
|
||||
of the original video."
|
||||
"
|
||||
WSG and GIF both allow for files up to around 5MB in size, as
|
||||
well as an audio stream. Most other boards limit files to 3MB
|
||||
in size, and disallow audio. Selecting 'YES' will enable the
|
||||
5MB limit and audio, or typing 'C' will allow you to set your
|
||||
own limit and enable/disable audio."
|
||||
"
|
||||
This sets the metadata title value. Most video players will
|
||||
display this title when playing the video, and many people
|
||||
on media sharing sites will use this tag to embed useful info
|
||||
about the video, ie the name of the tv show or muscian in the
|
||||
video."
|
||||
"
|
||||
4chan allows only 2 codecs for webm, VP8 and VP9. VP8 is older
|
||||
and will usually encode faster than VP9, but VP9 results in
|
||||
much higher quality for the same file size. VP9 is now the default
|
||||
for WebRTC video across the internet, but there are still some
|
||||
applictions that have limited support. If you have issues with
|
||||
VP9 webms, try using VP8 instead.
|
||||
This script defaults to VP9 if you don't specify a codec."
|
||||
)
|
||||
|
||||
echo "${hints[$1]}"
|
||||
|
||||
sleep 0.5
|
||||
|
||||
}
|
||||
|
||||
# Option flags, in case the user wants to skip the prompts
|
||||
while getopts :i:o:n:f:r:s:e:m:a:t:c:vhy flag
|
||||
do
|
||||
case "${flag}" in
|
||||
i) input_file=${OPTARG}
|
||||
debug_echo Input file set: ${OPTARG};;
|
||||
o) output_directory=${OPTARG}
|
||||
debug_echo Output directory set: ${OPTARG};;
|
||||
n) filename=${OPTARG}
|
||||
debug_echo Filename set: ${OPTARG};;
|
||||
f) fps=${OPTARG}
|
||||
debug_echo FPS set: ${OPTARG};;
|
||||
r) resolution=${OPTARG}
|
||||
debug_echo Resolution set: ${OPTARG};;
|
||||
s) start=${OPTARG}
|
||||
debug_echo Start set: ${OPTARG};;
|
||||
e) end=${OPTARG}
|
||||
debug_echo End set: ${OPTARG};;
|
||||
m) max_file_size=${OPTARG}
|
||||
debug_echo Max file size set: ${OPTARG};;
|
||||
a) audio_set=${OPTARG}
|
||||
debug_echo Audio set: ${OPTARG};;
|
||||
t) title=${OPTARG}
|
||||
debug_echo Title set: ${OPTARG};;
|
||||
c) codec=${OPTARG}
|
||||
debug_echo Codec set: ${OPTARG};;
|
||||
v) debug="true";;
|
||||
h) help="true";;
|
||||
y) prompt=false;;
|
||||
:) printf $'\n '"Invalid option: -$OPTARG requires an argument" 1>&2; show_hint 0 >&2 && exit 1;;
|
||||
*) printf $'\n '"Invalid option!" 1>&2; show_hint 0 >&2 && exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check that the user has correctly set the default path to a directory ending in /
|
||||
check_default_path() {
|
||||
if ! [[ "${default_path: -1}" == "/" ]]; then default_path="$default_path/"
|
||||
debug_echo
|
||||
debug_echo "Default path does not end in \"/\" ! Adding..."
|
||||
debug_echo Default path: $default_path;
|
||||
fi
|
||||
}
|
||||
|
||||
# Checking that we set both a file size and options for audio, because these are set at the same time for simplicity
|
||||
check_valid_arguments() {
|
||||
if ([ -z "$max_file_size" ] && [ -z "$audio_set" ]) || ([ -n "$max_file_size" ] && [ -n "$audio_set" ])
|
||||
then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
get_input_file() {
|
||||
# If we haven't specified a file with -i we need to ask the user for one now
|
||||
if [ -z "$input_file" ]; then
|
||||
read -erp $'\n '"Path to input file: " input_file
|
||||
case "$input_file" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 1 >&2
|
||||
read -erp $'\n '"Path to input file: " input_file
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
# Determine if the file exists (note: this doesn't check if the file is WRITEABLE)
|
||||
while [[ ! -f "$input_file" ]]; do
|
||||
read -erp $'\n '"Input file must be a real file!"$'\n '"Path to input file: " input_file
|
||||
done
|
||||
else # Check that the -i argument is a file that exists
|
||||
while [[ ! -f "$input_file" ]]; do
|
||||
read -erp $'\n '"Input file must be a real file!"$'\n '"Path to input file: " input_file
|
||||
done
|
||||
printf $'\n '"Input File: $input_file"$'\n'
|
||||
fi
|
||||
# Grab the file size - this is useful for a comparison later
|
||||
input_file=$input_file
|
||||
input_filesize=$(stat -c%s "$input_file")
|
||||
input_filesize="$(echo "$input_filesize/1000" | bc -l)"
|
||||
|
||||
# Get the source video information
|
||||
source_resolution=$(ffprobe -i "$input_file" -v quiet -show_entries stream=height -hide_banner -of default=noprint_wrappers=1:nokey=1)
|
||||
source_length=$(ffprobe -i "$input_file" -v quiet -show_entries format=duration -hide_banner -of default=noprint_wrappers=1:nokey=1)
|
||||
# Wrapping this in brackets prevent it from getting more than one value for FPS
|
||||
source_fps=($(ffprobe -i "$input_file" -v quiet -show_entries stream=r_frame_rate -hide_banner -of default=noprint_wrappers=1:nokey=1))
|
||||
source_fps=$(echo $source_fps | bc)
|
||||
# Total frame count is used to make a progress bar
|
||||
source_frame_count=$(ffprobe -i "$input_file" -v quiet -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0)
|
||||
|
||||
# Split up the full path to extract just the filename, sans extension
|
||||
xpath=${input_file%/*}
|
||||
xbase=${input_file##*/}
|
||||
input_filename=${xbase%.*}
|
||||
}
|
||||
|
||||
# We set both the audio and the file size at the same time.
|
||||
# This is because 4chan uses the same filesize/audio settings across multiple boards.
|
||||
get_max_filesize() {
|
||||
# If we set a max file size with -m...
|
||||
if [ $max_file_size ]; then
|
||||
# ...And we said we want audio....
|
||||
if [ $audioset == "y" ]; then
|
||||
audioset="-c:a libvorbis "
|
||||
else
|
||||
audioset="-an "
|
||||
fi
|
||||
else
|
||||
if [ "$prompt" = true ]; then
|
||||
# Ask the user for target filesize based on 4chan limits
|
||||
# They are slightly below the limit to account for ffmpeg using average bitrates and usually being slightly over-size.
|
||||
# WSG and GIF have higher file size limits, and uniquely allow audio.
|
||||
read -rp $'\n '"Posting to WSG/GIF (audio and higher filesize)? [y/N]"$'\n '"Or type 'c' for a custom value"$'\n '"Enable larger file size: " response
|
||||
case "$response" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 6 >&2
|
||||
read -rp $'\n '"Enable larger file size: " response
|
||||
;;
|
||||
esac
|
||||
case "$response" in
|
||||
# WSG/GIFs file size limit is ~5MB
|
||||
[yY][eE][sS]|[yY])
|
||||
max_file_size=4900
|
||||
audioset="-c:a libvorbis "
|
||||
;;
|
||||
# A custom value needs both...
|
||||
[cC])
|
||||
# ... A file size...
|
||||
read -rp $'\n '"Enter max filesize in kilobytes: " max_file_size
|
||||
read -rp $'\n '"Would you like audio? " response
|
||||
case "$response" in
|
||||
# ...And an audio setting.
|
||||
[yY][eE][sS]|[yY])
|
||||
audioset="-c:a libvorbis "
|
||||
;;
|
||||
*)
|
||||
audioset="-an "
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
# If they said no to WSG/GIF, we can just set a "blue board" default
|
||||
*)
|
||||
max_file_size=2900
|
||||
audioset="-an "
|
||||
;;
|
||||
esac
|
||||
# If we didn't set a max file size, and we skiped prompts, set a default that works on most "blue boards"
|
||||
else
|
||||
max_file_size=2950; audioset="-an "
|
||||
fi
|
||||
fi
|
||||
|
||||
# We don't want to make the webm bigger than the source file, ffempeg cannot "add more quality"
|
||||
if [ ${input_filesize%.*} -lt $max_file_size ]; then
|
||||
max_file_size=$input_filesize
|
||||
fi
|
||||
}
|
||||
|
||||
get_codec() {
|
||||
if [ -z $codec ]; then
|
||||
# Ask the user for the codec version (vp8 or vp9), or use default (vp9) if not provided
|
||||
if [ "$prompt" = true ]; then
|
||||
read -rp $'\n '"Would you like to use VP[8] or VP[9] encoding?"$'\n '"Leave Blank: Default (VP9)"$'\n '"Codec: " codec
|
||||
fi
|
||||
fi
|
||||
case "$codec" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 8 >&2
|
||||
read -rp $'\n '"webm version: " codec
|
||||
;;
|
||||
esac
|
||||
case "$codec" in
|
||||
#VP8 is the default setting for libvpx
|
||||
[8])
|
||||
codec="-c:v libvpx "
|
||||
;;
|
||||
[9])
|
||||
codec="-c:v libvpx-vp9 "
|
||||
;;
|
||||
esac
|
||||
if [ -z $codec ]; then codec="-c:v libvpx-vp9 "; fi
|
||||
}
|
||||
|
||||
get_output_file() {
|
||||
# Ask the user for the output path if they didn't specify one with -o
|
||||
if [ -z $output_directory ]; then
|
||||
if [ "$prompt" = true ]; then
|
||||
while read -erp $'\n '"Please enter the destination path."$'\n '"Example: '$HOME/Videos/'"$'\n '"Leave Blank: Default path ($default_path)"$'\n '"Destination path: " output_directory; do
|
||||
case "$output_directory" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 2 >&2
|
||||
read -erp $'\n '"Destination path: " output_directory;
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
# Use the defaults if no path provided
|
||||
if [ -z "$output_directory" ]; then output_directory="$default_path"; fi
|
||||
|
||||
# Ask the user for the output filename
|
||||
if [ "$prompt" = true ]; then
|
||||
while read -erp $'\n '"Please enter the output filename."$'\n '"Example: 'My_Movie'"$'\n '"Leave Blank: Default filename ($input_filename)"$'\n '"Output filename: " filename; do
|
||||
case "$filename" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 2 >&2
|
||||
read -erp $'\n '"Output filename: " filename
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
# Use the input filename if no filename provided
|
||||
if [ -z "$filename" ]; then filename="$input_filename"; fi
|
||||
else
|
||||
# If the user specified a full path and filename when running the script, we use that instead
|
||||
if [ "${output_directory: -5}" == ".webm" ]; then
|
||||
temp_filename="$output_directory"
|
||||
fi
|
||||
fi
|
||||
# temp_filename is used as a placeholder while we figure out what to do with it
|
||||
if [ -z $temp_filename ]; then
|
||||
# Once again making sure our output directory ends in /
|
||||
debug_echo
|
||||
if ! [[ "${output_directory: -1}" == "/" ]]; then
|
||||
output_directory="$output_directory/"
|
||||
debug_echo "Output directory does not end in \"/\" ! Adding..."
|
||||
fi
|
||||
output_filename="$output_directory$filename.webm"
|
||||
# Check to see if the output directory exists, and if not, create it
|
||||
if [ ! -d "$output_directory" ]; then
|
||||
debug_echo "$output_directory" not found! creating...
|
||||
mkdir -p "$output_directory"
|
||||
fi
|
||||
else
|
||||
output_filename="$temp_filename"
|
||||
fi
|
||||
output_basename=${output_filename##*/}
|
||||
output_basename=${output_basename%.*}
|
||||
}
|
||||
|
||||
get_frames() {
|
||||
#
|
||||
if [ -z "$fps" ]; then
|
||||
if [ "$prompt" = true ]; then
|
||||
while read -rp $'\n '"Please enter webm framerate '(fps)'."$'\n '"Example: 30"$'\n '"Leave Blank: Source video framerate"$'\n '"Framerate: " fps; do
|
||||
case "$fps" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 3 >&2
|
||||
read -rp $'\n '"Framerate: " fps;
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if [ -z $fps ]; then fps="$source_fps"; fi;
|
||||
elif [ $fps == "d" ]; then
|
||||
fps="$source_fps"
|
||||
fi
|
||||
}
|
||||
|
||||
get_resolution() {
|
||||
# Prompt the user for the resolution
|
||||
if [ -z "$resolution" ]; then
|
||||
if [ "$prompt" = true ]; then
|
||||
while read -rp $'\n '"Please enter webm vertical render resolution."$'\n '"Example: 720"$'\n '"Leave Blank: Source video resolution."$'\n '"Resolution: " resolution; do
|
||||
case "$resolution" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 4 >&2
|
||||
read -rp $'\n '"Resolution: " resolution
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if [ -z "$resolution" ]; then resolution="$source_resolution"; fi;
|
||||
# The -r option accepts the argument "d" to use the default (source) resolution
|
||||
elif [ "$resolution" == "d" ]; then
|
||||
resolution="$source_resolution"
|
||||
fi
|
||||
}
|
||||
|
||||
get_clip_start() {
|
||||
source_length=$1
|
||||
# Ask the user where the encode should start (in seconds offset from the beginning of the source)
|
||||
if [ "$prompt" = true ]; then
|
||||
while read -rp $'\n '"Please enter webm rendering offset in SECONDS."$'\n '"Example: 31"$'\n '"Leave Blank: Start of source video."$'\n '"Offset: " input; do
|
||||
case "$input" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 5 >&2
|
||||
read -rp $'\n '"Offset: " input
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if [ -z "$input" ]; then input=0; fi
|
||||
|
||||
check_valid_clip "start" "$input" "$source_length"
|
||||
}
|
||||
|
||||
get_clip_end() {
|
||||
allowed_length=$1
|
||||
start=$2
|
||||
# Ask the user where the encode should end (in seconds offset from the beginning of the SOURCE, not from the beginning we just set)
|
||||
if [ "$prompt" = true ]; then
|
||||
while read -rp $'\n '"Please enter webm rendering length in SECONDS."$'\n '"Example: 15"$'\n '"Leave Blank: Entire source video."$'\n '"Length: " input; do
|
||||
case "$input" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 5 >&2
|
||||
read -rp $'\n '"Offset: " input
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if [ -z "$input" ]; then input=$allowed_length; fi
|
||||
|
||||
check_valid_clip "end" "$input" "$allowed_length"
|
||||
}
|
||||
|
||||
check_valid_clip() {
|
||||
input=$2
|
||||
allowed_length=$3
|
||||
while (( $(echo "$input>$allowed_length" | bc -l) )); do
|
||||
if [ $1 = "start" ]; then
|
||||
read -rp $'\n '"Rendering offset cannot be longer than the legnth of the source video! (${source_length%.*} seconds)"$'\n '"Please enter webm rendering offset in SECONDS."$'\n '"Offset: " input
|
||||
elif [ $1 = "end" ]; then
|
||||
read -rp $'\n '"Rendering length cannot be longer than the remainder of the video! (${allowed_length%.*} seconds)"$'\n '"Please enter webm rendering length in SECONDS."$'\n '"Length: " input
|
||||
fi
|
||||
fail_counter
|
||||
done
|
||||
echo $input
|
||||
}
|
||||
|
||||
fail_counter() {
|
||||
fails=$(($fails+1))
|
||||
if (( $(echo "$fails>3" | bc -l) )); then
|
||||
printf $'\n '"I'm getting really sick of this you know.";
|
||||
fi
|
||||
}
|
||||
|
||||
# Allow the user to add a title in the metadata
|
||||
get_title() {
|
||||
if [ "$prompt" = true ]; then
|
||||
if [ -z $title ]; then
|
||||
printf ""$'\n '"Add a title to be used in metadata tags"$'\n '"If left blank, the output filename ($output_basename) will be used."
|
||||
while read -rp $'\n '"Title: " title; do
|
||||
case "$title" in
|
||||
[hH][eE][lL][pP]|[hH]|[-][hH])
|
||||
show_hint 7 >&2
|
||||
read -rp $'\n '"Title: " title
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if [ -z $title ]; then title="$output_basename"; fi
|
||||
title=$title
|
||||
}
|
||||
|
||||
# I totally nabbed this from github
|
||||
# https://github.com/fearside/ProgressBar/blob/master/progressbar.sh
|
||||
ProgressBar() {
|
||||
# Process data
|
||||
progress=$(echo "((${1}*100/${2}*100)/100)/2" | bc)
|
||||
done=$(echo "(${progress}*4)/10" | bc)
|
||||
left=$(echo "40-$done" | bc)
|
||||
# Build progressbar string lengths
|
||||
done=$(printf "%${done}s")
|
||||
left=$(printf "%${left}s")
|
||||
|
||||
printf "\rProgress: [${done// /#}${left// /-}] ${progress}%%"
|
||||
}
|
||||
|
||||
ffmpeg_progress() {
|
||||
# Make it execute a subprocess with the same ID, so both are killed at the same time
|
||||
pid=$!
|
||||
trap "kill $pid 2> /dev/null" EXIT
|
||||
current_frame=0
|
||||
# Drawing the progress bar for as long as the ffmpeg process is running
|
||||
while kill -0 $pid 2> /dev/null; do
|
||||
# So that we aren't flooding the CPU with curren frame checks
|
||||
sleep 0.3;
|
||||
current_frame=$(cat .ffmpeg-log | grep frame= | tail -1)
|
||||
current_frame=${current_frame:6}
|
||||
if [ -z $current_frame ]; then current_frame=1; fi
|
||||
# Sometimes frames will get re-rendered or something idk but we don't want the % to go over 100 even if it renders more frames
|
||||
if [ $current_frame -gt $source_frame_count ]; then current_frame=$source_frame_count; fi
|
||||
ProgressBar ${current_frame} ${source_frame_count};
|
||||
done
|
||||
}
|
||||
|
||||
run_conversion() {
|
||||
debug_echo
|
||||
debug_echo Source frame count: $source_frame_count
|
||||
printf "\nBeginning 1st pass...\n"
|
||||
eval ffmpeg ${complete_command[@]} -pass 1 -passlogfile .ffmpeg-2pass-log -y null -nostdin -progress .ffmpeg-log 2>&1 > /dev/null &
|
||||
ffmpeg_progress
|
||||
# Make sure the progress bar actually finishes
|
||||
ProgressBar 200 100
|
||||
printf "\n1st pass: done"
|
||||
printf "\nBeginning 2nd pass...\n"
|
||||
# Second verse, same as the first, could get better but it's gonna get... uh, an output that isn't null
|
||||
eval ffmpeg ${complete_command[@]} -pass 2 -passlogfile .ffmpeg-2pass-log -y \""$output_filename"\" -nostdin -progress .ffmpeg-log 2>&1 > /dev/null &
|
||||
ffmpeg_progress
|
||||
ProgressBar 200 100
|
||||
printf "\n2nd pass: done"
|
||||
sleep 0.1
|
||||
|
||||
# Let the user know just how small their webm is
|
||||
output_filesize=$(stat -c%s "$output_filename")
|
||||
output_filesize="$(echo "$output_filesize/1000" | bc -l)"
|
||||
|
||||
bytes_saved="$(echo "$input_filesize-$output_filesize" | bc -l)"
|
||||
|
||||
printf "
|
||||
All done!
|
||||
|
||||
You can find the finished file at: '$output_filename'
|
||||
Total filesize: ${output_filesize%.*} Kilobytes
|
||||
You saved: ${bytes_saved%.*} Kilobytes!
|
||||
"
|
||||
}
|
||||
|
||||
if [ -z $help ]; then
|
||||
|
||||
check_default_path
|
||||
# if ! check_valid_arguments; then printf $'\n '"Error! if -a is specified, -m must also be specified, and vice versa!"$'\n' && exit 1; fi
|
||||
get_input_file
|
||||
|
||||
debug_echo
|
||||
debug_echo Input file: "$input_file"
|
||||
debug_echo Source resolution: "$source_resolution"
|
||||
debug_echo Source length: "$source_length"
|
||||
debug_echo Source fps: "$source_fps"
|
||||
|
||||
get_output_file
|
||||
|
||||
debug_echo
|
||||
debug_echo Output directory: "$output_directory"
|
||||
debug_echo Output filename: "$output_filename"
|
||||
|
||||
get_max_filesize
|
||||
|
||||
if [ $audioset = "-c:a libvorbis " ]; then audio="Yes"; else audio="No"; fi
|
||||
|
||||
debug_echo
|
||||
debug_echo Max file size: "$max_file_size"
|
||||
debug_echo Audio: $audio
|
||||
|
||||
get_codec
|
||||
|
||||
debug_echo
|
||||
debug_echo Codec: "${codec:6}"
|
||||
|
||||
get_frames
|
||||
|
||||
debug_echo
|
||||
debug_echo FPS: "$fps"
|
||||
|
||||
get_resolution
|
||||
|
||||
debug_echo
|
||||
debug_echo Resolution "$resolution"
|
||||
|
||||
if [ $start ]; then
|
||||
start=$(check_valid_clip "start" "$start" "$source_length")
|
||||
else
|
||||
start=$(get_clip_start "$source_length")
|
||||
fi
|
||||
|
||||
allowed_length=$(echo "$source_length - $start" | bc -l)
|
||||
|
||||
debug_echo
|
||||
debug_echo Start: "$start"
|
||||
debug_echo Allowed length: "$allowed_length"
|
||||
|
||||
if [ $end ]; then
|
||||
end=$(check_valid_clip "end" "$end" "$allowed_length")
|
||||
else
|
||||
end=$(get_clip_end "$allowed_length" "$start")
|
||||
fi
|
||||
|
||||
length=$(echo "$allowed_length-$start" | bc)
|
||||
|
||||
debug_echo
|
||||
debug_echo Source length: "$source_length"
|
||||
debug_echo End: "$end"
|
||||
debug_echo Length: "$length"
|
||||
|
||||
bitrate=$(echo "8*$max_file_size/$length" | bc)'K'
|
||||
|
||||
debug_echo
|
||||
debug_echo Bitrate: "$bitrate"
|
||||
|
||||
get_title
|
||||
|
||||
debug_echo
|
||||
debug_echo Title: "$title"
|
||||
|
||||
# Tell the user what we've just done, and ask them if these settings are ok
|
||||
printf $'\n '"Creating webm with the following settings:
|
||||
Codec: ${codec#*v}
|
||||
Audio: $audio
|
||||
Resolution: $resolution
|
||||
Framerate: $fps
|
||||
Start at: $start
|
||||
End at: $end
|
||||
Duration: $length
|
||||
Target File Size: "$max_file_size"MB
|
||||
Bitrate: $bitrate
|
||||
Title: $title
|
||||
Output to: $output_filename
|
||||
"
|
||||
|
||||
####################THE PART WHERE THE MAGIC HAPPENS#####################
|
||||
|
||||
# complete_command="-i $input_file -metadata thanks-to=Ruzakai -metadata date-encoded=$(date +'%m-%d-%Y') -metadata title=$title -ss $start -t $length $codec -b:v $bitrate -vf fps=$fps,scale=-1:$resolution $audioset-sn -loglevel error -f webm"
|
||||
|
||||
complete_command=("-i \"$input_file\"" "-metadata thanks-to=Ruzakai" "-metadata date-encoded=$(date +'%m-%d-%Y')" "-metadata title=\"$title\"" "-ss $start" "-t $length" "$codec" "-b:v $bitrate" "-vf fps=$fps,scale=-1:$resolution" "$audioset" "-sn" "-loglevel error" -f webm)
|
||||
|
||||
#########################################################################
|
||||
|
||||
if [ "$prompt" = true ]; then
|
||||
read -rp $'\n '"Start the conversion? [Y/n]: " continue
|
||||
|
||||
else
|
||||
continue=y
|
||||
fi
|
||||
case "$continue" in
|
||||
[yY][eE][sS]|[yY])
|
||||
run_conversion $complete_command $output_filename
|
||||
;;
|
||||
*)
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
printf $'\n '"Would you like to view the created webm?"
|
||||
read -rp $'\n '"View webm? [y/N]: " view
|
||||
case "$view" in
|
||||
[yY][eE][sS]|[yY])
|
||||
xdg-open "$output_filename"
|
||||
;;
|
||||
*)
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
else
|
||||
cat <<EOF | less
|
||||
_ _ ______________ ________________ __
|
||||
| | | | ___| ___ \ \/ |_ _| ___\ \ / /
|
||||
| | | | |__ | |_/ / . . | | | | |_ \ V /
|
||||
| |/\| | __|| ___ \ |\/| | | | | _| \ /
|
||||
\ /\ / |___| |_/ / | | |_| |_| | | |
|
||||
\/ \/\____/\____/\_| |_/\___/\_| \_/
|
||||
|
||||
VERSION: 2.1 CREATED: 1/1/2021 BY: ANON
|
||||
|
||||
NAME
|
||||
webmify - convert a video file into a webm using ffmpeg
|
||||
|
||||
SYNOPSIS
|
||||
webmify [OPTIONS]
|
||||
webmify
|
||||
|
||||
DESCRIPTION
|
||||
Designed to get the best quality WEBM for posting on 4chan. Options for the two
|
||||
most common board file sizes and audio restrcitions.
|
||||
|
||||
Convert a single INPUT file to an OUTPUT directory. The output file will use the
|
||||
same name as the source unless otherwise specified.
|
||||
|
||||
Arguments are optional. If no arguments are specified, the user is prompted for
|
||||
conversion settings.
|
||||
|
||||
I highly reccomend placing this script in $HOME/Scripts and creating an alias
|
||||
alias wbm='$HOME/Scripts/webmify.sh"
|
||||
|
||||
OPTIONS
|
||||
-i
|
||||
INPUT file.
|
||||
|
||||
-o
|
||||
OUTPUT directory.
|
||||
If a filename is provided instead of a directory, it will be used for the
|
||||
output FILENAME.
|
||||
If the user wishes to specify a filename here, it must end in ".webm"
|
||||
|
||||
-n
|
||||
Output FILENAME, not including PATH.
|
||||
|
||||
-f
|
||||
Desired output FRAMERATE in frames per second
|
||||
|
||||
-r
|
||||
Desired output vertical RESOLUTION.
|
||||
Example: "720" for 720p
|
||||
|
||||
-s
|
||||
Time to START the encode, in seconds from the beginning of the video.
|
||||
This will trim off N number of seconds from the beginning of the video.
|
||||
|
||||
-e
|
||||
When the output file should END, in seconds from the beginning of the
|
||||
video.
|
||||
Cannot be longer than the source length.
|
||||
|
||||
-m
|
||||
Specify the MAX FILE SIZE in bytes.
|
||||
Because of how FFMPEG works, this should be a little under the actual
|
||||
desired file size.
|
||||
Example: "4900" for ~5MB
|
||||
|
||||
If -m is specified, -a MUST ALSO be specified.
|
||||
|
||||
-a
|
||||
Specify if the output should have AUDIO or not.
|
||||
'y' for audio, anything else for no audio.
|
||||
|
||||
If -a is specified, -m MUST ALSO be specified.
|
||||
|
||||
-t
|
||||
String to be used as the metadata TITLE.
|
||||
|
||||
-c
|
||||
Specify ffmpeg to use either VP8 or VP9 encoding.
|
||||
VP9 offers higher quality, while VP8 will encode faster.
|
||||
Example: "9" for VP9
|
||||
|
||||
-h
|
||||
Show this HELP message.
|
||||
|
||||
-v
|
||||
Enable VERBOSE debugging.
|
||||
|
||||
-y
|
||||
Will skip all user prompts. If a certain value is not specified, the
|
||||
default will be used.
|
||||
The default value for MAX FILE SIZE is 2950.
|
||||
User is still prompted for INPUT file if none is specified.
|
||||
|
||||
DEFAULTS
|
||||
If no options are given, and a prompt is skipped, the default settings will be
|
||||
used. They are as follows:
|
||||
|
||||
OUTPUT DIRECTORY
|
||||
The default directory is configured in the beginning of this
|
||||
script file. Out of the box, this is "$HOME/Videos/webms".
|
||||
If the default directory setting in this script file is left
|
||||
blank, converted videos will output to the same directory the
|
||||
script was run from.
|
||||
|
||||
OUTPUT FILENAME
|
||||
Same as source filename.
|
||||
|
||||
FRAMERATE
|
||||
Same as source framerate rounded to the nearest whole number (eg.
|
||||
29.997 FPS becomes 29)
|
||||
|
||||
RESOLUTION
|
||||
Same as source resolution.
|
||||
|
||||
START and END
|
||||
No default value - if none is provided the entire source video
|
||||
will be processed.
|
||||
|
||||
MAX FILE SIZE
|
||||
2900MB
|
||||
|
||||
AUDIO
|
||||
No audio.
|
||||
|
||||
TITLE
|
||||
Same as source filename.
|
||||
|
||||
CODEC
|
||||
VP9. If you run into trouble with VP9 support, try using VP8
|
||||
instead.
|
||||
|
||||
AUTHOR
|
||||
Just a guy trying to make some webms
|
||||
|
||||
COPYRIGHT
|
||||
You can use this however you want. I give you permission.
|
||||
Just don't use it like that!
|
||||
|
||||
EOF
|
||||
fi
|
Loading…
x
Reference in New Issue
Block a user