vivekchakraverty commited on
Commit
0fe3056
·
verified ·
1 Parent(s): f192b6c

Download video via RapidAPI (own-CDN) -> faster-whisper transcript + local screenshots -> delete; retire proxies

Browse files
Files changed (1) hide show
  1. pipeline/asr.py +60 -0
pipeline/asr.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Local ASR transcription with faster-whisper, run on the downloaded video file.
2
+
3
+ Used when the pipeline downloads the source video (via the RapidAPI fast-downloader):
4
+ faster-whisper reads the media directly (PyAV decodes the audio track), so no separate
5
+ audio extraction is needed. Returns ``[{start, end, text}]`` segments — the same shape the
6
+ caption-based path produces — so the rest of the pipeline is unchanged.
7
+
8
+ Model size / device are configurable via env: ``WHISPER_MODEL`` (default ``base``),
9
+ ``WHISPER_DEVICE`` (default ``cpu``), ``WHISPER_COMPUTE`` (default ``int8`` — fastest on
10
+ CPU). ``base``/``int8`` is a sensible CPU default; use ``small``/``medium`` (or a GPU) for
11
+ higher accuracy.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import os
16
+ from functools import lru_cache
17
+
18
+
19
+ class ASRError(RuntimeError):
20
+ """Raised when local transcription fails."""
21
+
22
+
23
+ @lru_cache(maxsize=1)
24
+ def _model():
25
+ from faster_whisper import WhisperModel
26
+
27
+ size = os.environ.get("WHISPER_MODEL", "base")
28
+ device = os.environ.get("WHISPER_DEVICE", "cpu")
29
+ compute = os.environ.get("WHISPER_COMPUTE", "int8")
30
+ return WhisperModel(size, device=device, compute_type=compute)
31
+
32
+
33
+ def transcribe_file(media_path: str, language: str | None = "en",
34
+ progress=None) -> list[dict]:
35
+ """Transcribe ``media_path`` (audio or video) into ``[{start, end, text}]``.
36
+
37
+ ``language`` pins the language (faster + avoids misdetection); pass None to
38
+ auto-detect.
39
+ """
40
+ if not os.path.exists(media_path):
41
+ raise ASRError(f"media file not found: {media_path}")
42
+ try:
43
+ model = _model()
44
+ # No vad_filter: it depends on onnxruntime (Silero VAD) that isn't always
45
+ # present and, when broken, silently drops every segment. beam_size=1 for speed.
46
+ segments, info = model.transcribe(media_path, language=language, beam_size=1)
47
+ except Exception as exc:
48
+ raise ASRError(f"faster-whisper failed: {type(exc).__name__}: {exc}") from exc
49
+
50
+ total = float(getattr(info, "duration", 0) or 0)
51
+ out: list[dict] = []
52
+ for s in segments: # generator — transcription happens as we iterate
53
+ text = (s.text or "").strip()
54
+ if text:
55
+ out.append({"start": float(s.start), "end": float(s.end), "text": text})
56
+ if progress and total:
57
+ progress(min(1.0, (s.end or 0) / total), desc="Transcribing (faster-whisper)")
58
+ if not out:
59
+ raise ASRError("faster-whisper produced no speech segments.")
60
+ return out