馃敡 Where my dotfiles lives in harmony and peace, most of the time
at main 3.5 kB view raw
1#!/usr/bin/env bash 2set -euo pipefail 3 4# Whispr - Groq Whisper Transcription Script 5# Based on https://github.com/EmbeddedMhawar/groq-whisper-linux/blob/master/groq_whisper.sh 6 7API_KEY="${GROQ_API_KEY:-}" 8if [[ -z "$API_KEY" ]]; then 9 notify-send -u critical "Groq Error" "Missing GROQ_API_KEY" 10 exit 1 11fi 12 13STATE_DIR="${XDG_RUNTIME_DIR:-/tmp}/whisp" 14mkdir -p "$STATE_DIR" 15 16FILENAME="${STATE_DIR}/rec.flac" 17PIDFILE="${STATE_DIR}/rec.pid" 18REC_LOG="${STATE_DIR}/rec_error.log" 19CURL_LOG="${STATE_DIR}/curl_error.log" 20ERROR_LOG="${STATE_DIR}/error.log" 21 22if [ -f "$PIDFILE" ]; then 23 PID="$(<"$PIDFILE")" 24 if kill -0 "$PID" 2>/dev/null; then 25 notify-send -u low -t 1000 "Groq" "Finishing..." 26 sleep 1 27 kill -INT "$PID" 2>/dev/null || true 28 for _ in {1..50}; do 29 kill -0 "$PID" 2>/dev/null || break 30 sleep 0.1 31 done 32 fi 33 rm "$PIDFILE" 34 35 notify-send -u low -t 2000 "Groq" "Transcribing..." 36 37 if [[ ! -s "$FILENAME" ]]; then 38 { 39 echo "Error: recording file missing or empty: $FILENAME" 40 [[ -s "$REC_LOG" ]] && { echo; echo "--- rec stderr ---"; cat "$REC_LOG"; } 41 } >"$ERROR_LOG" 42 notify-send -u critical "Groq Error" "No audio captured. Check $ERROR_LOG" 43 exit 1 44 fi 45 46 MAX_RETRIES=3 47 RETRY_DELAY=1 48 HTTP_CODE="" 49 TEXT="" 50 51 : >"$CURL_LOG" 52 53 attempt=0 54 while (( attempt < MAX_RETRIES )); do 55 attempt=$((attempt + 1)) 56 CURL_BODY="$(mktemp -p "$STATE_DIR" whisp_curl_body.XXXXXX)" 57 set +e 58 HTTP_CODE="$(curl -sS -o "$CURL_BODY" -w "%{http_code}" "https://api.groq.com/openai/v1/audio/transcriptions" \ 59 -H "Authorization: Bearer $API_KEY" \ 60 -F "file=@$FILENAME" \ 61 -F "model=whisper-large-v3" \ 62 -F "response_format=text" \ 63 --connect-timeout 15 \ 64 --max-time 300 \ 65 2>>"$CURL_LOG")" 66 CURL_EXIT=$? 67 set -e 68 TEXT="$(<"$CURL_BODY")" 69 rm -f "$CURL_BODY" 70 71 if [[ $CURL_EXIT -ne 0 ]]; then 72 HTTP_CODE="000" 73 fi 74 75 if [[ "$HTTP_CODE" == "200" ]]; then 76 break 77 fi 78 79 # Retry on transient errors 80 if [[ "$HTTP_CODE" =~ ^(400|429|500|502|503|504)$ ]] && [[ $attempt -lt $MAX_RETRIES ]]; then 81 notify-send -u low -t 1500 "Groq" "Retrying... (attempt $((attempt+1))/$MAX_RETRIES)" 82 sleep $RETRY_DELAY 83 RETRY_DELAY=$((RETRY_DELAY * 2)) 84 else 85 break 86 fi 87 done 88 89 if [[ "$HTTP_CODE" != "200" ]]; then 90 { 91 echo "Error (HTTP $HTTP_CODE) after $attempt attempts:" 92 [[ -n "${TEXT:-}" ]] && echo "$TEXT" 93 [[ -s "$CURL_LOG" ]] && { echo; echo "--- curl stderr (tail) ---"; tail -n 50 "$CURL_LOG"; } 94 } >"$ERROR_LOG" 95 notify-send -u critical "Groq Error" "Failed (Code $HTTP_CODE). Check $ERROR_LOG" 96 exit 1 97 else 98 printf %s "$TEXT" | wl-copy 99 notify-send -u low -t 2000 "Groq" "Transcription Done!" 100 fi 101 102else 103 : >"$REC_LOG" 104 rec -q -r 16000 -c 1 -b 16 "$FILENAME" 2>"$REC_LOG" & 105 PID=$! 106 echo "$PID" > "$PIDFILE" 107 108 sleep 0.1 109 if ! kill -0 "$PID" 2>/dev/null; then 110 rm -f "$PIDFILE" 111 notify-send -u critical "Groq Error" "Recording failed. Check $REC_LOG" 112 exit 1 113 fi 114 115 notify-send -u low -t 1000 "Groq" "Listening... (press again to finish)" 116fi