urdu-s2s-mvp / scripts /s2s_live_preflight.py
sufinity's picture
Deploy Urdu S2S MVP
c759578 verified
Raw
History Blame Contribute Delete
2.85 kB
#!/usr/bin/env python3
"""Preflight checks for the live Urdu S2S runtime."""
from __future__ import annotations
import argparse
import importlib.util
import json
import os
import sys
from pathlib import Path
from typing import Callable, Mapping
ROOT = Path(__file__).resolve().parents[1]
DEFAULT_AUDIO = ROOT / "data/raw/benchmarks/gemini_urdu_s2s_v1/audio/bench_001.wav"
DEFAULT_VOICE_ANCHOR = ROOT / "data/processed/voice_anchors/chatterbox_praxy_v1/bench_025.wav"
def default_module_available(name: str) -> bool:
return importlib.util.find_spec(name) is not None
def check_runtime(
*,
audio_path: Path,
voice_prompt_audio_path: Path,
require_openai_key: bool,
module_available: Callable[[str], bool] = default_module_available,
env: Mapping[str, str] = os.environ,
python_version: tuple[int, int, int] = sys.version_info[:3],
) -> dict[str, object]:
dependencies = {
"faster_whisper": "present" if module_available("faster_whisper") else "missing",
"chatterbox": "present" if module_available("chatterbox") else "missing",
"soundfile": "present" if module_available("soundfile") else "missing",
}
paths = {
"audio_path": "present" if audio_path.exists() else "missing",
"voice_prompt_audio_path": "present" if voice_prompt_audio_path.exists() else "missing",
}
secrets = {
"OPENAI_API_KEY": "present" if env.get("OPENAI_API_KEY") else "missing",
}
warnings: list[str] = []
if python_version >= (3, 13, 0):
warnings.append(
f"Python {python_version[0]}.{python_version[1]} detected; "
"ML audio packages are usually safer on Python 3.10-3.12."
)
checks = list(dependencies.values()) + list(paths.values())
if require_openai_key:
checks.extend(secrets.values())
return {
"ok": all(value == "present" for value in checks),
"python": ".".join(str(part) for part in python_version),
"dependencies": dependencies,
"paths": paths,
"secrets": secrets,
"warnings": warnings,
}
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--audio-path", type=Path, default=DEFAULT_AUDIO)
parser.add_argument("--voice-prompt-audio-path", type=Path, default=DEFAULT_VOICE_ANCHOR)
parser.add_argument("--no-openai-key-required", action="store_true")
return parser.parse_args()
def main() -> int:
args = parse_args()
report = check_runtime(
audio_path=args.audio_path,
voice_prompt_audio_path=args.voice_prompt_audio_path,
require_openai_key=not args.no_openai_key_required,
)
print(json.dumps(report, indent=2, ensure_ascii=False))
return 0 if report["ok"] else 2
if __name__ == "__main__":
raise SystemExit(main())