← back to Beverlyhillsvideos

filmgen/store_card.sh

29 lines

#!/bin/zsh
# store_card.sh — render + animate + narrate one store card locally ($0).
#   filmgen/store_card.sh "<Store Name>" "<tagline>" "<narration>" <out-slug>
# Produces public/video/store/<slug>.mp4 (1080x1920). No paid APIs.
set -e
cd "$(dirname "$0")/.."
NAME="$1"; TAGLINE="$2"; NARR="$3"; SLUG="$4"
VOICE="${STORE_VOICE:-Samantha}"          # swap to a Premium/cloned voice later
OUTDIR="public/video/store"; mkdir -p "$OUTDIR" filmgen/work
PNG="filmgen/work/${SLUG}-card.png"
AIFF="filmgen/work/${SLUG}-narr.aiff"
MP4="${OUTDIR}/${SLUG}.mp4"

python3 filmgen/store_card.py "$NAME" "$TAGLINE" "$PNG"

# narration → aac; measure its length so the film matches the voiceover (+1.4s tail)
say -v "$VOICE" -o "$AIFF" "$NARR"
NDUR=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$AIFF")
DUR=$(python3 -c "print(max(8.0, float('$NDUR')+1.4))")
FR=$(python3 -c "print(int($DUR*30))")
END=$(python3 -c "print(round($DUR-0.6,2))")

# slow Ken Burns zoom on the still + fade in/out, mux narration under it
ffmpeg -y -loop 1 -i "$PNG" -i "$AIFF" \
  -filter_complex "[0:v]scale=1350:2400,zoompan=z='min(zoom+0.00035,1.10)':d=${FR}:s=1080x1920:fps=30,fade=in:0:12,fade=out:st=${END}:d=0.6,format=yuv420p[v]" \
  -map "[v]" -map 1:a -c:v libx264 -preset medium -crf 20 -c:a aac -b:a 128k \
  -t "$DUR" -movflags +faststart "$MP4" 2>/dev/null
echo "wrote $MP4  (${DUR}s, voice=${VOICE})"