File size: 4,431 Bytes
1656123
 
c9bdefb
 
1656123
 
 
2032ce4
5fe379f
1656123
 
 
 
 
 
 
 
 
 
9dc9b96
1656123
 
 
2032ce4
 
 
 
8203c90
6a87101
1656123
 
 
 
c9bdefb
1656123
 
 
 
2032ce4
1656123
 
5a5f3c0
37e4785
 
76c80ea
1656123
 
 
 
37e4785
1656123
2032ce4
26b0d5c
2032ce4
6a87101
 
 
 
 
 
 
 
 
 
 
 
 
 
2032ce4
1656123
37e4785
1656123
5fe379f
6a87101
1656123
 
 
d399866
 
 
c092233
d399866
1656123
c9bdefb
37e4785
1656123
 
 
5fe379f
 
 
1656123
 
5fe379f
 
 
 
00e0911
1656123
00e0911
37e4785
00e0911
 
 
5fe379f
37e4785
5fe379f
1656123
 
5fe379f
1656123
 
 
37e4785
1656123
 
37e4785
1656123
807b744
 
 
 
 
 
 
1656123
 
 
2032ce4
 
a2e53e2
 
 
e579447
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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 کن

@app.get("/health")
async def health():
    return {"status": "ok", "message": "SubFlow backend is running"}


@app.websocket("/transcribe")
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