Spaces:
Running on Zero
Running on Zero
Upload 2 files
Browse files- app.py +45 -2
- requirements.txt +1 -0
app.py
CHANGED
|
@@ -21,6 +21,8 @@ def _zerogpu_startup_probe():
|
|
| 21 |
|
| 22 |
import gigaam
|
| 23 |
import gradio as gr
|
|
|
|
|
|
|
| 24 |
|
| 25 |
# Модель грузим ОДИН раз при старте контейнера, не на каждый запрос.
|
| 26 |
# v3_e2e_ctc — версия с пунктуацией и нормализацией текста (не голый поток
|
|
@@ -33,6 +35,33 @@ import gradio as gr
|
|
| 33 |
# компактная (220-240М параметров), GPU ей и не нужен.
|
| 34 |
MODEL = gigaam.load_model("v3_e2e_ctc", device="cpu")
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
# Нативный model.transcribe() ограничен 25 секундами аудио за вызов.
|
| 37 |
# Официальный обход (.transcribe_longform) тянет за собой pyannote.audio
|
| 38 |
# и токен Hugging Face — ради простой последовательной нарезки заводить
|
|
@@ -73,12 +102,23 @@ def _split_into_chunks(wav_path: str) -> list[str]:
|
|
| 73 |
return sorted(glob.glob(os.path.join(out_dir, "chunk_*.wav")))
|
| 74 |
|
| 75 |
|
| 76 |
-
def transcribe(audio_path: str) -> str:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
if not audio_path:
|
| 78 |
return ""
|
| 79 |
wav_path = _to_wav(audio_path)
|
| 80 |
chunks: list[str] = []
|
| 81 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
chunks = _split_into_chunks(wav_path)
|
| 83 |
parts = [str(MODEL.transcribe(chunk)).strip() for chunk in chunks]
|
| 84 |
return " ".join(p for p in parts if p).strip()
|
|
@@ -100,7 +140,10 @@ def transcribe(audio_path: str) -> str:
|
|
| 100 |
# предсказуем (/call/transcribe) и не завязан на автогенерируемое имя.
|
| 101 |
demo = gr.Interface(
|
| 102 |
fn=transcribe,
|
| 103 |
-
inputs=
|
|
|
|
|
|
|
|
|
|
| 104 |
outputs=gr.Textbox(label="Транскрипция"),
|
| 105 |
title="GigaAM-v3 — распознавание речи (RU)",
|
| 106 |
api_name="transcribe",
|
|
|
|
| 21 |
|
| 22 |
import gigaam
|
| 23 |
import gradio as gr
|
| 24 |
+
from faster_whisper import WhisperModel
|
| 25 |
+
from faster_whisper.audio import decode_audio
|
| 26 |
|
| 27 |
# Модель грузим ОДИН раз при старте контейнера, не на каждый запрос.
|
| 28 |
# v3_e2e_ctc — версия с пунктуацией и нормализацией текста (не голый поток
|
|
|
|
| 35 |
# компактная (220-240М параметров), GPU ей и не нужен.
|
| 36 |
MODEL = gigaam.load_model("v3_e2e_ctc", device="cpu")
|
| 37 |
|
| 38 |
+
# GigaAM обучена только на русской речи — на других языках она не "не
|
| 39 |
+
# понимает" в смысле пустого результата, а галлюцинирует русский текст по
|
| 40 |
+
# созвучию (особенно опасно для карточки "о чём песня" — см. index.js:
|
| 41 |
+
# ошибочная "русская" расшифровка иностранного текста песни ломает весь
|
| 42 |
+
# последующий ответ модели). Поэтому перед прогоном через GigaAM отдельно
|
| 43 |
+
# определяем язык лёгкой моделью faster-whisper (tiny, только
|
| 44 |
+
# language-id — полную транскрибацию ею не делаем, для этого дальше в
|
| 45 |
+
# пайплайне бота уже есть Groq Whisper). tiny достаточно для language-id:
|
| 46 |
+
# точность определения языка у tiny почти не хуже, чем у крупных моделей,
|
| 47 |
+
# в отличие от точности самой транскрибации.
|
| 48 |
+
LANG_ID_MODEL = WhisperModel("tiny", device="cpu", compute_type="int8")
|
| 49 |
+
|
| 50 |
+
# Ниже этого порога уверенности определённому языку не доверяем и всё
|
| 51 |
+
# равно отдаём на GigaAM — так безопаснее для коротких/тихих голосовых,
|
| 52 |
+
# где language-id менее надёжен, чем ошибочно отбраковывать русскую речь.
|
| 53 |
+
LANG_ID_MIN_CONFIDENCE = 0.5
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _detect_language(wav_path: str) -> tuple[str, float]:
|
| 57 |
+
"""Определяет язык по первому 30-секундному сегменту WAV (больше и не
|
| 58 |
+
нужно — language-id у Whisper всегда смотрит только на первый сегмент,
|
| 59 |
+
длинное аудио тут не даёт точности, только замедляет)."""
|
| 60 |
+
audio = decode_audio(wav_path, sampling_rate=16000)
|
| 61 |
+
language, probability, _ = LANG_ID_MODEL.detect_language(audio)
|
| 62 |
+
return language, probability
|
| 63 |
+
|
| 64 |
+
|
| 65 |
# Нативный model.transcribe() ограничен 25 секундами аудио за вызов.
|
| 66 |
# Официальный обход (.transcribe_longform) тянет за собой pyannote.audio
|
| 67 |
# и токен Hugging Face — ради простой последовательной нарезки заводить
|
|
|
|
| 102 |
return sorted(glob.glob(os.path.join(out_dir, "chunk_*.wav")))
|
| 103 |
|
| 104 |
|
| 105 |
+
def transcribe(audio_path: str, force_giga: bool = False) -> str:
|
| 106 |
+
"""force_giga=True пропускает language-id и всегда гонит через GigaAM —
|
| 107 |
+
для ручного выбора движка на стороне бота ("Жень текст giga"). В
|
| 108 |
+
остальных случаях (auto) сначала проверяем язык и на не-русском сразу
|
| 109 |
+
возвращаем "" — вызывающий код в боте трактует пустой ответ как "GigaAM
|
| 110 |
+
не справился" и молча уходит на Groq Whisper (см. transcribeViaGigaAM в
|
| 111 |
+
index.js), поэтому отдельный сигнал "чужой язык" наружу прокидывать не
|
| 112 |
+
нужно, пустой строки достаточно."""
|
| 113 |
if not audio_path:
|
| 114 |
return ""
|
| 115 |
wav_path = _to_wav(audio_path)
|
| 116 |
chunks: list[str] = []
|
| 117 |
try:
|
| 118 |
+
if not force_giga:
|
| 119 |
+
language, probability = _detect_language(wav_path)
|
| 120 |
+
if language != "ru" or probability < LANG_ID_MIN_CONFIDENCE:
|
| 121 |
+
return ""
|
| 122 |
chunks = _split_into_chunks(wav_path)
|
| 123 |
parts = [str(MODEL.transcribe(chunk)).strip() for chunk in chunks]
|
| 124 |
return " ".join(p for p in parts if p).strip()
|
|
|
|
| 140 |
# предсказуем (/call/transcribe) и не завязан на автогенерируемое имя.
|
| 141 |
demo = gr.Interface(
|
| 142 |
fn=transcribe,
|
| 143 |
+
inputs=[
|
| 144 |
+
gr.Audio(type="filepath", label="Аудио"),
|
| 145 |
+
gr.Checkbox(value=False, label="Принудительно GigaAM (бе�� проверки языка)"),
|
| 146 |
+
],
|
| 147 |
outputs=gr.Textbox(label="Транскрипция"),
|
| 148 |
title="GigaAM-v3 — распознавание речи (RU)",
|
| 149 |
api_name="transcribe",
|
requirements.txt
CHANGED
|
@@ -3,3 +3,4 @@ torch==2.11.0
|
|
| 3 |
torchaudio==2.11.0+cpu
|
| 4 |
git+https://github.com/salute-developers/GigaAM.git
|
| 5 |
gradio
|
|
|
|
|
|
| 3 |
torchaudio==2.11.0+cpu
|
| 4 |
git+https://github.com/salute-developers/GigaAM.git
|
| 5 |
gradio
|
| 6 |
+
faster-whisper
|