BanglaSumQA / backend /modules /asr_engine.py
Nanny7's picture
Initial commit: BanglaSumQA - Bangla AI Summarizer & QA System
d6722a2
Raw
History Blame Contribute Delete
3.67 kB
"""
Bangla ASR Engine — uses faster-whisper (CTranslate2 backend) for efficient
speech-to-text. Supports webm, ogg, wav, mp3, m4a, flac via ffmpeg.
Model is lazy-loaded on first call.
faster-whisper is a drop-in replacement for openai-whisper with:
- Same model weights / same quality
- 4x faster inference
- Lower memory footprint
- Proper pip wheel (no build issues)
"""
import os
import sys
import warnings
warnings.filterwarnings("ignore")
# Fix Windows console encoding so Bangla characters print safely
if sys.stdout.encoding and sys.stdout.encoding.lower() != "utf-8":
try:
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
except Exception:
pass
# Lazy-loaded globals
_model = None
_model_size = None
def _log(msg: str):
"""Safe print that never raises UnicodeEncodeError on Windows consoles."""
try:
print(msg)
except UnicodeEncodeError:
print(msg.encode("utf-8", errors="replace").decode("ascii", errors="replace"))
def _load_model():
"""Lazily load faster-whisper model (called once on first use)."""
global _model, _model_size
if _model is not None:
return
from faster_whisper import WhisperModel
# 'small' (~500MB) is a good balance: accurate for Bangla, loads in ~60s on CPU
size = os.getenv("WHISPER_MODEL_SIZE", "small")
_log(f"[Whisper] Loading faster-whisper model size: '{size}'")
_log(f"[Whisper] First run will download the model weights (~500MB for 'small')...")
# Use int8 on CPU for memory efficiency; float16 on GPU
device = "cuda" if _cuda_available() else "cpu"
compute = "float16" if device == "cuda" else "int8"
_model = WhisperModel(size, device=device, compute_type=compute)
_model_size = size
_log(f"[Whisper] faster-whisper '{size}' loaded on {device} ({compute})!")
def _cuda_available() -> bool:
try:
import torch
return torch.cuda.is_available()
except Exception:
return False
def transcribe_audio(audio_path: str) -> str:
"""
Transcribe an audio file to Bangla text using faster-whisper.
Args:
audio_path: Path to the audio file (any ffmpeg-supported format).
Returns:
Transcribed Bangla text string.
Raises:
RuntimeError: If transcription fails.
"""
_load_model()
if not os.path.exists(audio_path):
raise RuntimeError(f"Audio file not found: {audio_path}")
file_size = os.path.getsize(audio_path)
if file_size < 100:
raise RuntimeError("অডিও ফাইলটি খুব ছোট বা খালি।")
_log(f"[Whisper] Transcribing: {os.path.basename(audio_path)} ({file_size} bytes)")
try:
segments, info = _model.transcribe(
audio_path,
language="bn", # Bengali/Bangla
task="transcribe",
beam_size=5,
vad_filter=True, # Skip silent segments
vad_parameters=dict(min_silence_duration_ms=500),
)
# faster-whisper returns a generator; collect all segment text
text_parts = [segment.text for segment in segments]
transcript = " ".join(text_parts).strip()
except Exception as e:
raise RuntimeError(f"অডিও ট্রান্সক্রিপশনে সমস্যা হয়েছে: {e}")
# Safe log: encode preview so Windows cp1252 console never crashes
preview = transcript[:100].encode("utf-8", errors="replace").decode("ascii", errors="replace")
_log(f"[Whisper] Transcript ({info.language}, {info.language_probability:.0%}): {preview}...")
return transcript