Percy3822 commited on
Commit
cd2fd2f
·
verified ·
1 Parent(s): d5083c7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -36
app.py CHANGED
@@ -1,4 +1,4 @@
1
- import os, io, time
2
  from fastapi import FastAPI, UploadFile, File, HTTPException
3
  from pydantic import BaseModel
4
  from faster_whisper import WhisperModel
@@ -6,7 +6,7 @@ from faster_whisper import WhisperModel
6
  MODEL_NAME = os.getenv("FASTER_WHISPER_MODEL", "tiny.en")
7
  NUM_THREADS = int(os.getenv("NUM_THREADS", "2"))
8
 
9
- # Load model at startup (CPU, int8)
10
  model = WhisperModel(MODEL_NAME, device="cpu", compute_type="int8", num_workers=NUM_THREADS)
11
 
12
  app = FastAPI(title="STT (faster-whisper CPU)")
@@ -16,44 +16,44 @@ class TranscribeOut(BaseModel):
16
  language: str | None = None
17
  duration: float | None = None
18
 
19
- @app.get("/health")
20
- def health():
21
- return {"ok": True, "model": MODEL_NAME}
22
-
23
  @app.post("/transcribe", response_model=TranscribeOut)
24
- async def transcribe(file: UploadFile = File(...)):
25
- # Basic validations
26
- if not file.filename:
27
- raise HTTPException(status_code=400, detail="No filename")
28
- if not file.content_type or not file.content_type.startswith("audio/"):
29
- # Allow unknown types; client may not set correctly
30
- pass
31
-
32
- # Read all bytes in memory (small test files)
33
- try:
34
- payload = await file.read()
35
- finally:
36
- await file.close()
37
  if not payload:
38
  raise HTTPException(status_code=400, detail="Empty file")
39
 
40
- # Run inference
41
- start = time.time()
42
- audio_buf = io.BytesIO(payload)
43
-
44
  try:
45
- segments, info = model.transcribe(audio_buf, vad_filter=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  except Exception as e:
47
- # Most common: ffmpeg missing (fixed by Dockerfile), or invalid audio
48
  raise HTTPException(status_code=500, detail=f"Transcription failed: {e}")
49
-
50
- text_chunks = []
51
- for seg in segments:
52
- text_chunks.append(seg.text.strip())
53
- text = " ".join([t for t in text_chunks if t])
54
-
55
- return TranscribeOut(
56
- text=text.strip(),
57
- language=getattr(info, "language", None),
58
- duration=getattr(info, "duration", None),
59
- )
 
1
+ import os, uuid, tempfile, shutil
2
  from fastapi import FastAPI, UploadFile, File, HTTPException
3
  from pydantic import BaseModel
4
  from faster_whisper import WhisperModel
 
6
  MODEL_NAME = os.getenv("FASTER_WHISPER_MODEL", "tiny.en")
7
  NUM_THREADS = int(os.getenv("NUM_THREADS", "2"))
8
 
9
+ # Load model once (CPU, int8)
10
  model = WhisperModel(MODEL_NAME, device="cpu", compute_type="int8", num_workers=NUM_THREADS)
11
 
12
  app = FastAPI(title="STT (faster-whisper CPU)")
 
16
  language: str | None = None
17
  duration: float | None = None
18
 
 
 
 
 
19
  @app.post("/transcribe", response_model=TranscribeOut)
20
+ async def transcribe(
21
+ file: UploadFile = File(...),
22
+ beam_size: int = 1,
23
+ vad_filter: bool = True,
24
+ ):
25
+ # Read the upload
26
+ payload = await file.read()
27
+ await file.close()
 
 
 
 
 
28
  if not payload:
29
  raise HTTPException(status_code=400, detail="Empty file")
30
 
31
+ # Persist to a temp file so ffmpeg can probe it robustly
32
+ suffix = os.path.splitext(file.filename or "")[1] or ".wav"
33
+ tmp_path = os.path.join(tempfile.gettempdir(), f"stt_{uuid.uuid4().hex}{suffix}")
 
34
  try:
35
+ with open(tmp_path, "wb") as f:
36
+ f.write(payload)
37
+
38
+ # Transcribe via file path (lets faster-whisper/ffmpeg do decoding)
39
+ segments, info = model.transcribe(
40
+ tmp_path,
41
+ beam_size=beam_size,
42
+ vad_filter=vad_filter,
43
+ )
44
+
45
+ parts = [seg.text.strip() for seg in segments if seg.text and seg.text.strip()]
46
+ text = " ".join(parts).strip()
47
+
48
+ return TranscribeOut(
49
+ text=text,
50
+ language=getattr(info, "language", None),
51
+ duration=getattr(info, "duration", None),
52
+ )
53
  except Exception as e:
 
54
  raise HTTPException(status_code=500, detail=f"Transcription failed: {e}")
55
+ finally:
56
+ try:
57
+ os.remove(tmp_path)
58
+ except Exception:
59
+ pass