AliJabbarpour commited on
Commit
6f452b7
·
verified ·
1 Parent(s): a761e46

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -4
app.py CHANGED
@@ -6,6 +6,7 @@ from fastapi import FastAPI, WebSocket, WebSocketDisconnect
6
  from fastapi.middleware.cors import CORSMiddleware
7
  from faster_whisper import WhisperModel
8
  from df.enhance import enhance, init_df, load_audio, save_audio
 
9
  from pipeline.postprocess import process
10
 
11
  app = FastAPI()
@@ -34,6 +35,13 @@ align_labels = align_bundle.get_labels()
34
  align_dictionary = {c: i for i, c in enumerate(align_labels)}
35
  print("Word-alignment model ready!")
36
 
 
 
 
 
 
 
 
37
 
38
  def realign_word_timestamps(waveform_16k, words, whisper_start, whisper_end):
39
  """
@@ -72,7 +80,6 @@ def realign_word_timestamps(waveform_16k, words, whisper_start, whisper_end):
72
  spans = torchaudio.functional.merge_tokens(aligned_tokens[0], scores[0])
73
 
74
  ratio = clip.shape[1] / emission.shape[1] / 16000
75
- char_idx = 0
76
  new_words = []
77
  span_idx = 0
78
  for w, tok in clean_words:
@@ -92,6 +99,17 @@ def realign_word_timestamps(waveform_16k, words, whisper_start, whisper_end):
92
  return words
93
 
94
 
 
 
 
 
 
 
 
 
 
 
 
95
  @app.get("/health")
96
  async def health():
97
  return {"status": "ok", "message": "SubFlow backend is running"}
@@ -155,6 +173,9 @@ async def transcribe(websocket: WebSocket):
155
  if align_waveform.shape[0] > 1:
156
  align_waveform = align_waveform.mean(dim=0, keepdim=True)
157
 
 
 
 
158
  segments = []
159
  for seg in segments_raw:
160
  words = list(seg.words)
@@ -166,16 +187,20 @@ async def transcribe(websocket: WebSocket):
166
  align_waveform, word_dicts, word_dicts[0]["start"], word_dicts[-1]["end"]
167
  )
168
 
 
 
 
169
  segments.append({
170
  "text": seg.text.strip(),
171
  "start": realigned[0]["start"],
172
  "end": realigned[-1]["end"],
173
  "words": realigned,
 
174
  })
175
 
176
  print(f"Step 6: got {len(segments)} segments")
177
  for i, seg in enumerate(segments[:5]):
178
- print(f" seg[{i}]: '{seg['text']}' | words={len(seg['words'])} | dur={seg['end']-seg['start']:.2f}s")
179
 
180
  await websocket.send_json({"status": "processing"})
181
 
@@ -189,8 +214,6 @@ async def transcribe(websocket: WebSocket):
189
  "duration": info.duration,
190
  })
191
  print("Step 8: done sent!")
192
-
193
- # کمی صبر کن تا client پیام رو دریافت کنه
194
  import asyncio
195
  await asyncio.sleep(1)
196
 
 
6
  from fastapi.middleware.cors import CORSMiddleware
7
  from faster_whisper import WhisperModel
8
  from df.enhance import enhance, init_df, load_audio, save_audio
9
+ from pyannote.audio import Pipeline as DiarizationPipeline
10
  from pipeline.postprocess import process
11
 
12
  app = FastAPI()
 
35
  align_dictionary = {c: i for i, c in enumerate(align_labels)}
36
  print("Word-alignment model ready!")
37
 
38
+ print("Loading speaker-diarization model...", flush=True)
39
+ HF_TOKEN = os.environ.get("HF_TOKEN")
40
+ diarize_pipeline = DiarizationPipeline.from_pretrained(
41
+ "pyannote/speaker-diarization-3.1", use_auth_token=HF_TOKEN
42
+ )
43
+ print("Speaker-diarization model ready!")
44
+
45
 
46
  def realign_word_timestamps(waveform_16k, words, whisper_start, whisper_end):
47
  """
 
80
  spans = torchaudio.functional.merge_tokens(aligned_tokens[0], scores[0])
81
 
82
  ratio = clip.shape[1] / emission.shape[1] / 16000
 
83
  new_words = []
84
  span_idx = 0
85
  for w, tok in clean_words:
 
99
  return words
100
 
101
 
102
+ def get_speaker_at(diarization, time_sec):
103
+ """
104
+ برای یه لحظه‌ی مشخص از صدا، می‌گه اون لحظه مال کدوم گوینده‌ست (SPEAKER_00, SPEAKER_01, ...).
105
+ اگه هیچ گوینده‌ای پیدا نشد، None برمی‌گردونه.
106
+ """
107
+ for turn, _, speaker in diarization.itertracks(yield_label=True):
108
+ if turn.start <= time_sec <= turn.end:
109
+ return speaker
110
+ return None
111
+
112
+
113
  @app.get("/health")
114
  async def health():
115
  return {"status": "ok", "message": "SubFlow backend is running"}
 
173
  if align_waveform.shape[0] > 1:
174
  align_waveform = align_waveform.mean(dim=0, keepdim=True)
175
 
176
+ print("Step 5.6: running speaker diarization")
177
+ diarization = diarize_pipeline(audio_to_transcribe)
178
+
179
  segments = []
180
  for seg in segments_raw:
181
  words = list(seg.words)
 
187
  align_waveform, word_dicts, word_dicts[0]["start"], word_dicts[-1]["end"]
188
  )
189
 
190
+ mid_time = (realigned[0]["start"] + realigned[-1]["end"]) / 2
191
+ speaker = get_speaker_at(diarization, mid_time)
192
+
193
  segments.append({
194
  "text": seg.text.strip(),
195
  "start": realigned[0]["start"],
196
  "end": realigned[-1]["end"],
197
  "words": realigned,
198
+ "speaker": speaker,
199
  })
200
 
201
  print(f"Step 6: got {len(segments)} segments")
202
  for i, seg in enumerate(segments[:5]):
203
+ print(f" seg[{i}]: '{seg['text']}' | speaker={seg['speaker']} | dur={seg['end']-seg['start']:.2f}s")
204
 
205
  await websocket.send_json({"status": "processing"})
206
 
 
214
  "duration": info.duration,
215
  })
216
  print("Step 8: done sent!")
 
 
217
  import asyncio
218
  await asyncio.sleep(1)
219