missvector commited on
Commit
51d6026
·
1 Parent(s): 29953bd

Switch to Vosk

Browse files
Files changed (1) hide show
  1. app.py +17 -50
app.py CHANGED
@@ -1,15 +1,13 @@
1
  import os
2
  import json
3
- import wave
4
  import tempfile
5
- import subprocess
6
  from pathlib import Path
7
  from fastapi import FastAPI, File, UploadFile
8
- from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
9
  from fastapi.staticfiles import StaticFiles
10
  from fastapi.middleware.cors import CORSMiddleware
11
- import shutil
12
- import asyncio
13
 
14
  app = FastAPI()
15
 
@@ -22,11 +20,8 @@ app.add_middleware(
22
 
23
  app.mount("/static", StaticFiles(directory="static"), name="static")
24
 
25
- # Vosk инициализируется мгновенно, 40MB
26
- from vosk import Model, KaldiRecognizer
27
- print("🟢 Loading Vosk model...")
28
- model = Model("vosk-model-small-ru-0.22")
29
- print("✅ Vosk ready!")
30
 
31
  @app.get("/", response_class=HTMLResponse)
32
  async def root():
@@ -37,55 +32,27 @@ async def root():
37
  async def transcribe_audio(file: UploadFile = File(...)):
38
  async def generate():
39
  try:
40
- yield json.dumps({"type": "status", "text": "🔄 Конвертация аудио..."}) + "\n"
41
 
42
  suffix = Path(file.filename).suffix
43
  with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
44
  shutil.copyfileobj(file.file, tmp)
45
  tmp_path = tmp.name
46
 
47
- # Конвертируем в WAV 16kHz моно
48
- wav_path = tmp_path + ".wav"
49
- subprocess.run([
50
- "ffmpeg", "-i", tmp_path,
51
- "-ar", "16000", "-ac", "1",
52
- "-acodec", "pcm_s16le",
53
- wav_path, "-y", "-loglevel", "quiet"
54
- ])
55
-
56
- yield json.dumps({"type": "status", "text": "🔄 Распознавание речи..."}) + "\n"
57
-
58
- # Открываем WAV и распознаем
59
- wf = wave.open(wav_path, "rb")
60
- rec = KaldiRecognizer(model, wf.getframerate())
61
- rec.SetWords(False)
62
-
63
- text = ""
64
- while True:
65
- data = wf.readframes(4000)
66
- if len(data) == 0:
67
- break
68
- if rec.AcceptWaveform(data):
69
- result = json.loads(rec.Result())
70
- part = result.get("text", "")
71
- if part:
72
- text += part + " "
73
- yield json.dumps({
74
- "type": "segment",
75
- "text": text.strip()
76
- }) + "\n"
77
 
78
- # Финальный результат
79
- final = json.loads(rec.FinalResult())
80
- text += final.get("text", "")
81
- text = text.strip()
82
 
83
- # Чистим файлы
84
- Path(tmp_path).unlink(missing_ok=True)
85
- Path(wav_path).unlink(missing_ok=True)
86
 
87
- yield json.dumps({"type": "done", "text": text}) + "\n"
88
-
 
 
 
 
89
  except Exception as e:
90
  yield json.dumps({"type": "error", "text": f"❌ Ошибка: {str(e)}"}) + "\n"
91
  finally:
 
1
  import os
2
  import json
3
+ import requests
4
  import tempfile
5
+ import shutil
6
  from pathlib import Path
7
  from fastapi import FastAPI, File, UploadFile
8
+ from fastapi.responses import HTMLResponse, StreamingResponse
9
  from fastapi.staticfiles import StaticFiles
10
  from fastapi.middleware.cors import CORSMiddleware
 
 
11
 
12
  app = FastAPI()
13
 
 
20
 
21
  app.mount("/static", StaticFiles(directory="static"), name="static")
22
 
23
+ HF_TOKEN = os.getenv("HF_TOKEN") # добавь в Settings -> Secrets
24
+ API_URL = "https://api-inference.huggingface.co/models/openai/whisper-tiny"
 
 
 
25
 
26
  @app.get("/", response_class=HTMLResponse)
27
  async def root():
 
32
  async def transcribe_audio(file: UploadFile = File(...)):
33
  async def generate():
34
  try:
35
+ yield json.dumps({"type": "status", "text": "🔄 Отправка на API..."}) + "\n"
36
 
37
  suffix = Path(file.filename).suffix
38
  with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
39
  shutil.copyfileobj(file.file, tmp)
40
  tmp_path = tmp.name
41
 
42
+ with open(tmp_path, "rb") as f:
43
+ data = f.read()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ Path(tmp_path).unlink()
 
 
 
46
 
47
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
48
+ response = requests.post(API_URL, headers=headers, data=data)
 
49
 
50
+ if response.status_code == 200:
51
+ text = response.json().get("text", "")
52
+ yield json.dumps({"type": "done", "text": text}) + "\n"
53
+ else:
54
+ yield json.dumps({"type": "error", "text": f"❌ API ошибка: {response.status_code}"}) + "\n"
55
+
56
  except Exception as e:
57
  yield json.dumps({"type": "error", "text": f"❌ Ошибка: {str(e)}"}) + "\n"
58
  finally: