virtual-class / scripts /smoke_tts.py
tourmii's picture
Deploy HF Spaces
905b7fd
Raw
History Blame Contribute Delete
2.55 kB
"""Thử giọng đọc chạy tại chỗ: tổng hợp một câu, in tốc độ và mốc từng từ.
SPEECH_PROVIDER=vieneu python scripts/smoke_tts.py
SPEECH_PROVIDER=vieneu python scripts/smoke_tts.py "Câu muốn nghe thử."
Lần chạy đầu tiên sẽ tải model từ HuggingFace về ~/.cache/huggingface, mất vài
phút. Những lần sau chỉ còn thời gian nạp model.
"""
import base64
import logging
import os
import sys
import time
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "backend"))
os.environ.setdefault("SPEECH_PROVIDER", "vieneu")
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")
from app.config import settings # noqa: E402
from app.services.speech import SpeechUnavailable, synthesize, warm_up # noqa: E402
DEFAULT = (
"Bình phương cạnh huyền bằng tổng bình phương hai cạnh góc vuông. "
"Em nhìn lên bảng nhé, thầy viết công thức ra đây."
)
def main() -> int:
text = sys.argv[1] if len(sys.argv) > 1 else DEFAULT
print(f"Provider : {settings.speech_provider}")
print(f"Giọng : {settings.vieneu_voice}")
print(f"Câu : {text}\n")
# Nạp model trước rồi mới bấm giờ — máy chủ cũng nạp sẵn lúc khởi động, nên
# gộp chung vào sẽ ra một con số không giống thứ học sinh thực sự phải chờ.
started = time.perf_counter()
warm_up()
print(f"Nạp model: {time.perf_counter() - started:.1f}s\n")
started = time.perf_counter()
try:
clip = synthesize(text, speed=1.0)
except SpeechUnavailable as exc:
print(f"Không đọc được: {exc}")
return 1
elapsed = time.perf_counter() - started
audio = base64.b64decode(clip.audio_base64)
spoken = clip.timings[-1].end_ms / 1000 if clip.timings else 0.0
out = Path("smoke_tts.mp3" if clip.mime_type == "audio/mpeg" else "smoke_tts.wav")
out.write_bytes(audio)
print(f"Mất : {elapsed:.1f}s cho ~{spoken:.1f}s tiếng (RTF {elapsed / max(spoken, 1e-6):.2f})")
print(f"File : {out}{len(audio) // 1024} KB, {clip.mime_type}")
print(f"Mốc : {len(clip.timings)} từ")
for timing in clip.timings[:8]:
print(f" {timing.start_ms:>6}{timing.end_ms:>6} ms {timing.word}")
if len(clip.timings) > 8:
print(" ...")
return 0
if __name__ == "__main__":
raise SystemExit(main())