Resize Video to Target Size Shortcut

Resize Video Files to a Target File Size with Siri Shortcuts

Re-encode video files to a specific size target with ffmpeg.


Please note: this shortcut is macOS-only.

Requirements

This shortcut re-encodes single inputted video files to a specified file size target (in MB, per run) with ffmpeg, which it will then save to a new .mp4 file entitled [source filename]-[provided file size]MB.mp4 in a directory of your choosing via a Save File action.

Installation

At install, you will be asked to specify:

  1. The default source prompt for the shortcut (Photos will ask you for a video file from iCloud Photos while Files will use a standard Finder prompt.)
  2. Whether or not you’d like the Delete Immediately option in the Delete Files action toggled on by default. This action is handling a (frankly, completely redundant) file - neither the source file nor the output from the Save File action will be deleted.

Source

#!/bin/bash 
# 
# Re-encode a video to a target size in MB. 
# Example: 
#    ./this_script.sh video.mp4 15 
 
T_SIZE="$2" # target size in MB 
T_FILE="${1%.*}-$2MB.mp4" # filename out 
 
# Original duration in seconds 
O_DUR=$(\ 
    ffprobe \ 
    -v error \ 
    -show_entries format=duration \ 
    -of csv=p=0 "$1") 
 
# Original audio rate 
O_ARATE=$(\ 
    ffprobe \ 
    -v error \ 
    -select_streams a:0 \ 
    -show_entries stream=bit_rate \ 
    -of csv=p=0 "$1") 
 
# Original audio rate in KiB/s 
O_ARATE=$(\ 
    awk \ 
    -v arate="$O_ARATE" \ 
    'BEGIN { printf "%.0f", (arate / 1024) }') 
 
# Target size is required to be less than the size of the original audio stream 
T_MINSIZE=$(\ 
    awk \ 
    -v arate="$O_ARATE" \ 
    -v duration="$O_DUR" \ 
    'BEGIN { printf "%.2f", ( (arate * duration) / 8192 ) }') 
 
# Equals 1 if target size is ok, 0 otherwise 
IS_MINSIZE=$(\ 
    awk \ 
    -v size="$T_SIZE" \ 
    -v minsize="$T_MINSIZE" \ 
    'BEGIN { print (minsize < size) }') 
 
# Give useful information if size is too small 
if [[ $IS_MINSIZE -eq 0 ]]; then 
    printf "%s\n" "Target size ${T_SIZE}MB is too small!" >&2 
    printf "%s %s\n" "Try values larger than" "${T_MINSIZE}MB" >&2 
    exit 1 
fi 
 
# Set target audio bitrate 
T_ARATE=$O_ARATE 
 
 
# Calculate target video rate - MB -> KiB/s 
T_VRATE=$(\ 
    awk \ 
    -v size="$T_SIZE" \ 
    -v duration="$O_DUR" \ 
    -v audio_rate="$O_ARATE" \ 
    'BEGIN { print  ( ( size * 8192.0 ) / ( 1.048576 * duration ) - audio_rate) }') 
 
# Perform the conversion 
ffmpeg \ 
    -y \ 
    -i "$1" \ 
    -c:v libx264 \ 
    -b:v "$T_VRATE"k \ 
    -pass 1 \ 
    -an \ 
    -f mp4 \ 
    /dev/null \ 
&& \ 
ffmpeg \ 
    -i "$1" \ 
    -c:v libx264 \ 
    -b:v "$T_VRATE"k \ 
    -pass 2 \ 
    -c:a aac \ 
    -b:a "$T_ARATE"k \ 
    $T_FILE

Subscribe to Crud

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe