recycleactor commited on
Commit
2072e4a
·
verified ·
1 Parent(s): 9fcc86f

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +45 -2
  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=gr.Audio(type="filepath", label="Аудио"),
 
 
 
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