Add speaker-attributed meeting transcription

This commit is contained in:
2026-06-12 12:18:35 +00:00
parent 7516e0ad61
commit 8fd5e5b464
7 changed files with 571 additions and 13 deletions
+55
View File
@@ -363,6 +363,61 @@ async def transcribe(audio_path: str) -> str:
pass
async def transcribe_tracks(tracks: list[dict]) -> str:
"""Transcribe per-speaker WAV files and return a speaker-labeled transcript.
``tracks`` is a list of dicts shaped like the ``tracks.json`` manifest
entries: ``{"display_name": str, "path": str, ...}``. Each track is
transcribed independently, then prefixed with the speaker's display name so
the summary model can attribute who said what.
Tracks that produce no transcript (silence-only, decode failure) are
skipped. Raises RuntimeError only if NO track produced any text.
"""
from helpers import build_transcript_block
blocks: list[str] = []
failures: list[str] = []
for track in tracks:
path = track.get("path")
display_name = track.get("display_name") or "Unknown User"
if not path or not os.path.exists(path):
failures.append(f"{display_name}: track file missing ({path})")
continue
try:
text = await transcribe(path)
except Exception as exc: # noqa: BLE001 - per-track isolation is intentional
failures.append(f"{display_name}: {exc}")
logger.warning(
"Per-speaker transcription failed: display_name=%s path=%s error=%s",
display_name,
path,
exc,
)
continue
if text.strip():
blocks.append(build_transcript_block(display_name, text))
logger.info(
"Per-speaker transcription complete: display_name=%s transcript_chars=%s",
display_name,
len(text.strip()),
)
if not blocks:
raise RuntimeError(
"Speaker-track transcription produced no text"
+ (": " + " | ".join(failures) if failures else "")
)
if failures:
logger.warning("Some speaker tracks failed to transcribe: %s", " | ".join(failures))
return "\n\n".join(blocks)
def _extract_chat_content(data: Any, *, provider: str) -> str:
try:
content = data["choices"][0]["message"]["content"]