Add video
This commit is contained in:
parent
589de0c5ac
commit
7c36cbfdd4
18 changed files with 2292 additions and 333 deletions
|
|
@ -19,10 +19,24 @@ set -euo pipefail
|
|||
APP_URL="${APP_URL:-http://host.docker.internal:3001}"
|
||||
PB_URL="${PB_URL:-http://host.docker.internal:8090}"
|
||||
API_URL="${API_URL:-http://host.docker.internal:8001}"
|
||||
PB_ADMIN_EMAIL="${PB_ADMIN_EMAIL:-admin@propertymap.local}"
|
||||
PB_ADMIN_PASSWORD="${PB_ADMIN_PASSWORD:-propertymap-dev-2024}"
|
||||
PB_EMAIL="${PB_EMAIL:-demo-video@local.test}"
|
||||
PB_PASSWORD="${PB_PASSWORD:-DemoVideoPass123!}"
|
||||
MAX_DURATION_S="${MAX_DURATION_S:-15}"
|
||||
RECORD_SCALE="${RECORD_SCALE:-2}" # 2x raw capture -> real 50fps after speed-up
|
||||
OUTPUT_FPS="${OUTPUT_FPS:-50}" # matches RECORD_SCALE=2 output cadence
|
||||
CAPTURE_SCALE="${CAPTURE_SCALE:-1.5}" # sharper than 1x without the 2x software-GL cost
|
||||
AUTH_TTL_HOURS="${AUTH_TTL_HOURS:-24}" # re-auth if auth.json older than this
|
||||
# Where the homepage <video> source lives. Vite copies frontend/public/* into
|
||||
# the built bundle, so updating this path is what makes the new clip appear
|
||||
# on the homepage. Override if the dashboard ever moves.
|
||||
PUBLISH_DIR="${PUBLISH_DIR:-../frontend/public/video}"
|
||||
# When in the *output* timeline (post-speedup) to grab the poster frame.
|
||||
# Right-pane inspection (~10s output) is the clearest paused-state preview:
|
||||
# Manchester map, filters applied, right pane populated, larger narration
|
||||
# caption visible.
|
||||
POSTER_TIME_S="${POSTER_TIME_S:-8}"
|
||||
|
||||
FRESH_AUTH="${FORCE_AUTH:-0}"
|
||||
DO_ENCODE=1
|
||||
|
|
@ -107,6 +121,7 @@ fi
|
|||
if [ "$need_auth" = "1" ]; then
|
||||
say "Minting fresh auth.json (user: $PB_EMAIL)"
|
||||
PB_URL="$PB_URL" PB_EMAIL="$PB_EMAIL" PB_PASSWORD="$PB_PASSWORD" \
|
||||
PB_ADMIN_EMAIL="$PB_ADMIN_EMAIL" PB_ADMIN_PASSWORD="$PB_ADMIN_PASSWORD" \
|
||||
APP_URL="$APP_URL" \
|
||||
node dist/auth.js
|
||||
else
|
||||
|
|
@ -119,7 +134,9 @@ mkdir -p output
|
|||
# Wipe last run's leaking artifacts so the rename step picks up *this* run.
|
||||
rm -f output/recording.webm output/recording.mp4 output/page@*.webm output/page@*.webm.untrimmed
|
||||
|
||||
APP_URL="$APP_URL" MAX_DURATION_S="$MAX_DURATION_S" node dist/record.js
|
||||
APP_URL="$APP_URL" MAX_DURATION_S="$MAX_DURATION_S" CAPTURE_SCALE="$CAPTURE_SCALE" \
|
||||
RECORD_SCALE="$RECORD_SCALE" OUTPUT_FPS="$OUTPUT_FPS" \
|
||||
node dist/record.js
|
||||
|
||||
if [ ! -s output/recording.webm ]; then
|
||||
fail "recording.webm missing or empty"
|
||||
|
|
@ -132,19 +149,54 @@ if [ "$DO_ENCODE" = "1" ]; then
|
|||
fi
|
||||
say "Encoding to MP4"
|
||||
ffmpeg -y -loglevel warning -i output/recording.webm \
|
||||
-c:v libx264 -pix_fmt yuv420p -crf 18 -movflags +faststart \
|
||||
-c:v libx264 -pix_fmt yuv420p -crf 14 -preset fast \
|
||||
-movflags +faststart \
|
||||
output/recording.mp4
|
||||
|
||||
# Poster: a single high-quality JPEG extracted from a representative
|
||||
# moment in the output timeline. Used as the homepage <video poster=...>,
|
||||
# which is what the visitor sees before pressing play.
|
||||
# - -ss AFTER -i = output-side seek, frame-accurate (input-side seek
|
||||
# would land on the nearest keyframe, drifting back up to ~2s).
|
||||
# - -update 1 tells ffmpeg the output is a single image, not a sequence.
|
||||
# - -q:v 2 = high JPEG quality (~95%); poster file is ~120KB at 1080p.
|
||||
say "Extracting poster frame at ${POSTER_TIME_S}s"
|
||||
ffmpeg -y -loglevel warning -i output/recording.mp4 -ss "$POSTER_TIME_S" \
|
||||
-frames:v 1 -update 1 -q:v 2 \
|
||||
output/poster.jpg
|
||||
fi
|
||||
|
||||
# -- publish to homepage ------------------------------------------------------
|
||||
# Only publish when we did the encode (otherwise we'd be copying a stale
|
||||
# mp4 next to a fresh webm). --no-encode skips this whole block.
|
||||
if [ "$DO_ENCODE" = "1" ]; then
|
||||
if [ ! -d "$PUBLISH_DIR" ]; then
|
||||
say "Creating $PUBLISH_DIR"
|
||||
mkdir -p "$PUBLISH_DIR"
|
||||
fi
|
||||
say "Publishing to $PUBLISH_DIR"
|
||||
cp output/recording.mp4 "$PUBLISH_DIR/recording.mp4"
|
||||
cp output/poster.jpg "$PUBLISH_DIR/poster.jpg"
|
||||
fi
|
||||
|
||||
# -- report -------------------------------------------------------------------
|
||||
say "Done"
|
||||
if command -v ffprobe >/dev/null 2>&1; then
|
||||
for f in output/recording.webm output/recording.mp4; do
|
||||
for f in output/recording.webm output/recording.mp4 output/poster.jpg \
|
||||
"$PUBLISH_DIR/recording.mp4" "$PUBLISH_DIR/poster.jpg"; do
|
||||
[ -f "$f" ] || continue
|
||||
dur=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")
|
||||
size=$(stat -c '%s' "$f" 2>/dev/null || stat -f '%z' "$f")
|
||||
printf ' %s %ss %s bytes\n' "$f" "$(printf '%.2f' "$dur")" "$size"
|
||||
case "$f" in
|
||||
*.mp4|*.webm)
|
||||
dur=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")
|
||||
printf ' %s %ss %s bytes\n' "$f" "$(printf '%.2f' "$dur")" "$size"
|
||||
;;
|
||||
*)
|
||||
printf ' %s %s bytes\n' "$f" "$size"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
ls -la output/recording.* 2>/dev/null || true
|
||||
ls -la output/recording.* output/poster.jpg \
|
||||
"$PUBLISH_DIR/recording.mp4" "$PUBLISH_DIR/poster.jpg" 2>/dev/null || true
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue