Prd/resources/whisper/smoke_test.sh
Lucy Doupalů be9f14ce34 Helpdesk - operator console + patched GrapheneOS Dialer for call handling
A small helpdesk system: an office Pixel running a patched GrapheneOS Dialer
answers technician calls, records both call legs as separate channels, and a
Ruby backend transcribes them through Whisper and files an AI summary against
the caller.

Squashed to a single commit for sharing. No credentials are included; secrets
live outside the repo in /etc/helpdesk/env on the server or a gitignored
.claude/env.local locally. See .claude/env.local.example for the shape.

Start at README.md, then docs/architecture.md.
2026-07-27 18:50:32 +02:00

97 lines
2.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# smoke_test.sh — End-to-end pipeline smoke test.
#
# Synthesizes a 2-speaker Czech dialogue with espeak-ng (no real audio
# needed), runs it through transcribe.py, and asserts the output contains
# both speaker tags. The transcription itself will be robotic-TTS nonsense;
# this test only verifies that the ffmpeg → ASR → align → diarize → assign
# → render pipeline executes end-to-end without errors.
set -euo pipefail
cd "$(dirname "$0")"
if ! command -v espeak-ng >/dev/null; then
echo "ERROR: espeak-ng not installed."
echo " sudo apt install espeak-ng (Debian/Ubuntu)"
echo " brew install espeak-ng (macOS)"
exit 2
fi
if ! command -v ffmpeg >/dev/null; then
echo "ERROR: ffmpeg not installed."
exit 2
fi
if [ -z "${HF_TOKEN:-}" ]; then
echo "ERROR: HF_TOKEN not set in the environment."
echo " Create a token at https://huggingface.co/settings/tokens"
echo " Accept terms on:"
echo " https://huggingface.co/pyannote/speaker-diarization-community-1"
echo " https://huggingface.co/pyannote/segmentation-3.0"
echo " Then: export HF_TOKEN=hf_..."
exit 2
fi
TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT
# Two Czech utterances at distinct pitches to fake two speakers.
espeak-ng -v cs -p 25 -s 150 \
"Dobrý den, jak se dnes máte? Doufám, že dobře." \
-w "$TMPDIR/a.wav"
espeak-ng -v cs -p 75 -s 145 \
"Děkuji, mám se výborně. A vy? Co je dnes nového?" \
-w "$TMPDIR/b.wav"
espeak-ng -v cs -p 25 -s 150 \
"Mám hodně práce, ale nestěžuji si. Pracujeme na zajímavém projektu." \
-w "$TMPDIR/c.wav"
espeak-ng -v cs -p 75 -s 145 \
"To je skvělé. Přeji vám hodně úspěchů." \
-w "$TMPDIR/d.wav"
# 0.4 s silence between turns.
ffmpeg -hide_banner -loglevel error -y \
-f lavfi -i anullsrc=r=22050:cl=mono -t 0.4 \
-ac 1 "$TMPDIR/sil.wav"
# Concat list.
{
echo "file '$TMPDIR/a.wav'"
echo "file '$TMPDIR/sil.wav'"
echo "file '$TMPDIR/b.wav'"
echo "file '$TMPDIR/sil.wav'"
echo "file '$TMPDIR/c.wav'"
echo "file '$TMPDIR/sil.wav'"
echo "file '$TMPDIR/d.wav'"
} > "$TMPDIR/concat.txt"
ffmpeg -hide_banner -loglevel error -y \
-f concat -safe 0 -i "$TMPDIR/concat.txt" \
-ar 16000 -ac 1 "$TMPDIR/smoke.wav"
OUT="$TMPDIR/smoke.txt"
echo ">>> running transcribe.py on synthesized 4-utterance dialogue…"
python transcribe.py "$TMPDIR/smoke.wav" -o "$OUT" \
--min-speakers 2 --max-speakers 2
if [ ! -s "$OUT" ]; then
echo "FAIL: $OUT is empty."
exit 1
fi
echo
echo "=== output ==="
cat "$OUT"
echo "=============="
echo
if grep -q "\[Speaker 1\]:" "$OUT" && grep -q "\[Speaker 2\]:" "$OUT"; then
echo "PASS: both [Speaker 1] and [Speaker 2] tags present."
exit 0
else
echo "FAIL: output missing one or both speaker tags."
echo " Pipeline ran end-to-end but diarization may have collapsed"
echo " the two TTS voices into one speaker (espeak-ng voices are"
echo " acoustically similar). Try with a real recording."
exit 1
fi