Pastebin PRO Accounts SPRING SPECIAL! For a limited time only get 40% discount on a LIFETIME PRO account! Offer Ends April 18th!
SHARE
TWEET
webm-convert
a guest
Nov 30th, 2014
202
Never
- #!/bin/bash
- filesize=$1
- audio_bitrate=$2
- source=$3
- temp="/tmp/${RANDOM}_ffmpeg_vstats"
- quality_decrease=2.5 #decreases quality X times
- absolute_minimum_bitrate=64 #minimum video bitrate and vertical resolution
- q_min=4 #starting value for qmin
- q_max=20 #starting value for qmax
- q_max_maximum=40 #maximum value for qmax
- percent_expectation=0.1 #required gains for quality loss
- fullpath="$(readlink -f "$source")"
- source_dir="$(dirname "$fullpath")"
- filename=$(basename "$source")
- filename="${filename%.*}"
- if [ -z "$filesize" ] || [ -z "$audio_bitrate" ] || [ -z "$source" ] || [ -z "$(echo $filesize | grep "[0-9]")" ] || [ -z "$(echo $audio_bitrate | grep "[0-9]")" ]
- then
- echo "USAGE: $0 [Filesize in MB] [Audio bitrate in kbit/s] [Filename]"
- exit 0
- fi
- if [ "$audio_bitrate" -ge "45" ]
- then
- encode_audio="-codec:a libvorbis -b:a ${audio_bitrate}k -ac 2 -clev 3dB -slev -6dB"
- else
- audio_bitrate=0
- encode_audio="-an"
- fi
- filesize_bytes="$(echo "$filesize * 1048576" | bc | awk -F'.' '{print $1}')"
- display ()
- {
- time_start=$(date +%s)
- frame_count=0
- time_eta=0
- time_elapsed=0
- while [ -e /proc/$PID ]
- do
- sleep 2
- if [ -e "$temp" ]
- then
- ffmpeg_vstats=$(awk '{gsub(/frame=/, "")}/./{line=$1-1} END{print line}' $temp)
- if [ -n "$ffmpeg_vstats" ]
- then
- if [ "$ffmpeg_vstats" -gt "$frame_count" ]
- then
- frame_count=$ffmpeg_vstats
- progress=$(( 100 * frame_count / source_frames ))
- time_elapsed=$(( $(date +%s) - time_start ))
- echo $time_elapsed > /tmp/elapsed.value
- time_eta=$(date -d @$(awk 'BEGIN{print int(('$time_elapsed' / '$frame_count') * ('$source_frames' - '$frame_count'))}') -u +%H:%M:%S)
- fi
- fi
- echo -ne "\rElapsed Time: $(date -d @$time_elapsed -u +%H:%M:%S)\tETA: $time_eta\t ${progress}%"
- fi
- done
- }
- cleanup ()
- {
- rm -f "$temp" 2> /dev/null
- rm -f "$source_dir/$source_checksum-0.log" 2> /dev/null
- }
- badrun ()
- {
- rm -f "$temp" 2> /dev/null
- rm -f "$output_file_new" 2> /dev/null
- rm -f "$source_dir/$source_checksum-0.log" 2> /dev/null
- }
- dirtyexit ()
- {
- rm -f "$temp" 2> /dev/null
- rm -f "$output_file_new" 2> /dev/null
- rm -f "$output_file_old" 2> /dev/null
- rm -f "$source_dir/$source_checksum-0.log" 2> /dev/null
- }
- calculateresize ()
- {
- if [ "$bitrate" -le "$absolute_minimum_bitrate" ]
- then
- bitrate=$absolute_minimum_bitrate
- resize_height=$absolute_minimum_bitrate
- resize="-vf scale=-1:${bitrate}"
- else
- source_bpp=$(echo "scale=10; ($source_bitrate/$source_area)/$quality_decrease" | bc)
- resize_area=$(echo "scale=10; $bitrate/$source_bpp" | bc)
- resize_height=$(echo "scale=10; $source_height * ($resize_area/$source_area)" | bc | awk -F'.' '{print $1}' | tr -d ' ')
- if [ "$resize_height" -ge "$source_height" ]
- then
- resize_height=$source_height
- fi
- resize="-vf scale=-1:${resize_height}"
- fi
- }
- adjustmaxbitrate ()
- {
- if [ "$source_bitrate" -le "$bitrate" ]
- then
- bitrate=$source_bitrate
- resize_height=$source_height
- resize=""
- exit_increase=1
- fi
- }
- adjustslices ()
- {
- if [ "$resize_height" -le "480" ]
- then
- slices="-slices 1"
- else
- if [ "$resize_height" -lt "720" ]
- then
- slices="-slices 2"
- else
- slices="-slices 4"
- fi
- fi
- }
- adjustquantizer ()
- {
- byte_check=$(echo "$output_size - $filesize_bytes" | bc | awk -F'.' '{print $1}')
- #echo "adjust quantizer"
- if [ "$byte_check" -ge "2000000" ]
- then
- let q_max=q_max+10
- q_adjust=10
- else
- if [ "$byte_check" -ge "1000000" ]
- then
- let q_max=q_max+6
- q_adjust=6
- else
- if [ "$byte_check" -ge "10000" ]
- then
- let q_max=q_max+4
- q_adjust=4
- else
- let q_max=q_max+2
- q_adjust=2
- fi
- fi
- if [ "$q_max" -gt "$q_max_maximum" ]
- then
- #echo "adjust bitrate 3"
- q_max=$q_max_maximum
- q_adjust=255
- let bitrate=bitrate-10
- calculateresize
- adjustslices
- fi
- fi
- }
- if [ -e "$source" ]
- then
- time=$(ffmpeg -i "$source" 2>&1 | grep Duration | cut -d ' ' -f 4 | cut -d '.' -f 1 | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
- if [ "$(echo $time | grep [0-9])" ]
- then
- thread_number=$(grep -m1 "siblings" /proc/cpuinfo | awk -F": " '{print $2}')
- source_checksum=$(md5sum "$source" | awk '{print $1}')
- source_fps=$(ffmpeg -i "$source" 2>&1 | sed -n "s/.*, \(.*\) tbr.*/\1/p")
- source_duration=$(ffmpeg -i "$source" 2>&1 | sed -n "s/.* Duration: \([^,]*\), .*/\1/p" | awk -F':' '{print $1 * 3600 + $2 * 60 + $3}')
- source_bitrate=$(ffmpeg -i "$source" 2>&1 | grep bitrate | awk '{print $6}')
- source_area=$(ffmpeg -i "$source" 2>&1 | grep Video | grep 0.0 | awk -F'[' '{print $1}' | awk -F',' '{print $3}' | awk -F'x' '{print $1 * $2}')
- source_height=$(ffmpeg -i "$source" 2>&1 | grep Video | grep 0.0 | awk -F'[' '{print $1}' | awk -F',' '{print $3}' | awk -F'x' '{print $2}')
- source_frames=$(echo "scale=4; $source_duration * $source_fps" | bc | awk -F'.' '{print $1}')
- bitrate=$(echo "(($filesize*8192)/$time)-$audio_bitrate-10" | bc)
- max_bitrate=$(echo "$bitrate*4" | bc)
- min_bitrate=$(echo "$bitrate/10" | bc)
- if [ -z "$source_height" ] || [ -z "$source_bitrate" ] || [ -z "$source_area" ]
- then
- echo "$source cannot be read by ffmpeg."
- exit 1
- else
- if [ -z "$(echo $source_height | grep "[0-9]")" ]
- then
- echo "$source cannot be read by ffmpeg."
- exit 1
- fi
- if [ -z "$(echo $source_bitrate | grep "[0-9]")" ]
- then
- echo "$source cannot be read by ffmpeg."
- exit 1
- fi
- if [ -z "$(echo $source_area | grep "[0-9]")" ]
- then
- echo "$source cannot be read by ffmpeg."
- exit 1
- fi
- fi
- if [ "$source_bitrate" -le "$bitrate" ]
- then
- bitrate=$source_bitrate
- resize_height=$source_height
- resize=""
- else
- calculateresize
- fi
- adjustslices
- output_file_new="$source_dir/${filename}_vbr_${bitrate}k.webm"
- max_bitrate=$(echo "$bitrate*2" | bc)
- min_bitrate=$(echo "$bitrate/10" | bc)
- trap "{ dirtyexit; exit 255; }" SIGINT SIGTERM
- if [ ! -e "$output_file_new" ]
- then
- attempt=1
- finished=0
- q_adjust=0
- increase=0
- exit_increase=0
- while [ "$finished" -ne "1" ]
- do
- output_file_new="$source_dir/${filename}_vbr_${bitrate}k.webm"
- #echo $output_file_new
- clear
- #echo
- echo "Encoding: $filename"
- echo "Video @ ${bitrate}kbit/s"
- if [ "$audio_bitrate" -eq "0" ]
- then
- echo "Audio @ Disabled"
- else
- echo "Audio @ ${audio_bitrate}kbit/s"
- fi
- echo "qmin: $q_min"
- echo "qmax: $q_max"
- if [ -n "$old_size" ]
- then
- echo "Last attempt was: ${old_size} bytes"
- fi
- echo "Attempt: $attempt"
- echo "Starting first pass."
- ffmpeg -y -i "$source" \
- -vstats_file $temp \
- -loglevel quiet -c:v libvpx \
- -threads $thread_number \
- -passlogfile "$source_dir/$source_checksum" \
- -auto-alt-ref 1 $slices \
- -lag-in-frames 16 \
- -cpu-used 0 \
- -keyint_min 0 \
- -g 360 \
- -qmin $q_min \
- -qmax $q_max \
- -quality good \
- -minrate ${min_bitrate}k \
- -maxrate ${max_bitrate}k \
- -b:v ${bitrate}k ${resize} \
- -an -pass 1 -f webm /dev/null
- echo "Starting second pass."
- ffmpeg -y -i "$source" \
- -vstats_file $temp \
- -loglevel quiet -c:v libvpx \
- -threads $thread_number \
- -passlogfile "$source_dir/$source_checksum" \
- -auto-alt-ref 1 $slices \
- -lag-in-frames 16 \
- -cpu-used 0 \
- -keyint_min 0 \
- -g 360 \
- -qmin $q_min \
- -qmax $q_max \
- -quality good \
- -minrate ${min_bitrate}k \
- -maxrate ${max_bitrate}k \
- -b:v ${bitrate}k ${resize} \
- $encode_audio -pass 2 -f webm "$output_file_new" &
- PID=$! &&
- display
- rm -f $temp
- output_size=$(du -b "$output_file_new" | awk '{print $1}')
- if [ "$output_size" -lt "$filesize_bytes" ]
- then
- if [ "$attempt" -eq "1" ] || [ "$increase" -eq "1" ] || [ "$q_adjust" -eq "10" ] || [ "$q_adjust" -eq "6" ] || [ "$q_adjust" -eq "4" ] || [ "$q_adjust" -eq "2" ] && [ "$exit_increase" -eq "0" ]
- then
- rm -f "$output_file_old" 2> /dev/null
- output_file_old=$output_file_new
- increase=1
- let bitrate=bitrate+10
- calculateresize
- adjustmaxbitrate
- adjustslices
- else
- if [ "$output_size" -eq "0" ]
- then
- badrun
- echo "The file failed to encode."
- echo "Please try again with a larger filesize or audio bitrate."
- exit 5
- else
- finished=1
- fi
- fi
- else
- if [ ! -e "$output_file_old" ]
- then
- badrun
- if [ "$q_adjust" -eq "255" ]
- then
- let bitrate=bitrate-10
- calculateresize
- adjustslices
- #echo "adjust bitrate 1"
- else
- if [ "$attempt" -gt "2" ]
- then
- output_difference="$(echo "($old_size - $output_size)" | bc | awk -F'.' '{print $1}')"
- expectation="$(echo "$old_size * $percent_expectation" | bc | awk -F'.' '{print $1}')"
- if [ "$output_difference" -lt "$expectation" ]
- then
- if [ "$q_adjust" -eq 10 ]
- then
- let q_max=q_max-q_adjust
- fi
- q_adjust=255
- let bitrate=bitrate-10
- calculateresize
- adjustslices
- #echo "adjust bitrate 2"
- else
- adjustquantizer
- fi
- else
- adjustquantizer
- fi
- fi
- else
- badrun
- output_file_new=$output_file_old
- finished=1
- fi
- fi
- old_size=$output_size
- let attempt=attempt+1
- done
- if [ "$finished" -eq "1" ]
- then
- echo
- echo "Encode finished."
- du -b "$output_file_new"
- cleanup
- else
- echo
- echo "Unable to encode file to required size."
- echo "Increase filesize limit to accomidate this file."
- cleanup
- fi
- else
- echo "File already exists."
- fi
- else
- echo "$source cannot be read by ffmpeg."
- cleanup
- exit 1
- fi
- else
- echo "File does not exist."
- cleanup
- exit 2
- fi
RAW Paste Data
