131 lines
5.9 KiB
Bash
Executable file
131 lines
5.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Regenerate the website capture assets: search.webm, manage-indexing.webm,
|
|
# duplicates.png, query-highlight.png — all landing in packaging/captures/
|
|
# (gitignored). Needs a graphical session (X11 or Wayland — screenshots and
|
|
# video frames are read back from the app's own framebuffer, so the display
|
|
# server does not matter) and ffmpeg with libx264rgb and libvpx-vp9.
|
|
#
|
|
# The app is built with the `capture` feature and drives itself through
|
|
# packaging/capture-scenario.txt (see crates/quicksearch-gui/src/capture.rs
|
|
# for the command grammar). It runs against a throwaway index of this
|
|
# repository plus ~/.cargo/registry/src, under scratch XDG dirs — the real
|
|
# ~/.config/quicksearch and index are never touched.
|
|
#
|
|
# The scratch dirs live OUTSIDE both index roots on purpose: the demo config
|
|
# has an empty ignore list, so a scratch index database inside an indexed
|
|
# tree would be indexed and watched by the very run that writes it.
|
|
set -euo pipefail
|
|
|
|
here="$(cd "$(dirname "$0")" && pwd)"
|
|
repo="$(dirname "$here")"
|
|
out="$here/captures"
|
|
work="${TMPDIR:-/tmp}/quicksearch-capture"
|
|
|
|
# --- preflight --------------------------------------------------------------
|
|
if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then
|
|
echo "capture needs a graphical session (neither DISPLAY nor" \
|
|
"WAYLAND_DISPLAY is set)" >&2
|
|
exit 1
|
|
fi
|
|
for tool in ffmpeg ffprobe cargo; do
|
|
command -v "$tool" >/dev/null || { echo "missing tool: $tool" >&2; exit 1; }
|
|
done
|
|
# The encoder list is captured first: `grep -q` closing the pipe early would
|
|
# make ffmpeg exit on SIGPIPE, which pipefail reports as failure.
|
|
encoders="$(ffmpeg -hide_banner -encoders 2>/dev/null)"
|
|
for enc in libx264rgb libvpx-vp9; do
|
|
grep -q "$enc" <<< "$encoders" \
|
|
|| { echo "ffmpeg lacks the $enc encoder" >&2; exit 1; }
|
|
done
|
|
# A config.toml beside the binary would silently override the scratch XDG
|
|
# config entirely (portable mode) — refuse to run with one present.
|
|
if [ -e "$repo/target/release/config.toml" ]; then
|
|
echo "remove $repo/target/release/config.toml first: portable mode would" \
|
|
"override the capture config" >&2
|
|
exit 1
|
|
fi
|
|
registry="$HOME/.cargo/registry/src"
|
|
[ -d "$registry" ] || { echo "missing demo index root: $registry" >&2; exit 1; }
|
|
|
|
# --- build + parser tests ---------------------------------------------------
|
|
cargo test --manifest-path "$repo/Cargo.toml" --release --locked \
|
|
-p quicksearch-gui --features capture capture::
|
|
cargo build --manifest-path "$repo/Cargo.toml" --release --locked \
|
|
-p quicksearch-gui --features capture
|
|
|
|
# --- scratch environment ----------------------------------------------------
|
|
# Fresh every run: no stale index, no schema-mismatch prompt, and a fresh
|
|
# app.ron so the window opens at its default 1000x700 geometry.
|
|
rm -rf "$work"
|
|
mkdir -p "$work/config/quicksearch" "$work/data" "$work/tmp" "$out"
|
|
cat > "$work/config/quicksearch/config.toml" <<EOF
|
|
# Generated by packaging/capture.sh — the demo config for capture runs.
|
|
[paths]
|
|
indexing_paths = ["$repo", "$registry"]
|
|
|
|
[indexing]
|
|
auto_index = true
|
|
include_hidden = true
|
|
ignore_patterns = []
|
|
|
|
# 1.5x zoom + proportionally larger windows (set in the scenario) render the
|
|
# same layout at ~1.5x the pixel density, for crisper website assets.
|
|
[ui]
|
|
scale = 1.25
|
|
EOF
|
|
|
|
# --- run the scripted app ---------------------------------------------------
|
|
# The outer timeout catches a wedged run; the driver's own hard timeouts
|
|
# should fire well before it.
|
|
echo "Running the capture scenario (the initial index build takes minutes)..."
|
|
env XDG_CONFIG_HOME="$work/config" \
|
|
XDG_DATA_HOME="$work/data" \
|
|
QS_CAPTURE_SCRIPT="$here/capture-scenario.txt" \
|
|
QS_CAPTURE_OUT="$work/tmp" \
|
|
timeout 2400 "$repo/target/release/quicksearch" \
|
|
|| { code=$?; echo "capture run failed (exit $code; 2=script parse," \
|
|
"3=wait timeout, 4=io/ffmpeg, 124=hung)" >&2; exit 1; }
|
|
|
|
# --- transcode the lossless intermediates to VP9 webm -----------------------
|
|
# The recording itself is lossless, so webm quality is decided entirely here.
|
|
# QS_WEBM_CRF is the knob: constant-quality factor, 0 (best) to 63; UI text
|
|
# stays crisp around 24-32, and each step of ~6 roughly halves/doubles the
|
|
# file size. QS_WEBM_CPU trades encode time for compression efficiency
|
|
# (0 slowest/best to 5 fastest).
|
|
crf="${QS_WEBM_CRF:-26}"
|
|
cpu="${QS_WEBM_CPU:-0}"
|
|
for clip in manage-indexing search; do
|
|
[ -s "$work/tmp/$clip.cap.mkv" ] \
|
|
|| { echo "missing recording: $clip.cap.mkv" >&2; exit 1; }
|
|
# The crop drops at most one row/column: yuv420p needs even dimensions,
|
|
# and fractional display scaling can make the window an odd size.
|
|
ffmpeg -y -hide_banner -loglevel warning -i "$work/tmp/$clip.cap.mkv" \
|
|
-vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" \
|
|
-c:v libvpx-vp9 -b:v 0 -crf "$crf" -deadline good -cpu-used "$cpu" \
|
|
-row-mt 1 -pix_fmt yuv420p -an "$out/$clip.webm"
|
|
done
|
|
mv "$work/tmp/query-highlight.png" "$work/tmp/duplicates.png" "$out/"
|
|
|
|
# --- verify -----------------------------------------------------------------
|
|
fail=0
|
|
for f in "$out/search.webm" "$out/manage-indexing.webm"; do
|
|
codec=$(ffprobe -v error -select_streams v:0 \
|
|
-show_entries stream=codec_name -of csv=p=0 "$f")
|
|
dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$f")
|
|
[ "$codec" = vp9 ] || { echo "FAIL: $f codec=$codec" >&2; fail=1; }
|
|
awk -v d="$dur" 'BEGIN{exit !(d>=4 && d<=60)}' \
|
|
|| { echo "FAIL: $f duration=${dur}s (expected 4-60s)" >&2; fail=1; }
|
|
echo "OK: $f (vp9, ${dur}s)"
|
|
done
|
|
for f in "$out/duplicates.png" "$out/query-highlight.png"; do
|
|
dims=$(ffprobe -v error -select_streams v:0 \
|
|
-show_entries stream=width,height -of csv=p=0 "$f")
|
|
echo "OK: $f (${dims})"
|
|
done
|
|
[ "$fail" -eq 0 ]
|
|
|
|
# $work is kept for post-mortems (app stderr is on this terminal; the scratch
|
|
# index and raw .cap.mkv files live there) and recreated fresh next run.
|
|
echo
|
|
echo "Assets:"
|
|
ls -l "$out"/*.webm "$out"/*.png
|