feat(tools): add a reproducible terminal capture harness
Records on a throwaway Xvfb display at fixed geometry, drives the session with xdotool, and quantises through a per-clip palette so the terminal's colours survive instead of dithering.
This commit is contained in:
3 files changed
+121
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 874 KiB |
Executable
+57
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/record-lib.sh"
|
||||
|
||||
GEOMETRY=${GEOMETRY:-1120x680}
|
||||
EXAMPLE="$ROOT/examples/raytracer"
|
||||
OUT="$ROOT/assets/kitty.gif"
|
||||
WORK=$(mktemp -d)
|
||||
|
||||
git -C "$ROOT" stash list >/dev/null 2>&1 || true
|
||||
cp -a "$EXAMPLE" "$WORK/raytracer"
|
||||
rm -rf "$WORK/raytracer/build"
|
||||
mkdir -p "$WORK/bin"
|
||||
ln -sf "$ROOT/meowc" "$WORK/bin/meowc"
|
||||
|
||||
start_xvfb "$GEOMETRY"
|
||||
|
||||
kitty \
|
||||
--config "$HOME/.config/kitty/kitty.conf" \
|
||||
-o remember_window_size=no \
|
||||
-o "initial_window_width=${GEOMETRY%x*}" \
|
||||
-o "initial_window_height=${GEOMETRY#*x}" \
|
||||
-o confirm_os_window_close=0 \
|
||||
--directory "$WORK/raytracer" \
|
||||
-- bash --noprofile --norc >/dev/null 2>&1 &
|
||||
KITTY_PID=$!
|
||||
sleep 3
|
||||
|
||||
xdotool search --sync --onlyvisible --class kitty windowactivate >/dev/null 2>&1 || true
|
||||
xdotool type --delay 10 -- 'export PS1="raytracer \$ " PATH='"$WORK"'/bin:$PATH; clear'
|
||||
xdotool key Return
|
||||
sleep 1
|
||||
|
||||
start_capture "$GEOMETRY" "$WORK/kitty.mkv"
|
||||
|
||||
send_line 'meowc build' 7
|
||||
send_line '# Nothing changed' 0.6
|
||||
send_line 'meowc build' 2.5
|
||||
send_line '# Every mtime moves, not one byte does' 0.6
|
||||
send_line 'touch src/*/*.c include/*.h' 0.8
|
||||
send_line 'meowc build' 2.5
|
||||
send_line '# Recolour a sphere in the scene description' 0.6
|
||||
send_line "sed -i 's/0.22 0.42/0.20 0.70/' scenes/studio.scene" 0.8
|
||||
send_line '# Codegen reruns, only what reads it rebuilds' 0.6
|
||||
send_line 'meowc build' 3.5
|
||||
send_line '# A comment only edit: recompiled, cascade stops' 0.6
|
||||
send_line "sed -i '1i // early cutoff' src/math/vec3.c" 0.8
|
||||
send_line 'meowc build' 3
|
||||
send_line 'meowc test' 5
|
||||
|
||||
sleep 2
|
||||
stop_capture
|
||||
kill "$KITTY_PID" 2>/dev/null || true
|
||||
|
||||
to_gif "$WORK/kitty.mkv" "$OUT" 11
|
||||
rm -rf "$WORK"
|
||||
echo "wrote $OUT"
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
FONT=${FONT:-JetBrainsMono Nerd Font Mono}
|
||||
FPS=${FPS:-12}
|
||||
|
||||
start_xvfb() {
|
||||
local geometry=$1
|
||||
for n in $(seq 90 120); do
|
||||
[ -e "/tmp/.X11-unix/X$n" ] && continue
|
||||
DISPLAY=":$n"
|
||||
Xvfb "$DISPLAY" -screen 0 "${geometry}x24" -nolisten tcp >/dev/null 2>&1 &
|
||||
XVFB_PID=$!
|
||||
export DISPLAY XVFB_PID
|
||||
for _ in $(seq 50); do
|
||||
xdotool getdisplaygeometry >/dev/null 2>&1 && return 0
|
||||
sleep 0.1
|
||||
done
|
||||
kill "$XVFB_PID" 2>/dev/null || true
|
||||
done
|
||||
echo "no free X display" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
start_capture() {
|
||||
local geometry=$1 out=$2
|
||||
ffmpeg -v error -y -f x11grab -draw_mouse 0 -framerate "$FPS" \
|
||||
-video_size "$geometry" -i "$DISPLAY" -codec:v libx264 -preset ultrafast \
|
||||
-qp 0 "$out" >/dev/null 2>&1 &
|
||||
FFMPEG_PID=$!
|
||||
export FFMPEG_PID
|
||||
sleep 1
|
||||
}
|
||||
|
||||
stop_capture() {
|
||||
kill -INT "$FFMPEG_PID" 2>/dev/null || true
|
||||
wait "$FFMPEG_PID" 2>/dev/null || true
|
||||
}
|
||||
|
||||
send_line() {
|
||||
local text=$1 pause=${2:-0.9}
|
||||
xdotool type --delay 42 -- "$text"
|
||||
sleep 0.35
|
||||
xdotool key Return
|
||||
sleep "$pause"
|
||||
}
|
||||
|
||||
to_gif() {
|
||||
local src=$1 out=$2 fps=${3:-11}
|
||||
local palette=${src%.mkv}.png
|
||||
ffmpeg -v error -y -i "$src" -vf "fps=$fps,palettegen=stats_mode=diff" "$palette"
|
||||
ffmpeg -v error -y -i "$src" -i "$palette" \
|
||||
-lavfi "fps=$fps[x];[x][1:v]paletteuse=dither=none:diff_mode=rectangle" \
|
||||
-loop 0 "$out"
|
||||
rm -f "$palette"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
kill "${FFMPEG_PID:-}" 2>/dev/null || true
|
||||
kill "${XVFB_PID:-}" 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
Reference in new issue
Block a user