ememzyvisuals commited on
Commit
c1a4846
·
verified ·
1 Parent(s): 7a30f78

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. Dockerfile +1 -1
  2. app.py +1 -105
  3. requirements.txt +1 -0
Dockerfile CHANGED
@@ -4,4 +4,4 @@ COPY requirements.txt .
4
  RUN pip install --no-cache-dir -r requirements.txt
5
  COPY app.py .
6
  EXPOSE 7860
7
- CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--ws-ping-interval", "20", "--ws-ping-timeout", "40"]
 
4
  RUN pip install --no-cache-dir -r requirements.txt
5
  COPY app.py .
6
  EXPOSE 7860
7
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py CHANGED
@@ -49,7 +49,7 @@ for size, repo in MODEL_IDS.items():
49
  local_dir = snapshot_download(repo_id=repo, token=HF_TOKEN)
50
  PROCESSORS[size] = WhisperProcessor.from_pretrained(local_dir)
51
  MODELS[size] = ctranslate2.models.Whisper(
52
- local_dir, compute_type="int8", inter_threads=1, intra_threads=1
53
  )
54
  log_event("model_loaded_ok", model_size=size)
55
  except Exception as e:
@@ -247,110 +247,6 @@ async def transcribe(
247
  return {"request_id": request_id, "model_size": model_size, "language": language, "text": text,
248
  "audio_duration_s": round(duration_s, 2), "chunks_processed": n_chunks, "elapsed_s": round(elapsed, 2)}
249
 
250
- @app.websocket("/ws/transcribe")
251
- async def ws_transcribe(
252
- websocket: WebSocket,
253
- model_size: str = Query("large"),
254
- language: str = Query(...),
255
- token: str = Query(...),
256
- ):
257
- try:
258
- info = hf_api.whoami(token=token)
259
- user_orgs = [o.get("name") for o in info.get("orgs", [])]
260
- if ORG_NAME not in user_orgs:
261
- await websocket.close(code=4403); return
262
- username = info.get("name", "unknown")
263
- except Exception:
264
- await websocket.close(code=4401); return
265
-
266
- if model_size not in MODELS or language not in VALID_LANGS or VAD_MODEL is None:
267
- await websocket.close(code=4400); return
268
-
269
- await websocket.accept()
270
- send_lock = asyncio.Lock()
271
- async def safe_send_json(payload):
272
- async with send_lock:
273
- await websocket.send_json(payload)
274
- async def heartbeat(interval: float = 20.0):
275
- while True:
276
- await asyncio.sleep(interval)
277
- try:
278
- await safe_send_json({"type": "heartbeat"})
279
- log_event("ws_heartbeat_sent", user=username)
280
- except Exception as e:
281
- log_event("ws_heartbeat_failed", user=username, error=str(e))
282
- return
283
- heartbeat_task = asyncio.create_task(heartbeat())
284
- log_event("ws_connected", user=username, model_size=model_size, language=language)
285
-
286
- SR = 16000
287
- FRAME_SAMPLES = 512
288
- FRAME_BYTES = FRAME_SAMPLES * 2
289
- SILENCE_FRAMES_TO_FLUSH = max(1, int(600 / ((FRAME_SAMPLES / SR) * 1000)))
290
- MAX_UTTERANCE_SAMPLES = 25 * SR
291
- SPEECH_PROB_THRESHOLD = 0.5
292
-
293
- byte_buffer = b""
294
- speech_frames, speech_started, silence_run = [], False, 0
295
-
296
- async def flush_and_transcribe():
297
- nonlocal speech_frames, speech_started, silence_run
298
- if not speech_frames:
299
- speech_started, silence_run = False, 0
300
- return
301
- audio = np.concatenate(speech_frames)
302
- speech_frames, speech_started, silence_run = [], False, 0
303
- if len(audio) < int(0.2 * SR):
304
- return
305
- try:
306
- text, duration_s, _ = await asyncio.to_thread(run_inference, audio, SR, model_size, language)
307
- await safe_send_json({"type": "final", "text": text, "audio_duration_s": round(duration_s, 2)})
308
- log_event("ws_utterance_transcribed", user=username, duration_s=round(duration_s, 2))
309
- except Exception as e:
310
- log_event("ws_transcribe_error", user=username, error=str(e))
311
- try:
312
- await safe_send_json({"type": "error", "detail": "transcription failed"})
313
- except Exception:
314
- pass # socket already closed - nothing to send to
315
-
316
- try:
317
- while True:
318
- data = await websocket.receive_bytes()
319
- byte_buffer += data
320
- while len(byte_buffer) >= FRAME_BYTES:
321
- frame_bytes, byte_buffer = byte_buffer[:FRAME_BYTES], byte_buffer[FRAME_BYTES:]
322
- frame_f32 = np.frombuffer(frame_bytes, dtype=np.int16).astype(np.float32) / 32768.0
323
- prob = VAD_MODEL(torch.from_numpy(frame_f32), SR).item()
324
-
325
- if prob >= SPEECH_PROB_THRESHOLD:
326
- if not speech_started:
327
- speech_started = True
328
- await safe_send_json({"type": "speech_start"})
329
- speech_frames.append(frame_f32)
330
- silence_run = 0
331
- elif speech_started:
332
- speech_frames.append(frame_f32)
333
- silence_run += 1
334
- if silence_run >= SILENCE_FRAMES_TO_FLUSH:
335
- await flush_and_transcribe()
336
-
337
- if sum(len(f) for f in speech_frames) >= MAX_UTTERANCE_SAMPLES:
338
- log_event("ws_max_utterance_reached", user=username)
339
- await flush_and_transcribe()
340
- except WebSocketDisconnect:
341
- log_event("ws_disconnected", user=username)
342
- # client is gone - do not attempt to send anything further.
343
- # just discard any partial in-flight utterance rather than
344
- # transcribing into a socket that no longer exists.
345
- except RuntimeError as e:
346
- # server-initiated close (e.g. ping timeout) leaves the socket in
347
- # a disconnected state; a subsequent receive_bytes() raises
348
- # RuntimeError instead of WebSocketDisconnect. Treat the same way.
349
- log_event("ws_disconnected_runtime", user=username, error=str(e))
350
- finally:
351
- heartbeat_task.cancel()
352
-
353
-
354
  @app.exception_handler(HTTPException)
355
  async def http_exception_handler(request: Request, exc: HTTPException):
356
  log_event("request_error", path=str(request.url.path), status=exc.status_code, detail=exc.detail)
 
49
  local_dir = snapshot_download(repo_id=repo, token=HF_TOKEN)
50
  PROCESSORS[size] = WhisperProcessor.from_pretrained(local_dir)
51
  MODELS[size] = ctranslate2.models.Whisper(
52
+ local_dir, compute_type="int8", inter_threads=1, intra_threads=2
53
  )
54
  log_event("model_loaded_ok", model_size=size)
55
  except Exception as e:
 
247
  return {"request_id": request_id, "model_size": model_size, "language": language, "text": text,
248
  "audio_duration_s": round(duration_s, 2), "chunks_processed": n_chunks, "elapsed_s": round(elapsed, 2)}
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  @app.exception_handler(HTTPException)
251
  async def http_exception_handler(request: Request, exc: HTTPException):
252
  log_event("request_error", path=str(request.url.path), status=exc.status_code, detail=exc.detail)
requirements.txt CHANGED
@@ -16,3 +16,4 @@ websockets
16
  # force rebuild 1786901172
17
  # force rebuild 1786902184
18
  # force rebuild 1786902905
 
 
16
  # force rebuild 1786901172
17
  # force rebuild 1786902184
18
  # force rebuild 1786902905
19
+ # revert streaming, force rebuild 1786903429