extratone / i

All of my iOS/iPhone-related documentation, files, media, etc.
The Unlicense
37 stars 0 forks source link

Resize Video to Target Size Shortcut #300

Open extratone opened 1 year ago

extratone commented 1 year ago

Resize Video to Target Size Shortcut

Updated 02152023-204521


Social

I'm gonna call this one Mastodon-related because basically any other method of getting a given video clip below the file limit (40MB, in mastodon.social's case,) drives me crazy. #shortcuts #video #automation #mac https://routinehub.co/shortcut/14270

- [Mastodon](https://mastodon.social/@DavidBlue/109872079917980053) - [Telegram](https://t.me/extratone/13627) --- ## Re-encode video files to a specific size target with ffmpeg. **Please note**: this shortcut is macOS-only. ### Requirements - [**ffmpeg**](https://ffmpeg.org) (`brew install ffmpeg`) This shortcut re-encodes single inputted video files to a **specified file size target** (in MB, per run) with [**ffmpeg**](https://ffmpeg.org), 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](https://www.matthewcassinelli.com/actions/save-file). ### 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](https://matthewcassinelli.com/actions/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 - [Original Stack Overflow answer](https://stackoverflow.com/a/61146975/14383008) (whoo!) - [Script Gist](https://gist.github.com/extratone/4e9ffa59994ca32aaba3666c2031d9b1) ```bash #!/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 ```