From a10c8f0e74bd658b22dc49b43ebe582f57810ca4 Mon Sep 17 00:00:00 2001
From: anon <anon@anon.anon>
Date: Tue, 14 Mar 2023 20:28:23 +0100
Subject: [PATCH] init

---
 webmify.sh | 853 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 853 insertions(+)
 create mode 100644 webmify.sh

diff --git a/webmify.sh b/webmify.sh
new file mode 100644
index 0000000..c77353f
--- /dev/null
+++ b/webmify.sh
@@ -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