How to Automate Image and Video Compression on Ubuntu 24.04 with ImageMagick and FFmpeg
On this page
Large images and videos are the most common reason pages load slowly. This guide builds one Bash script that converts images to WebP, re-encodes videos for streaming and optionally uploads results to an Amazon S3 bucket with long-lived cache headers.
Prerequisites
- Ubuntu 24.04 with
sudoaccess - Source files in
/srv/uploads - Optional: AWS CLI v2 configured for a bucket you own, with an IAM policy limited to that bucket
Step-by-Step Guide
Step 1: Install the tools
sudo apt update sudo apt install -y ffmpeg imagemagick webp ffmpeg -version | head -n 1
Step 2: Write the optimization script
Save as optimize.sh. Files already converted are skipped, so reruns are fast.
#!/usr/bin/env bash
set -euo pipefail
SRC="${1:?Usage: optimize.sh SOURCE_DIR OUTPUT_DIR}"
OUT="${2:?Usage: optimize.sh SOURCE_DIR OUTPUT_DIR}"
mkdir -p "$OUT"
find "$SRC" -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) -print0 |
while IFS= read -r -d '' f; do
name="$(basename "${f%.*}")"
[ -f "$OUT/$name.webp" ] && continue
convert "$f" -auto-orient -strip -resize '1600x>' -quality 80 "$OUT/$name.webp"
done
find "$SRC" -type f \( -iname '*.mp4' -o -iname '*.mov' \) -print0 |
while IFS= read -r -d '' f; do
name="$(basename "${f%.*}")"
[ -f "$OUT/$name.mp4" ] && continue
ffmpeg -nostdin -loglevel error -i "$f" \
-c:v libx264 -crf 23 -preset medium -vf "scale='min(1280,iw)':-2" \
-c:a aac -b:a 128k -movflags +faststart "$OUT/$name.mp4"
done
echo "Optimization finished."
Step 3: Run it and compare sizes
chmod 750 optimize.sh ./optimize.sh /srv/uploads /srv/optimized du -sh /srv/uploads /srv/optimized
Step 4: Upload to S3 with cache headers (optional)
aws s3 sync /srv/optimized s3://your-bucket-name/media/ \ --cache-control "public, max-age=31536000, immutable"
Replace your-bucket-name with your bucket. The one-year immutable header is only safe if a changed file always gets a new name, for example hero-v2.webp.
Step 5: Schedule it
Add this line with crontab -e to run nightly at 02:00:
0 2 * * * /home/ubuntu/optimize.sh /srv/uploads /srv/optimized >> /tmp/optimize.log 2>&1
Adjust the script path to match your user's home directory.
Conclusion
Media is now compressed consistently and ready for a CDN. Keep original files, review the log weekly, keep names unique, and test visual quality on a few samples before bulk conversion.