"""Генерация голосовых куи-файлов (готовые записи для мгновенного проигрыша). Запускается ОДИН РАЗ при настройке (и при смене голоса/скорости в .env): .venv/bin/python assets/earcons/generate_cues.py Файлы — статичные wav: ассистент играет их мгновенно (без синтеза в реальном времени), что даёт немедленное подтверждение «аудио-тракт жив». Если хочется свои записи — просто положи свои wav с этими именами (генератор не перезапишет существующие без флага --force). """ from __future__ import annotations import asyncio import sys from pathlib import Path import numpy as np try: from modules.tts import make_tts from modules.brain.config import get_secret except ImportError: sys.path.insert(0, str(Path(__file__).resolve().parents[2])) from modules.tts import make_tts from modules.brain.config import get_secret CUES_DIR = Path(__file__).resolve().parent CUES = { "dialog_start.wav": "Ассистент готов к диалогу.", "dialog_end.wav": "Спасибо. До новых встреч!", "error_network.wav": "Ошибка. Связь отсутствует. Проверьте интернет.", "error_limit.wav": "Превышен лимит ответа. Попробуйте позже.", "error_general.wav": "Произошла ошибка. Попробуйте ещё раз.", "unclear_question.wav": "Ваш вопрос неразборчив. Повторите, пожалуйста, чуть громче и ближе к микрофону.", } def main() -> int: force = "--force" in sys.argv voice = get_secret("TTS_VOICE") or "ru-RU-SvetlanaNeural" rate = get_secret("TTS_RATE") or "+15" print(f"Голос: {voice}, темп: {rate}") tts = make_tts() # edge (или текущий провайдер из .env) for filename, text in CUES.items(): path = CUES_DIR / filename if path.exists() and not force: print(f" {filename}: уже есть, пропускаю (--force для перегенерации)") continue result = tts.synthesize(text) import soundfile as sf sf.write(str(path), result.audio, result.samplerate) print(f" {filename}: готов ({result.duration_sec:.1f} c)") print(f"\nФайлы в {CUES_DIR}") return 0 if __name__ == "__main__": sys.exit(main())