Skip to content

fix(cli): assign w{index} ids when loading JSON transcripts - #3770

Open
santhiprakash wants to merge 1 commit into
heygen-com:mainfrom
santhiprakash:fix/transcribe-word-id
Open

fix(cli): assign w{index} ids when loading JSON transcripts#3770
santhiprakash wants to merge 1 commit into
heygen-com:mainfrom
santhiprakash:fix/transcribe-word-id

Conversation

@santhiprakash

Copy link
Copy Markdown
Contributor

Continuation of #3461, closed in the 2026-09-08 stale-PR sweep with "please reopen with a rebased version if still relevant." This is that rebased version — GitHub blocks author-reopens on PRs closed by a maintainer, so it is filed fresh. Rebased onto current main (d66cd6dcc); the words-json loader on main still defaults missing ids to "", so the fix applies unchanged.

Fixes #3442

What

loadTranscript now assigns id: w{i} on the JSON branches (whisper-cpp, OpenAI, words-json), matching what the srt/vtt branches already do. The words-json branch also stops defaulting missing ids to "" — it repairs them to w{i} instead.

Why

audio/references/transcribe.md documents that word ids (w0, w1, …) are "added during normalization for stable references in caption overrides", but every JSON path dropped them: parseWhisperCpp and parseOpenAI never set id, and the flat words-json branch defaulted it to "", collapsing every word onto the same empty key. All engines funnel through loadTranscripttranscribeAudio rewrites transcript.json from its output — so CLI-produced transcripts ship without ids and per-word caption overrides have nothing to key on (#3442 has the full breakdown, including the SRT round-trip workaround users currently need).

How

Single normalization point: after the existing format-specific parsing in loadTranscript, map id: w.id || \w{i}`over the words.||rather than??so the empty-string ids written by older CLIs into words-json files are repaired on load, not preserved. SRT/VTT branches keep their existing assignment; theWord.id` doc comment already describes exactly this behavior.

Test plan

  • packages/cli: bunx vitest run src/whisper/ on the rebased head (c1f87c64b) — 108/108 pass, including updated expectations (whisper-cpp / openai / words-json now carry w0… ids) and the regression test that preserves existing ids (keep-me) while repairing empty ("" → w1) and missing (→ w2) ones. The count includes 4 newer tests from fix(cli): keep phrase-level CJK and Thai transcripts as separate cues #3436 on the rebased base.
  • tsc --noEmit in packages/cli — clean on the rebased head.
  • Original submission (prior base, see fix(cli): assign w{index} ids when loading JSON transcripts #3461): full packages/cli vitest suite green apart from the same 20 pre-existing environmental failures as clean main, plus oxlint / oxfmt --check green.

This change is AI-assisted; the bug analysis, fix, and tests were verified against the reproduction in #3442.

loadTranscript assigns id: w{index} on the srt/vtt branches but never on
the JSON branches: parseWhisperCpp and parseOpenAI drop the field and the
words-json branch defaults it to "". Every engine funnels through
loadTranscript, and transcribeAudio rewrites transcript.json from its
output, so CLI-produced transcripts ship without the stable word ids that
transcribe.md documents for caption overrides — per-word overrides have
nothing to key on.

Assign id: w.id || `w{index}` across the JSON branches, matching the
srt/vtt behavior. || also repairs the empty-string ids older CLIs wrote
to words-json files, which otherwise collapse every word onto one key.

Signed-off-by: Santhi Prakash <b.santhiprakash@gmail.com>
@miguel-heygen
miguel-heygen enabled auto-merge (squash) September 8, 2026 19:23
@santhiprakash

Copy link
Copy Markdown
Contributor Author

One CI note so the red X doesn't need investigating: the Tests on windows-latest failure on this head is unrelated to the diff. The only failing test is @hyperframes/engine's ffprobe.test.ts > probeMediaProfile > bounds the process-scoped probe cache, which timed out at its own 5s limit while running 129 fixtures on a cold Windows runner (1 failed / 1706 passed in that suite). This PR only touches packages/cli/src/whisper/normalize.{ts,test.ts}, and the same workflow has been green on 15+ other runs tonight, including three main runs after this one. Re-running failed jobs needs repo-side access, so we're leaving the head as-is rather than pushing a re-trigger commit.

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.

transcribe never assigns word id on the JSON path, so per-word caption overrides have nothing to key on

2 participants