Skip to content

Pack short meeting speech segments into one speech-to-text pass - #1862

Merged
r3dbars merged 3 commits into
mainfrom
claude/faster-meeting-transcripts-5rfhxf
Sep 28, 2026
Merged

r3dbars merged 3 commits into
mainfrom
claude/faster-meeting-transcripts-5rfhxf

Conversation

@r3dbars

@r3dbars r3dbars commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Why

Before: after Stop, a meeting made one Parakeet call per speech segment. Parakeet pads every call to a fixed 15 s window, so a typical 4 s segment cost the same work as 15 s of audio. Nothing kept the Mac awake while the job ran, so App Nap or idle sleep could stretch long jobs.

After: short segments are laid end to end (0.5 s silence between them) into one 15 s pass, and the text is split back per segment by token start times. A meeting needs roughly a third of the calls. The Mac stays awake (no App Nap, no idle sleep) while a transcription job runs.

Product Impact

  • Affects: meetings
  • Lane: meeting reliability
  • Why this matters: real-user P50 for 30 min+ meetings is ~66 s after Stop, with a long tail. The speech-to-text stage is most of that.

What changed

  • SpeechSegmentPacking (TranscriptedCore): layout of packed audio, word-level split by first-token start against mid-gap boundaries, and an in-order batcher. Segments longer than the window still go alone.
  • SpeechToTextEngine gains optional packedSegmentWindowSamples / transcribePackedSegments (default nil, so other engines are unchanged).
  • TranscriptionPipeline: system-audio loop and default mic loop go through the batcher. A packed call that fails or returns the wrong count falls back to one call per segment; cancellation still rethrows.
  • ParakeetEngine.transcribePackedSamplesWithTokenTimes + STTRouter wiring: Parakeet TDT v2/v3 only, auto language only. Whisper and explicit-language paths are untouched.
  • MeetingSTTAdapter: packing path, custom dictionary per segment, timings still recorded. TRANSCRIPTED_MEETING_STT_PACKING=0 turns it off.
  • TranscriptionJobActivity.keepingMacAwake wraps live, import and retry pipeline runs in a .userInitiated activity.
  • CLI import-audio: same packing switch plus a timing line ("N speech-to-text calls taking Y s (packing on/off)") for the before/after run.
  • Tests: SpeechSegmentPackingTests (layout, split, batcher, zero window, fallback).

How I checked it

  • scripts/dev/agent-preflight.sh
  • bash scripts/dev/linux-checks.sh (runs without Swift) — 48 passed
  • Selected checks from .agents/test-matrix.yml for the files changed (CI)
  • bash build.sh --no-open (CI)
  • bash run-tests.sh (CI)
  • Performance budget passed
  • bash run-integration-smoke.sh (CI)
  • swift test (CI)
  • swift test --package-path Tools/TranscriptedCLI (CI)
  • Manual check: before/after on a Mac

Checks I could not run, and why:

  • No Swift toolchain in the cloud session, so build and tests rely on CI.

Mac or hardware test still needed? Yes:

  1. TRANSCRIPTED_MEETING_STT_PACKING=0 transcripted import-audio <30-60 min recording> --output-dir <tmp> then the same without the variable. The timing line should show about a third of the calls and a shorter speech-to-text time with packing on. On main there is no packing, so the call count matches the "off" run.
  2. Diff the two transcripts: words should match apart from segment-edge differences.

Risk Review

  • Privacy / local-first behavior reviewed (on-device only, no new off-device data)
  • New analytics properties or Sentry tags avoid the sanitizer's drop fragments (none added; one local-only event meeting_packed_segments_transcribed)
  • Checked the text-pin tests for every file I edited (check-source-pins.py --changed-only PASS)
  • Storage path or migration impact reviewed (none)
  • Public-facing copy stays concrete and matches current product scope (no copy)
  • Release/update impact reviewed (none)
  • Agent PRs got an independent deep review of the full diff
  • UI changes include sanitized .agent-review/visuals/ evidence (no UI)
  • No private transcripts, audio, tokens, personal paths, or customer data are included

Notes

Follows #1861 (stage timings on meeting_transcript_saved), which will show the effect in real meetings via stt_calls, stt_ms and sleep_ms. Main risk: a word near a segment edge landing in the neighbouring segment.

Agent handoff

COORD_DONE: BRIEF | this PR | packing + keep-awake + CLI timing | none | decisions: Mac before/after run needs Justin's OK | linux-checks, source pins | CI green + deep review

🤖 Generated with Claude Code

https://claude.ai/code/session_01LcH2PBaqN6yYkxeoaYrj45


Generated by Claude Code

Mac results (2026-09-28, Apple M5 Max): passed

Built with this branch combined with main plus #1791 and #1788. Checks passed: build-deps --force, build.sh, run-tests.sh, swift test (incl. SpeechSegmentPackingTests), run-integration-smoke.sh, swift test --package-path Tools/TranscriptedCLI, and the CLI manifest and packaging tests.

transcripted-cli import-audio (--no-speaker-identification), packing off vs on:

Recording STT calls STT time Transcribe total
43 min, 5 speakers 251 → 156 20.00 → 15.63 s 24.55 → 19.72 s
27-min lecture with human captions 544 → 174 33.06 → 14.73 s 38.17 → 19.83 s

Accuracy:

  • 43 min: same 106 utterances and 5 speakers. 1 of 9,727 matched words moved speaker. 53 words (0.54%) differ, in 29 spots of 6 words or fewer.
  • Lecture vs its human captions (jiwer, same normalizer on both sides): WER 24.45% → 22.79%. Fewer substitutions (409 → 368), deletions (840 → 783) and insertions (461 → 443).

Packing is faster and no less accurate here.

claude and others added 3 commits September 25, 2026 17:24
Parakeet runs every call on a fixed 15 s window, so a 4 s segment costs as much encoder work as 15 s of audio, and a meeting made one call per segment. Short segments from the call audio and the default mic path now go end to end with 0.5 s of silence between them into one call, and the text is split back per segment by token start times. A packed call that fails falls back to one call per segment. TRANSCRIPTED_MEETING_STT_PACKING=0 turns packing off.

Also keeps the Mac from napping or idle-sleeping while a transcription job runs, and gives the CLI meeting import the same packing plus a timing line so a before/after run can prove the speedup.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LcH2PBaqN6yYkxeoaYrj45
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LcH2PBaqN6yYkxeoaYrj45
Picks up the VM test socket-path fix (#1883) and everything merged today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@r3dbars
r3dbars marked this pull request as ready for review September 28, 2026 02:53
@r3dbars
r3dbars merged commit af8b4fa into main Sep 28, 2026
8 checks passed
@r3dbars
r3dbars deleted the claude/faster-meeting-transcripts-5rfhxf branch September 28, 2026 08:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants