#!/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."