webmify 2.0

 avatar
unknown
sh
2 years ago
32 kB
31
Indexable
#!/bin/bash

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() {
    debug_echo
    debug_echo Showing hint: $1
    case "$1" in
    options)
        echo "
    Usage: webmify.sh [OPTIONS]
    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

    Or, you could run the script with no options
    and I will hold your hand through this scary
    terminal application.
        "
            ;;
    filename)
            echo "
    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."
            ;;
    output)
            echo "
    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."
            ;;
    fps)
            echo "
    Specify the FPS (Frames Per Second) you want for the output
    video. The most common FPS values are 24, 30 (or 29) and 60."
            ;;
    resolution)
            echo "
    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."
            ;;
    clip)
            echo "
    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."
            ;;
    filesize)
            echo "
    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."
            ;;
    title)
            echo "
    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."
            ;;
    codec)
            echo "
    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."
        ;;
    esac

    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 options >&2 && exit 1;;
#         \?) no_opts="true";;
    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 filename >&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 filesize >&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 codec >&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 output >&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 output >&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 fps >&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 resolution >&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 clip >&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 clip >&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 title >&2
                            read -rp $'\n    '"Title: " title
                            break
                        ;;
                            *)
                                break
                            ;;
                    esac
            done
        fi
    fi
    if [ -z $title ]; then title="$output_basename"; fi
}

# I totally nabbed this from github
# https://github.com/fearside/ProgressBar/blob/master/progressbar.sh
ProgressBar() {
    # Process data
    let _progress=(${1}*100/${2}*100)/100
    let _progress=(${_progress}/2)
    let _done=(${_progress}*4)/10
    let _left=40-$_done
    # 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() {
    complete_command=$1
    output_filename=$2
    debug_echo
    debug_echo Source frame count: $source_frame_count
    printf "\nBeginning 1st pass...\n"
    ffmpeg "$complete_command" -pass 1 -passlogfile .ffmpeg-2pass-log -y null -nostdin -progress .ffmpeg-log > /dev/null 2>&1 &
    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
    ffmpeg "$complete_command" -pass 2 -passlogfile .ffmpeg-2pass-log -y "$output_filename" -nostdin -progress .ffmpeg-log > /dev/null 2>&1 &
    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"

    #########################################################################

    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
Editor is loading...