Spaces:
Sleeping
Sleeping
File size: 2,683 Bytes
7d761b6 | 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 | """Transcription service: Audio -> canonical Transcript.
This is the only place that runs Whisper. It always uses Whisper's
"transcribe" task, never "translate" -- translation is handled as a
separate, text-based step (see services/translation.py) operating on the
Transcript this produces. That split is the core v1.0 architecture
decision: there is exactly one path from audio to text, and everything
else branches off the resulting Transcript.
"""
from __future__ import annotations
from typing import Optional
from faster_whisper import WhisperModel
from models.transcript import Segment, Transcript
# ISO 639-1 code -> display name. Used both for the "Source Language"
# dropdown and for labelling detected languages in the results dashboard.
SUPPORTED_LANGUAGES: dict[str, str] = {
"fr": "French",
"en": "English",
"de": "German",
"fa": "Persian",
"es": "Spanish",
}
class TranscriptionService:
"""Thin wrapper around a faster-whisper model.
Deliberately has no knowledge of translation, subtitles, or the UI --
it only knows how to turn audio into a Transcript.
"""
def __init__(
self,
model_size: str = "base",
device: str = "cpu",
compute_type: str = "int8",
download_root: str = "/tmp/whisper_models",
) -> None:
self._model = WhisperModel(
model_size,
device=device,
compute_type=compute_type,
download_root=download_root,
)
def transcribe(
self,
audio_path: str,
source_filename: str,
language: Optional[str] = None,
window_start: Optional[float] = None,
window_end: Optional[float] = None,
beam_size: int = 5,
) -> Transcript:
"""Run speech-to-text and return the canonical Transcript.
`language` is an ISO 639-1 code, or None for auto-detect (the
"Auto Detect" dropdown option).
"""
segments_iter, info = self._model.transcribe(
audio_path,
task="transcribe",
language=language,
beam_size=beam_size,
)
segments = [
Segment(index=i, start=seg.start, end=seg.end, text=seg.text.strip())
for i, seg in enumerate(segments_iter, start=1)
]
duration = segments[-1].end if segments else 0.0
return Transcript(
source_filename=source_filename,
language=info.language,
language_probability=info.language_probability,
duration=duration,
segments=segments,
window_start=window_start,
window_end=window_end,
)
|