Files
hermes-agent/tests/install/e2e-assets/record-stop.sh
T
ethernet cdaf0cf091 ci(install-e2e): one screen-recording mechanism on every runner, Xvfb for headless linux
The composite action .github/actions/e2e-screen-record owns setup and
lifecycle on all three OSes: ffmpeg via apt/brew-verify/winget+cache,
capture via x11grab/gdigrab/avfoundation, mkv at 15fps stopped by 'q'
on live stdin with kill fallback. Linux runners have no display, so
start brings up a dedicated Xvfb :99 and exports DISPLAY - one display
serves both the recorder and any app a later step launches.

Recording moves out of the GUI driver into workflow infrastructure -
that is what makes it uniform - and a missing ffmpeg or a zero-frame
file now FAILS the leg instead of skipping silently: the graceful-skip
path is how the windows leg shipped no recording.mkv while green.

Lifecycle proven locally: start against lavfi testsrc, q-stop, ffprobe
duration check (record-start.sh/record-stop.sh under nix ffmpeg).
2026-08-12 04:15:24 -04:00

50 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Stop a recording started by record-start.sh and verify the file is real.
#
# Usage: record-stop.sh OUTPUT.mkv
#
# Graceful stop: the character 'q' on ffmpeg's live stdin (the control
# fifo). Falls back to SIGINT (also a clean finalize for ffmpeg), then
# SIGKILL. Fails if the output is missing or has no decodable duration -
# a zero-frame recording is the classic silent failure.
set -euo pipefail
OUT="${1:?usage: record-stop.sh OUTPUT.mkv}"
STATE="$OUT.state"
[ -f "$STATE" ] || { echo "record-stop: no state at $STATE (was record-start run?)" >&2; exit 1; }
read -r FFMPEG_PID FIFO _SHEPHERD < "$STATE"
if kill -0 "$FFMPEG_PID" 2>/dev/null; then
# Write the quit key; don't hang if the reader is already gone.
{ printf 'q' > "$FIFO"; } 2>/dev/null &
WRITER=$!
for _ in $(seq 1 50); do
kill -0 "$FFMPEG_PID" 2>/dev/null || break
sleep 0.2
done
kill "$WRITER" 2>/dev/null || true
if kill -0 "$FFMPEG_PID" 2>/dev/null; then
echo "record-stop: q did not stop ffmpeg; SIGINT" >&2
kill -INT "$FFMPEG_PID" 2>/dev/null || true
for _ in $(seq 1 25); do
kill -0 "$FFMPEG_PID" 2>/dev/null || break
sleep 0.2
done
kill -9 "$FFMPEG_PID" 2>/dev/null || true
fi
fi
rm -f "$FIFO" "$STATE"
[ -s "$OUT" ] || { echo "record-stop: $OUT missing or empty" >&2; exit 1; }
if command -v ffprobe >/dev/null 2>&1; then
dur="$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$OUT" || echo 0)"
case "$dur" in
''|0|0.*) echo "record-stop: $OUT has no duration (zero-frame recording)" >&2; exit 1 ;;
esac
echo "record-stop: $OUT finalized (${dur}s)"
else
echo "record-stop: $OUT finalized (ffprobe absent; size $(wc -c < "$OUT") bytes)"
fi