Skip to content

Instantly share code, notes, and snippets.

@davekobrenski
Last active August 7, 2026 15:17
Show Gist options
  • Select an option

  • Save davekobrenski/8532a23238d83f019e1104217f41839e to your computer and use it in GitHub Desktop.

Select an option

Save davekobrenski/8532a23238d83f019e1104217f41839e to your computer and use it in GitHub Desktop.
Batch Optimize Videos for WEB with FFmpeg
#!/bin/sh
# colors
green='\033[0;32m'
purple='\033[0;35m'
cyan='\033[0;36m'
yellow='\033[0;33m'
clear='\033[0m'
# loop through immediate subdirectories
for dir in */
do
MYDIR=$(basename "$dir")
NEWDIR="${dir}compressed"
printf "%bConverting files in: %s\n---------------------------------------------\n%b\n" "$green" "$MYDIR" "$clear"
if [ ! -d "$NEWDIR" ]
then
printf " Creating new dir: %s\n" "$NEWDIR"
mkdir "$NEWDIR"
else
printf " Dir already exists: %s\n" "$NEWDIR"
fi
printf "%b Preparing files in %s:%b\n\n" "$yellow" "$MYDIR" "$clear"
for file in "./$dir"*.mov "./$dir"*.MOV
do
# skip if no files matched the pattern
[ -e "$file" ] || continue
FNAME=$(basename "${file%.*}")
NEWFILE="./${NEWDIR}/${FNAME}_1080p_H264_CRF-23.mp4"
printf " %s\n" "$file"
printf "%b %s %b\n" "$cyan" "$NEWFILE" "$clear"
# Standard web:
# -crf 23 -preset medium
# Higher quality:
# -crf 21 -preset slow
# Smaller files:
# -crf 24 -preset medium
ffmpeg -n -i "$file" \
-vf "scale=-2:'min(1080,ih)'" \
-c:v libx264 \
-crf 23 \
-preset medium \
-pix_fmt yuv420p \
-c:a aac \
-b:a 128k \
-movflags +faststart \
"$NEWFILE"
done
printf "\n"
done
@davekobrenski

davekobrenski commented Feb 21, 2025 •

Copy link
Copy Markdown
Author

Video Compression Script

This script batch-compresses .mov / .MOV video files for web delivery using FFmpeg.

It is designed to be run from a parent directory that contains one or more subfolders of videos. The script looks inside each immediate subfolder, finds .mov and .MOV files, and creates optimized .mp4 versions inside a new compressed folder within each subfolder.

Requirements

FFmpeg must already be installed on your machine and available from the command line.

To check whether FFmpeg is installed, run:

ffmpeg -version

What this script produces

The script creates web-friendly H.264 .mp4 files using the following settings:

Video codec: H.264 / libx264
Container: MP4
CRF: 23
Preset: medium
Pixel format: yuv420p
Maximum height: 1080p
Audio codec: AAC
Audio bitrate: 128 kbps
Fast start: enabled

In practical terms, this means:

  • Videos are converted to standard .mp4 files suitable for web playback.
  • Large source files, such as ProRes .mov exports, are compressed to much smaller H.264 files.
  • Videos taller than 1080px are scaled down to 1080p height.
  • Videos smaller than 1080p are not upscaled.
  • Aspect ratio is preserved.
  • The output width is forced to an even number for H.264 compatibility.
  • Audio is converted to AAC at 128 kbps.
  • faststart is enabled so web videos can begin playback before the entire file has downloaded.
  • Original files are left untouched.

Output files are named using this pattern:

OriginalFilename_1080p_H264_CRF-23.mp4

For example:

Video1.mov

becomes:

Video1_1080p_H264_CRF-23.mp4

Compression settings

The current FFmpeg command is:

ffmpeg -n -i "$file" \
  -vf "scale=-2:'min(1080,ih)'" \
  -c:v libx264 \
  -crf 23 \
  -preset medium \
  -pix_fmt yuv420p \
  -c:a aac \
  -b:a 128k \
  -movflags +faststart \
  "$NEWFILE"

CRF

The script currently uses:

-crf 23

CRF controls the visual quality / file size balance. Lower numbers produce higher quality and larger files. Higher numbers produce smaller files and lower quality.

Useful options to test:

-crf 21

Higher quality, larger file size.

-crf 23

Good general-purpose web compression.

-crf 24

Smaller files, still often acceptable depending on the source video.

Preset

The script currently uses:

-preset medium

The preset controls encoding speed and compression efficiency. It does not directly set quality; CRF does that.

Useful options:

-preset medium

Good default balance of speed and file size.

-preset slow

Slower encode, potentially smaller files at similar visual quality.

Instructions

This script is non-destructive and will leave original files intact. Optimized videos will be placed in a folder called compressed.

  1. Place this shell script in a directory that contains other folders with videos in them.

For example:

MyDir/
├── convert.sh
├── Videos/
│   ├── Video1.mov
│   └── Video2.mov
└── MoreVideos/
    ├── Video3.mov
    └── Video4.mov
  1. In Terminal, cd into the parent directory:
cd Path/To/MyDir
  1. Give execute permission to the script:
chmod +x ./convert.sh
  1. Run the script:
./convert.sh
  1. Check the newly created compressed folder inside each video directory for optimized files.

For example:

MyDir/
├── convert.sh
├── Videos/
│   ├── Video1.mov
│   ├── Video2.mov
│   └── compressed/
│       ├── Video1_1080p_H264_CRF-23.mp4
│       └── Video2_1080p_H264_CRF-23.mp4
└── MoreVideos/
    ├── Video3.mov
    ├── Video4.mov
    └── compressed/
        ├── Video3_1080p_H264_CRF-23.mp4
        └── Video4_1080p_H264_CRF-23.mp4

Notes

The script uses -n, which tells FFmpeg not to overwrite existing output files. This makes it safer to rerun the script on the same folder later.

If an output file already exists, FFmpeg will skip that file instead of replacing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment