reel-studio-2 / core /adapters /alignment.py
xvepkj's picture
initial commit
3d2098f
Raw
History Blame
1.57 kB
"""Forced-alignment fallback for word timings.
When a TTS provider returns no word timings, we try faster-whisper (if
installed) to recover them from the rendered audio. faster-whisper is an
OPTIONAL dependency — when missing or failing, return None and the render
stage degrades to static (per-scene) captions instead of karaoke.
"""
from __future__ import annotations
from typing import Optional
from core.contracts import WordTiming
from core.utils import log
_model = None
_model_failed = False
def align_words(audio_path: str, text: str) -> Optional[list[WordTiming]]:
"""Best-effort word timings for ``audio_path``. None on any failure."""
global _model, _model_failed
if _model_failed:
return None
try:
if _model is None:
from faster_whisper import WhisperModel # type: ignore
_model = WhisperModel("tiny", device="cpu", compute_type="int8")
segments, _info = _model.transcribe(audio_path, word_timestamps=True)
timings: list[WordTiming] = []
for seg in segments:
for w in seg.words or []:
timings.append(WordTiming(word=w.word.strip(), start=w.start, end=w.end))
return timings or None
except ImportError:
log.info("faster-whisper not installed — captions will be static (pip install faster-whisper to enable karaoke alignment)")
_model_failed = True
return None
except Exception as e:
log.warning("Forced alignment failed (%s) — falling back to static captions", e)
return None