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.
54 lines
2.1 KiB
Bash
Executable file
54 lines
2.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Live progress bar for transcribe.py.
|
|
# Run this in any terminal while transcribe.py is running:
|
|
# bash watch_progress.sh
|
|
# Renders a unicode bar that updates in place via \r.
|
|
set -u
|
|
cd "$(dirname "$0")"
|
|
|
|
LOG="transcribe.log"
|
|
WIDTH=40
|
|
STAGE="init"
|
|
PCT=0
|
|
|
|
bar() {
|
|
local pct=$1 stage=$2 extra=${3:-}
|
|
local fill=$(( pct * WIDTH / 100 ))
|
|
local empty=$(( WIDTH - fill ))
|
|
local line
|
|
line=$(printf "[%-7s] [%s%s] %3d%% %s" \
|
|
"$stage" \
|
|
"$(printf '█%.0s' $(seq 1 $fill 2>/dev/null))" \
|
|
"$(printf '░%.0s' $(seq 1 $empty 2>/dev/null))" \
|
|
"$pct" "$extra")
|
|
printf "\r\033[K%s" "$line"
|
|
}
|
|
|
|
# Wait for the log to appear.
|
|
while [ ! -f "$LOG" ]; do sleep 0.5; done
|
|
bar 0 init "waiting for ffmpeg…"
|
|
|
|
# Stream new log lines as they're written.
|
|
tail -n +1 -F "$LOG" 2>/dev/null | while IFS= read -r line; do
|
|
case "$line" in
|
|
*"[1/5] loading audio"*) STAGE="audio"; PCT=2; bar "$PCT" "$STAGE" "loading audio" ;;
|
|
*"[2/5] transcribing"*) STAGE="VAD"; PCT=5; bar "$PCT" "$STAGE" "voice activity detection" ;;
|
|
*"Progress:"*"%"*)
|
|
n=$(printf '%s\n' "$line" | sed -n 's/.*Progress:\s*\([0-9.]*\)%.*/\1/p')
|
|
if [ -n "$n" ]; then
|
|
PCT=${n%.*}
|
|
case "$STAGE" in
|
|
ASR) bar "$PCT" "$STAGE" "Whisper ASR" ;;
|
|
align) bar "$PCT" "$STAGE" "wav2vec2 word alignment" ;;
|
|
diarize) bar "$PCT" "$STAGE" "pyannote community-1" ;;
|
|
*) STAGE="ASR"; bar "$PCT" "$STAGE" "Whisper ASR" ;;
|
|
esac
|
|
fi
|
|
;;
|
|
*"[3/5] aligning"*) STAGE="align"; PCT=0; bar "$PCT" "$STAGE" "wav2vec2 word alignment"; printf "\n" ;;
|
|
*"[4/5] diarizing"*) STAGE="diarize"; PCT=0; bar "$PCT" "$STAGE" "pyannote community-1"; printf "\n" ;;
|
|
*"[5/5] assigning"*) STAGE="render"; PCT=95; bar "$PCT" "$STAGE" "merging speaker turns" ;;
|
|
"OK:"*) PCT=100; bar "$PCT" "done" "$line"; printf "\n"; break ;;
|
|
"ERROR:"*|*"Traceback"*|*"FAIL"*) printf "\n%s\n" "$line"; break ;;
|
|
esac
|
|
done
|