diff --git a/CHANGELOG.md b/CHANGELOG.md index 652d0f2..f288fb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Windows `ASR HTTP` 现在在 `auto` 模式下仍会优先尝试 `cuda + int8_float16`,但如果在真正推理阶段命中 `cublas/cudnn/cuda` 运行库缺失,会自动切回 `cpu + int8` 重试,不再把整次转写卡死在 GPU 路径。 - 这让“默认优先用 GPU、但当前机器 CUDA 运行库不完整”的场景也能稳定返回结果,同时保留混合中英文自动识别。 +- `smoke_public_storyforge.sh` 与 `smoke_fnos_storyforge_lan.sh` 现在会覆盖 ASR 转写链路,公网 smoke 在遇到 `127.0.0.1` 这类服务器内网地址时会自动跳过真实转写,避免在开发机上误判。 ### Windows ASR 默认改成 GPU 优先与自动语言识别 diff --git a/scripts/smoke_fnos_storyforge_lan.sh b/scripts/smoke_fnos_storyforge_lan.sh index 0344992..a3e8ea7 100755 --- a/scripts/smoke_fnos_storyforge_lan.sh +++ b/scripts/smoke_fnos_storyforge_lan.sh @@ -43,6 +43,9 @@ compat_file="$tmp_dir/compat.html" live_recorder_health_file="$tmp_dir/live-recorder-health.json" token_file="$tmp_dir/token.txt" project_id_file="$tmp_dir/project-id.txt" +asr_url_file="$tmp_dir/asr-url.txt" +asr_wav="$tmp_dir/asr.wav" +asr_result="$tmp_dir/asr.json" echo "[1/7] check fnOS web" curl_fetch "$WEB_URL/" >"$index_file" @@ -69,10 +72,47 @@ if lan_routing.get("cutvideoBaseUrl") != expected_cutvideo: raise SystemExit(f"unexpected cutvideoBaseUrl: {lan_routing.get('cutvideoBaseUrl')!r}") if lan_routing.get("cutvideoRouteMode") != "fnos_tunnel": raise SystemExit(f"unexpected cutvideoRouteMode: {lan_routing.get('cutvideoRouteMode')!r}") +asr_url = str(payload.get("asrHttpBaseUrl") or "").strip() +pathlib.Path(sys.argv[3]).write_text(asr_url, encoding="utf-8") print("healthz ok") -' "$health_file" "$CUTVIDEO_URL" +' "$health_file" "$CUTVIDEO_URL" "$asr_url_file" -echo "[4/7] check auto-session" +echo "[4/8] check ASR transcribe" +python3 - "$asr_wav" <<'PY' +import math +import struct +import sys +import wave + +path = sys.argv[1] +sample_rate = 16000 +duration = 0.25 +freq = 440.0 +samples = int(sample_rate * duration) +with wave.open(path, "wb") as handle: + handle.setnchannels(1) + handle.setsampwidth(2) + handle.setframerate(sample_rate) + for i in range(samples): + value = int(16000 * math.sin(2 * math.pi * freq * (i / sample_rate))) + handle.writeframes(struct.pack(""$asr_result" +python3 - "$asr_result" <<'PY' +import json +import pathlib +import sys + +payload = json.loads(pathlib.Path(sys.argv[1]).read_text()) +if "duration_ms" not in payload: + raise SystemExit("missing duration_ms") +if "success" not in payload: + raise SystemExit("missing success flag") +print("asr transcribe ok") +PY + +echo "[5/8] check auto-session" curl_fetch -X POST "$BACKEND_URL/v2/auth/auto-session" \ -H 'content-type: application/json' \ -d '{}' >"$session_file" @@ -93,7 +133,7 @@ print(f"auto-session ok: {username}") ' "$session_file" "$token_file" token="$(cat "$token_file")" -echo "[5/7] check live project context and action registry" +echo "[6/8] check live project context and action registry" curl_fetch "$BACKEND_URL/v2/projects" \ -H "Authorization: Bearer $token" >"$projects_file" python3 -c ' @@ -123,7 +163,7 @@ if missing: print("action registry ok") ' "$action_registry_file" -echo "[6/7] check integrations health" +echo "[7/8] check integrations health" curl_fetch "$BACKEND_URL/v2/integrations/health" \ -H "Authorization: Bearer $token" >"$integrations_file" python3 -c ' @@ -140,7 +180,7 @@ if not cutvideo.get("supports_uploads"): print("integrations ok") ' "$integrations_file" "$CUTVIDEO_URL" -echo "[7/8] check fnOS tunnel endpoints" +echo "[8/8] check fnOS tunnel endpoints" curl_fetch "$CUTVIDEO_URL/api/bootstrap" >"$bootstrap_file" curl_fetch "$COMPAT_URL/" >"$compat_file" python3 -c ' diff --git a/scripts/smoke_public_storyforge.sh b/scripts/smoke_public_storyforge.sh index ee6fc3f..378c739 100755 --- a/scripts/smoke_public_storyforge.sh +++ b/scripts/smoke_public_storyforge.sh @@ -26,10 +26,13 @@ health_file="$tmp_dir/health.json" html_file="$tmp_dir/index.html" js_file="$tmp_dir/app.js" openapi_file="$tmp_dir/openapi.json" +asr_url_file="$tmp_dir/asr-url.txt" +asr_wav="$tmp_dir/asr.wav" +asr_result="$tmp_dir/asr.json" echo "[1/4] check public healthz" curl_fetch "$BASE_URL/healthz" >"$health_file" -python3 - "$health_file" <<'PY' +python3 - "$health_file" "$asr_url_file" <<'PY' import json import pathlib import sys @@ -38,22 +41,66 @@ payload = json.loads(pathlib.Path(sys.argv[1]).read_text()) status = str(payload.get("status") or "").lower() if status != "ok": raise SystemExit(f"unexpected health status: {status!r}") +asr_url = str(payload.get("asrHttpBaseUrl") or "").strip() +pathlib.Path(sys.argv[2]).write_text(asr_url, encoding="utf-8") print("healthz ok") PY -echo "[2/4] check public index" +echo "[2/5] check public ASR transcribe" +python3 - "$asr_wav" <<'PY' +import math +import struct +import sys +import wave + +path = sys.argv[1] +sample_rate = 16000 +duration = 0.25 +freq = 440.0 +samples = int(sample_rate * duration) +with wave.open(path, "wb") as handle: + handle.setnchannels(1) + handle.setsampwidth(2) + handle.setframerate(sample_rate) + for i in range(samples): + value = int(16000 * math.sin(2 * math.pi * freq * (i / sample_rate))) + handle.writeframes(struct.pack(""$asr_result" + python3 - "$asr_result" <<'PY' +import json +import pathlib +import sys + +payload = json.loads(pathlib.Path(sys.argv[1]).read_text()) +if "duration_ms" not in payload: + raise SystemExit("missing duration_ms") +if "success" not in payload: + raise SystemExit("missing success flag") +print("asr transcribe ok") +PY + ;; +esac + +echo "[3/5] check public index" curl_fetch "$BASE_URL/" >"$html_file" rg -q "StoryForge" "$html_file" echo "index ok" -echo "[3/4] check deployed web bundle" +echo "[4/5] check deployed web bundle" curl_fetch "$BASE_URL/assets/app.js" >"$js_file" rg -q "select-platform" "$js_file" rg -q "trackingCursorMap" "$js_file" rg -q "renderPlatformSwitchChips" "$js_file" echo "bundle ok" -echo "[4/4] check public openapi routes" +echo "[5/5] check public openapi routes" curl_fetch "$BASE_URL/openapi.json" >"$openapi_file" for route in \ '"/v2/xiaohongshu/accounts"' \ diff --git a/tests/test_production_baseline.py b/tests/test_production_baseline.py index f5e0016..57cf0aa 100644 --- a/tests/test_production_baseline.py +++ b/tests/test_production_baseline.py @@ -244,6 +244,7 @@ class ProductionBaselineTests(unittest.TestCase): "/healthz", "/v2/auth/auto-session", "/v2/integrations/health", + "/transcribe", "/api/bootstrap", "19181", ]: