Add speaker-attributed meeting transcription
This commit is contained in:
@@ -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"]
|
||||
|
||||
Reference in New Issue
Block a user