45 lines
1.8 KiB
Python
45 lines
1.8 KiB
Python
"""Сборка строкового транскрипта сеанса из реконструированных фраз.
|
||
|
||
Формат строки — `[Имя MM:SS] текст` (или `[Имя ЧЧ:MM:SS] текст` от часа) —
|
||
ровно тот, что ожидает утверждённый map-промпт суммаризации
|
||
(`workers/summarizer/prompts/summary_map_ru.txt`) и парсит чанкер
|
||
(`backend/core/summarization/chunking.py`).
|
||
"""
|
||
|
||
from collections.abc import Sequence
|
||
from dataclasses import dataclass
|
||
|
||
|
||
@dataclass(frozen=True, slots=True)
|
||
class TranscriptLine:
|
||
"""Одна фраза транскрипта, готовая к форматированию в строку промпта.
|
||
|
||
`offset_s` — смещение начала фразы в секундах от `t_start` сеанса
|
||
(как у `PhraseDraft`, см. `workers/transcription/phrases.py`).
|
||
"""
|
||
|
||
speaker: str
|
||
offset_s: float
|
||
text: str
|
||
|
||
|
||
def _format_offset(offset_s: float) -> str:
|
||
"""Отформатировать смещение как `MM:SS`, либо `ЧЧ:MM:SS` при offset >= 1 часа."""
|
||
total_seconds = int(offset_s)
|
||
hours, remainder = divmod(total_seconds, 3600)
|
||
minutes, seconds = divmod(remainder, 60)
|
||
if hours:
|
||
return f"{hours}:{minutes:02d}:{seconds:02d}"
|
||
return f"{minutes:02d}:{seconds:02d}"
|
||
|
||
|
||
def build_transcript(lines: Sequence[TranscriptLine]) -> str:
|
||
"""Собрать транскрипт сеанса: сортировка по `offset_s` → строки-фразы.
|
||
|
||
Пустой список фраз даёт пустую строку.
|
||
"""
|
||
ordered = sorted(lines, key=lambda line: line.offset_s)
|
||
return "\n".join(
|
||
f"[{line.speaker} {_format_offset(line.offset_s)}] {line.text}" for line in ordered
|
||
)
|