Files
mediaplayer/whisper/verify.sh
2026-08-16 15:52:40 +08:00

119 lines
3.7 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#
# 验证 Whisper 转写服务:
# 1. 检查 GPU 与容器运行状态
# 2. 用测试音频发起 verbose_json 转写请求,校验响应契约
# 3. (可选)检查 oral-trainer-api 的集成状态
#
# 用法:
# ./verify.sh
# ./verify.sh --file /path/to/speech.wav
# ./verify.sh --url http://127.0.0.1:9000 --model Systran/faster-whisper-large-v3
# ./verify.sh --api-url http://127.0.0.1:8000
set -euo pipefail
WHISPER_URL="${WHISPER_URL:-http://127.0.0.1:9000}"
WHISPER_MODEL="${WHISPER_MODEL:-Systran/faster-whisper-large-v3}"
TEST_FILE=""
API_URL=""
usage() {
sed -n '2,9p' "$0" | sed 's/^# \{0,1\}//'
}
while [[ $# -gt 0 ]]; do
case "$1" in
--url) WHISPER_URL="$2"; shift 2 ;;
--model) WHISPER_MODEL="$2"; shift 2 ;;
--file) TEST_FILE="$2"; shift 2 ;;
--api-url) API_URL="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) echo "未知参数: $1"; usage; exit 1 ;;
esac
done
echo "==> Whisper 地址: $WHISPER_URL"
echo "==> 模型: $WHISPER_MODEL"
echo "==> 检查 GPU"
if command -v nvidia-smi >/dev/null 2>&1; then
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader | head -5
else
echo "警告: 未找到 nvidia-smi请确认 NVIDIA 驱动与容器运行时已安装(容器需要 --gpus 支持)。"
fi
echo "==> 检查容器状态"
if command -v docker >/dev/null 2>&1 && [[ -f docker-compose.yml ]]; then
docker compose ps --status running | sed -n '1,3p'
else
echo "警告: 未在当前目录发现 docker-compose.yml跳过容器状态检查。"
fi
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
if [[ -n "$TEST_FILE" ]]; then
AUDIO_FILE="$TEST_FILE"
else
echo "==> 生成测试音频3 秒 440Hz 正弦波)"
if ! command -v ffmpeg >/dev/null 2>&1; then
echo "错误: 未找到 ffmpeg请安装或用 --file 指定真实语音文件。" >&2
exit 1
fi
AUDIO_FILE="$TMP_DIR/tone.wav"
ffmpeg -hide_banner -loglevel error -f lavfi \
-i "sine=frequency=440:duration=3" -ar 16000 -ac 1 -y "$AUDIO_FILE"
fi
if [[ ! -f "$AUDIO_FILE" ]]; then
echo "错误: 音频文件不存在: $AUDIO_FILE" >&2
exit 1
fi
echo "==> 发起转写请求verbose_json"
START_TS="$(date +%s)"
RESPONSE="$(curl -sS --max-time 300 \
-X POST "$WHISPER_URL/v1/audio/transcriptions" \
-F "model=$WHISPER_MODEL" \
-F "file=@$AUDIO_FILE" \
-F "response_format=verbose_json" \
-F "temperature=0")"
ELAPSED="$(( $(date +%s) - START_TS ))"
echo "$RESPONSE" | python3 -c '
import json, sys
payload = json.load(sys.stdin)
text = payload.get("text")
segments = payload.get("segments")
assert isinstance(text, str), "响应缺少 text 字段"
assert isinstance(segments, list), "响应缺少 segments 字段(需要 verbose_json"
for index, segment in enumerate(segments):
start = segment.get("start")
end = segment.get("end")
if not (isinstance(start, (int, float)) and isinstance(end, (int, float)) and end > start >= 0):
raise AssertionError(f"segments[{index}] 缺少合法 start/end")
print(f"OK: text={text!r}")
print(f"OK: segments={len(segments)} 条")
'
echo "==> 转写耗时: ${ELAPSED}s"
if [[ -n "$API_URL" ]]; then
echo "==> 检查 API 集成 ($API_URL/healthz)"
curl -sS --max-time 15 "$API_URL/healthz" | python3 -c '
import json, sys
payload = json.load(sys.stdin)
configured = payload.get("moss_configured")
if configured is not True:
raise SystemExit(f"错误: moss_configured={configured!r},请检查 .env 中的 MOSS_TRANSCRIBE_URL")
print("OK: moss_configured=true")
'
fi
echo "全部检查通过。建议再用真实语音文件复核转写质量:"
echo " $0 --file /path/to/speech.wav"