Files
server-configs/httpserver/data/mew-neocities/library/mp4-to-gif.sh
2026-03-22 00:54:28 -07:00

88 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Convert Mew timeline MP4 clips into small, optimized GIFs for Neocities.
# Requires: ffmpeg, gifsicle
#
# Strategy:
# - Trim to the first few seconds
# - Sample only a few frames per second
# - Scale down to a small width
# - Use a global palette + heavy optimization
# - Aim to keep each GIF under ~5MB
#
# Usage (from this directory):
# chmod +x mp4-to-gif.sh
# ./mp4-to-gif.sh /path/to/source/mp4s
set -euo pipefail
SRC_DIR="${1:-.}"
OUT_DIR="${OUT_DIR:-.}"
# Tunables for size/quality tradeoff
FPS="${FPS:-3}" # frames per second sampled
WIDTH="${WIDTH:-360}" # output width in pixels
MAX_SECONDS="${MAX_SECONDS:-8}" # cap duration
if ! command -v ffmpeg &>/dev/null; then
echo "Error: ffmpeg not found. Install it first." >&2
exit 1
fi
if ! command -v gifsicle &>/dev/null; then
echo "Warning: gifsicle not found. Skipping extra optimization (GIFs may be larger)." >&2
fi
convert_one () {
local name="$1" # e.g. 2016-12-17_22-42-58
local in="$SRC_DIR/${name}.mp4"
# Unique temp files to avoid name clashes if run multiple times
local pal
pal="$(mktemp "${OUT_DIR}/${name}-palette-XXXX.png")"
local out_tmp
out_tmp="$(mktemp "${OUT_DIR}/${name}-tmp-XXXX.gif")"
local out_final="${OUT_DIR}/${name}.gif"
if [[ ! -f "$in" ]]; then
echo "Skip (missing): $in"
return
fi
echo "Processing $in -> $out_final"
# 1) Generate palette from trimmed, sparsely sampled, scaled frames
ffmpeg -y -t "$MAX_SECONDS" -i "$in" \
-vf "fps=${FPS},scale=${WIDTH}:-1:flags=lanczos,palettegen=stats_mode=single:max_colors=48" \
-frames:v 1 \
"$pal"
# 2) Apply palette to create GIF
ffmpeg -y -t "$MAX_SECONDS" -i "$in" -i "$pal" \
-lavfi "fps=${FPS},scale=${WIDTH}:-1:flags=lanczos [x]; [x][1:v] paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle" \
-loop 0 \
"$out_tmp"
# 3) Extra optimization with gifsicle, if available
if command -v gifsicle &>/dev/null; then
gifsicle -O3 --lossy=40 "$out_tmp" -o "$out_final"
rm -f "$out_tmp"
else
mv "$out_tmp" "$out_final"
fi
rm -f "$pal"
# 4) Print size
if command -v du &>/dev/null; then
echo -n "Final size: "
du -h "$out_final" | cut -f1
fi
}
convert_one "2016-12-17_22-42-58"
convert_one "2017-04-01_00-14-00"
convert_one "2018-06-19_06-20-25"
echo "Done. Upload the generated *.gif files to the 'library' folder on Neocities and ensure index.html references the .gif versions."