Skip to content

feat: transcript search — find where we discussed X across recordings#191

Open
seonghobae wants to merge 1 commit into
mainfrom
feat/transcript-search
Open

feat: transcript search — find where we discussed X across recordings#191
seonghobae wants to merge 1 commit into
mainfrom
feat/transcript-search

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Summary

New stdlib-only module transcript_search.py: a lightweight inverted index over timestamped transcript segments, so you can search one or many transcripts and get back matches with timestamps — "find where we discussed X" across an archive of recordings. It pairs with the transcription sidecar's .json outputs (#165) without importing them.

What's included

  • TranscriptIndexadd(recording_id, segments) accepts duck-typed segments (.start/.end/.text attributes or mapping keys); search(query) returns list[Match].
  • Match dataclassrecording_id, start, end, text, score.
  • Search semantics — lowercase Unicode word-regex tokenization; multi-word queries use AND semantics; scored by summed term frequency; sorted by score desc, then recording id and start time.
  • load_transcript_json(path) — reads the transcription sidecar shape {"segments": [{"start", "end", "text"}]} so the two features compose while staying independent.
  • Edge cases — empty/punctuation-only query raises ValueError; no matches returns []; case- and punctuation-insensitive.
  • Honest limitation — CJK text is only whitespace/punctuation-split, not morphologically segmented; documented in the module docstring.

Tests

tests/test_transcript_search.py (17 tests): timestamp fidelity, AND semantics, term-frequency ranking, tie-breaking (recording id then time), case-insensitivity, empty-query ValueError, no-match empty list, multi-recording search, empty-index search, mapping duck typing, missing-field TypeError, and sidecar JSON roundtrip via tmp file (plus malformed-shape rejection).

Gates

  • python3.14 -m unittest discover -s tests: 130 tests, no new failures (exactly the 5 baseline macOS os.listxattr errors).
  • python3.14 -m interrogate -c pyproject.toml transcript_search.py: 100%.
  • New files only; no existing files touched.

🤖 Generated with Claude Code

Add transcript_search.py, a stdlib-only module that answers "find where
we discussed X" across an archive of recordings:

- TranscriptIndex: add(recording_id, segments) with duck-typed segments
  (attributes or mapping keys), search(query) with case-insensitive,
  punctuation-insensitive AND semantics, scored by term frequency and
  sorted by score desc then recording/time.
- Match dataclass carrying recording_id, start, end, text, score.
- load_transcript_json(path): reads the transcription sidecar shape
  {"segments": [{"start", "end", "text"}]} so it composes with the
  transcription pipeline output without importing it.
- Honest documentation of the CJK whitespace-tokenization limitation.

Tests cover timestamp fidelity, AND semantics, ranking, tie-breaking,
case-insensitivity, empty-query ValueError, no-match empty list,
multi-recording search, duck typing, and sidecar JSON roundtrip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJRVbDrp1vGYkJgNHMGPpG
@seonghobae seonghobae enabled auto-merge (squash) July 6, 2026 14: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.

1 participant