# ==== F5-TTS_RUSSIAN — свой минимальный Gradio Space, по образу GigaAM ==== # # Деплой (как GigaAM): # 1. huggingface.co -> New Space -> SDK: Gradio -> Hardware: ZeroGPU # (бесплатно, но с очередью и лимитом времени на вызов — для одной # реплики этого достаточно; если не подойдёт, платный T4 small). # 2. Положить рядом с этим файлом: # - requirements.txt (см. ниже) # - ref_voice.wav — 5-15 секунд ЧИСТОЙ речи голосом, которым должен # говорить бот (без музыки/шума на фоне, лучше строгая, ровная # дикция — F5-TTS клонирует именно тембр и манеру произношения) # - переписать REF_TEXT ниже на ТОЧНУЮ дословную расшифровку того, что # реально сказано на ref_voice.wav (лишний/неточный текст — главная # причина кривых результатов у F5-TTS) # 3. Закоммитить (через веб-интерфейс Space или git push) — Space сам # соберётся и на первый вызов подтянет веса модели с HF (holodный # старт может занять пару минут — это нормально). # 4. В переменных окружения бота на Render задать: # TTS_SPACE=твой-юзернейм/имя-space # # requirements.txt: # f5-tts # gradio # soundfile # spaces import os import tempfile import gradio as gr import soundfile as sf import spaces from f5_tts.api import F5TTS # ---- Модель ---- # F5TTS_v1_Base_v2 — самый свежий из выложенных чекпоинтов Misha24-10 на # момент написания; если на HF появится более новый (проверить # huggingface.co/Misha24-10/F5-TTS_RUSSIAN) — можно смело поменять здесь. REPO = "Misha24-10/F5-TTS_RUSSIAN" CKPT_SUBPATH = "F5TTS_v1_Base_v2/model_last_inference.safetensors" VOCAB_SUBPATH = "F5TTS_v1_Base/vocab.txt" from huggingface_hub import hf_hub_download # Сами файлы весов можно тянуть на старте — это обычное скачивание, # GPU для этого не нужен. ckpt_path = hf_hub_download(REPO, CKPT_SUBPATH) vocab_path = hf_hub_download(REPO, VOCAB_SUBPATH) # ---- Референсный голос ---- REF_AUDIO = os.path.join(os.path.dirname(__file__), "ref_voice.wav") # !!! ОБЯЗАТЕЛЬНО заменить на точный текст, реально сказанный в ref_voice.wav REF_TEXT = "Судя по всему, использование костюма железного человека усугубляет ваше состояние." # А вот сам F5TTS(...) грузит чекпоинт СРАЗУ на CUDA-устройство — на # ZeroGPU видеокарта физически подключена к контейнеру только внутри # вызова функции, помеченной @spaces.GPU. Если создать модель на # верхнем уровне модуля (т.е. при старте контейнера), CUDA ещё не # подключена -> "RuntimeError: No CUDA GPUs are available". Поэтому # создаём модель лениво, при первом реальном запросе, уже внутри # GPU-функции. _tts = None def _get_tts(): global _tts if _tts is None: _tts = F5TTS( model="F5TTS_v1_Base", ckpt_file=ckpt_path, vocab_file=vocab_path, ) return _tts @spaces.GPU(duration=60) def tts_infer(text: str) -> str: if not text or not text.strip(): raise gr.Error("пустой текст") tts = _get_tts() wav, sr, _ = tts.infer( ref_file=REF_AUDIO, ref_text=REF_TEXT, gen_text=text.strip(), ) out_path = tempfile.mktemp(suffix=".wav") sf.write(out_path, wav, sr) return out_path demo = gr.Interface( fn=tts_infer, inputs=gr.Textbox(label="Текст"), outputs=gr.Audio(type="filepath", label="Озвучка"), api_name="tts", # именно этот путь бот дёргает как "/tts" через @gradio/client title="F5-TTS_RUSSIAN — озвучка для бота", ) demo.queue().launch()