from __future__ import annotations import argparse import base64 import json import math import struct import sys import urllib.error import urllib.request import wave from io import BytesIO def post_json(url: str, payload: dict, timeout: int) -> dict: request = urllib.request.Request( url, data=json.dumps(payload, ensure_ascii=False).encode("utf-8"), headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(request, timeout=timeout) as response: data = json.loads(response.read().decode("utf-8")) if not isinstance(data, dict): raise ValueError(f"JSON object expected from {url}") return data def make_wav_data_url(seconds: float = 1.0, sample_rate: int = 16000) -> str: frames = int(seconds * sample_rate) buffer = BytesIO() with wave.open(buffer, "wb") as wav: wav.setnchannels(1) wav.setsampwidth(2) wav.setframerate(sample_rate) for index in range(frames): envelope = 0.5 if 0.1 * sample_rate < index < 0.9 * sample_rate else 0.0 sample = int(9000 * envelope * math.sin(2 * math.pi * 440 * index / sample_rate)) wav.writeframesraw(struct.pack(" int: payload = { "base_url": args.audio_base_url, "audio_base64": make_wav_data_url(args.seconds), "filename": "smoke-tone.wav", "language": args.language, "task": args.task, } result = post_json(f"{args.chat_base_url.rstrip('/')}/api/audio/transcribe", payload, args.timeout) print(json.dumps(result, ensure_ascii=False, indent=2)) if result.get("error"): return 1 return 0 if result.get("model") and result.get("bytes") else 1 def format_url_error(exc: urllib.error.URLError) -> str: if isinstance(exc, urllib.error.HTTPError): try: body = exc.read().decode("utf-8", errors="replace").strip() except OSError: body = "" return f"HTTP {exc.code}: {body or exc.reason}" return str(exc) def main() -> int: parser = argparse.ArgumentParser(description="Smoke test audio transcription through the model chat API.") parser.add_argument("--chat-base-url", default="http://192.168.220.91:8765") parser.add_argument("--audio-base-url", default="http://docker-gpu.cin.su:8020") parser.add_argument("--language", default="russian") parser.add_argument("--task", default="transcribe") parser.add_argument("--seconds", type=float, default=1.0) parser.add_argument("--timeout", type=int, default=600) parser.add_argument("--allow-unavailable", action="store_true") args = parser.parse_args() try: return run(args) except (OSError, ValueError, urllib.error.URLError) as exc: message = format_url_error(exc) if isinstance(exc, urllib.error.URLError) else str(exc) print(f"Smoke audio transcription failed: {message}", file=sys.stderr) return 0 if args.allow_unavailable else 1 if __name__ == "__main__": raise SystemExit(main())