Download app.py from SubLabAI/Subflow: direct link, hf CLI and curl.
- Browser
- Download file 4.43 kB
-
https://huggingface.co/spaces/SubLabAI/Subflow/resolve/c0922331a58ef384d9caf803cb98a4e688e2a9bf/app.py
- Command line
-
hf download hf://spaces/SubLabAI/Subflow@c0922331a58ef384d9caf803cb98a4e688e2a9bf/app.py
-
curl -L -o app.py https://huggingface.co/spaces/SubLabAI/Subflow/resolve/c0922331a58ef384d9caf803cb98a4e688e2a9bf/app.py
4.43 kB
| import os | |
| import tempfile | |
| import numpy as np | |
| import torch | |
| from fastapi import FastAPI, WebSocket, WebSocketDisconnect | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from faster_whisper import WhisperModel | |
| from df.enhance import enhance, init_df, load_audio, save_audio | |
| from pipeline.postprocess import process | |
| app = FastAPI() | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| print("Loading Whisper model...", flush=True) | |
| model = WhisperModel("large-v3", device="cpu", compute_type="int8") | |
| print("Whisper model ready!") | |
| print("Loading DeepFilterNet model...", flush=True) | |
| df_model, df_state, _ = init_df() | |
| print("DeepFilterNet model ready!") | |
| USE_DEEPFILTERNET = False # برای تست بدون DeepFilterNet، این رو موقتاً False کن | |
| async def health(): | |
| return {"status": "ok", "message": "SubFlow backend is running"} | |
| async def transcribe(websocket: WebSocket): | |
| await websocket.accept() | |
| tmp_path = None | |
| enhanced_path = None | |
| try: | |
| print("Step 1: waiting for bytes") | |
| audio_bytes = await websocket.receive_bytes() | |
| print(f"Step 2: received {len(audio_bytes)} bytes") | |
| await websocket.send_json({"status": "receiving"}) | |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp: | |
| tmp.write(audio_bytes) | |
| tmp_path = tmp.name | |
| print(f"Step 3: saved to {tmp_path}") | |
| await websocket.send_json({"status": "cleaning"}) | |
| print("Step 3.5: cleaning audio with DeepFilterNet") | |
| audio_to_transcribe = tmp_path | |
| if USE_DEEPFILTERNET: | |
| await websocket.send_json({"status": "cleaning"}) | |
| print("Step 3.5: cleaning audio with DeepFilterNet") | |
| audio_data, _ = load_audio(tmp_path, sr=df_state.sr()) | |
| enhanced_audio = enhance(df_model, df_state, audio_data, atten_lim_db=20) | |
| enhanced_path = tmp_path.replace(".wav", "_enhanced.wav") | |
| save_audio(enhanced_path, enhanced_audio, df_state.sr()) | |
| audio_to_transcribe = enhanced_path | |
| print(f"Step 3.6: cleaned audio saved to {enhanced_path}") | |
| else: | |
| print("Step 3.5: skipping DeepFilterNet (disabled for A/B test)") | |
| await websocket.send_json({"status": "transcribing"}) | |
| print("Step 4: starting transcription") | |
| segments_raw, info = model.transcribe( | |
| audio_to_transcribe, | |
| language="en", | |
| word_timestamps=True, | |
| vad_filter=True, | |
| vad_parameters=dict( | |
| min_silence_duration_ms=500, | |
| speech_pad_ms=200, | |
| threshold=0.1 | |
| ), | |
| ) | |
| print("Step 5: transcription done") | |
| await websocket.send_json({"status": "processing"}) | |
| segments = [] | |
| for seg in segments_raw: | |
| words = list(seg.words) | |
| if not words: | |
| continue | |
| segments.append({ | |
| "text": seg.text.strip(), | |
| "start": words[0].start, | |
| "end": words[-1].end, | |
| "words": [{"word": w.word, "start": w.start, "end": w.end} for w in words], | |
| }) | |
| print(f"Step 6: got {len(segments)} segments") | |
| for i, seg in enumerate(segments[:5]): | |
| print(f" seg[{i}]: '{seg['text']}' | words={len(seg['words'])} | dur={seg['end']-seg['start']:.2f}s") | |
| srt_content = process(segments) | |
| print(f"Step 7: SRT built") | |
| await websocket.send_json({ | |
| "status": "done", | |
| "srt": srt_content, | |
| "language": info.language, | |
| "duration": info.duration, | |
| }) | |
| print("Step 8: done sent!") | |
| except WebSocketDisconnect: | |
| print("WebSocket disconnected by client") | |
| except Exception as e: | |
| print(f"ERROR: {type(e).__name__}: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| try: | |
| await websocket.send_json({"status": "error", "message": str(e)}) | |
| except Exception: | |
| pass | |
| finally: | |
| if tmp_path and os.path.exists(tmp_path): | |
| os.remove(tmp_path) | |
| if enhanced_path and os.path.exists(enhanced_path): | |
| os.remove(enhanced_path) | |
| try: | |
| await websocket.close() | |
| except Exception: | |
| pass |