"""字幕引擎:根据 stdout 关键词打时间戳,生成 SRT 字幕文件。""" from __future__ import annotations import time from dataclasses import dataclass from pathlib import Path from typing import List, Tuple @dataclass class _Entry: start: float # 距录制开始的秒数 text: str duration: float = 5.0 # 每条字幕默认显示 5 秒 class SubtitleEngine: def __init__(self, script: List[Tuple[str, str]], default_duration: float = 5.0): """ script: [(关键词, 字幕文案), ...] 关键词大小写不敏感,每个关键词只触发一次。 """ self._script = script self._default_duration = default_duration self._entries: List[_Entry] = [] self._matched: set[str] = set() self._t0: float = 0.0 def set_start_time(self, t: float) -> None: self._t0 = t def process_line(self, line: str) -> None: lower = line.lower() for keyword, text in self._script: if keyword in self._matched: continue if keyword.lower() in lower: elapsed = time.time() - self._t0 self._entries.append(_Entry(start=elapsed, text=text, duration=self._default_duration)) self._matched.add(keyword) def generate_srt(self, output_path: str) -> None: def _fmt(s: float) -> str: h = int(s // 3600) m = int((s % 3600) // 60) sec = int(s % 60) ms = int((s % 1) * 1000) return f"{h:02d}:{m:02d}:{sec:02d},{ms:03d}" Path(output_path).parent.mkdir(parents=True, exist_ok=True) with open(output_path, "w", encoding="utf-8") as f: for i, e in enumerate(self._entries, 1): f.write(f"{i}\n") f.write(f"{_fmt(e.start)} --> {_fmt(e.start + e.duration)}\n") f.write(f"{e.text}\n\n")