Last active
January 21, 2024 10:42
-
-
Save ArnoldsK/291ffaa32715e6830136d1199fc73f22 to your computer and use it in GitHub Desktop.
Bash script for reducing a file size of a video using ffmpeg to reduce bitrate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Usage: | |
# ~$ sh reduce_video_file_size.sh [./input.mp4] [size mb] [./output.mp4] | |
# Parameters can be preset or set by providing none | |
# Input and output names must end with ".mp4" | |
# Can use Git Bash to run the script on Windows | |
display_help() { | |
local FILE=`basename "$0"` | |
echo "" | |
echo "Usage: $FILE input_file target_size_mb [output_file=output.mp4]" | |
exit 0 | |
} | |
INPUT_FILE=$1 | |
TARGET_SIZE_MB=$2 | |
OUTPUT_FILE=$3 | |
# Ask for input before validating | |
if [[ $INPUT_FILE == "" ]]; then | |
read -p "Enter the input file name: " INPUT_FILE | |
fi | |
if [[ $TARGET_SIZE_MB == "" ]]; then | |
read -p "Enter the target file size in MB: " TARGET_SIZE_MB | |
fi | |
if [[ $OUTPUT_FILE == "" ]]; then | |
read -p "Enter the output file name: (output.mp4) " OUTPUT_FILE | |
fi | |
# Require input file name | |
if [[ $INPUT_FILE == "" ]]; then | |
echo "Input file name missing" | |
display_help | |
fi | |
# Require target size | |
if [[ $TARGET_SIZE_MB == "" || !($TARGET_SIZE_MB > 0) ]]; then | |
echo "Target size has to be at least 1 MB" | |
display_help | |
fi | |
# Set the default output file name | |
if [[ $OUTPUT_FILE == "" ]]; then | |
OUTPUT_FILE="output.mp4" | |
fi | |
# Check if the input file exists | |
if [ ! -f $INPUT_FILE ]; then | |
echo "Input file $INPUT_FILE not found" | |
exit 0 | |
fi | |
# Check if the file size is already below the target size | |
INPUT_FILE_SIZE_MB=$(($(wc -c < $INPUT_FILE) / 1000000)) | |
if [ $INPUT_FILE_SIZE_MB -lt $TARGET_SIZE_MB ]; then | |
echo "The file size is already below the target size" | |
exit 0 | |
fi | |
# Additional bitrate division to make sure the size is below the target | |
ADD_TO_DIVIDER=50 | |
# Calculate the target bitrate | |
BITRATE="$(awk "BEGIN {print int($TARGET_SIZE_MB * 1024 * 1024 * 8 / $(ffprobe \ | |
-v error \ | |
-show_entries format=duration \ | |
-of default=noprint_wrappers=1:nokey=1 \ | |
"$INPUT_FILE" \ | |
) / (1000 + $ADD_TO_DIVIDER))}")k" | |
# Custom 2pass log file prefix | |
PASSLOGFILE="$INPUT_FILE-pass" | |
# Do the resizing | |
echo "Working..." | |
ffmpeg -v error -y -i $INPUT_FILE -c:v libx264 -preset medium -b:v $BITRATE -pass 1 -passlogfile $PASSLOGFILE -c:a aac -b:a 128k -f mp4 /dev/null && \ | |
ffmpeg -v error -i $INPUT_FILE -c:v libx264 -preset medium -b:v $BITRATE -pass 2 -passlogfile $PASSLOGFILE -c:a aac -b:a 128k $OUTPUT_FILE | |
echo "Done" | |
# Delete junk files 2pass creates - could not find a way to disable | |
if [ -f $PASSLOGFILE-0.log ]; then | |
rm $PASSLOGFILE-0.log | |
fi | |
if [ -f $PASSLOGFILE-0.log.mbtree ]; then | |
rm $PASSLOGFILE-0.log.mbtree | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment