Skip to content

Fix missing word timestamps for non-English (espeak) voices#484

Merged
remsky merged 1 commit into
remsky:masterfrom
mlevinmail:fix/non-english-word-timestamps
Jul 12, 2026
Merged

Fix missing word timestamps for non-English (espeak) voices#484
remsky merged 1 commit into
remsky:masterfrom
mlevinmail:fix/non-english-word-timestamps

Conversation

@mlevinmail

Copy link
Copy Markdown
Contributor

Fixes #331 (and the non-English cases in #314).

Problem

/dev/captioned_speech returns timestamps: null for every non-English voice (Spanish, French, Italian, Hindi, Portuguese). KPipeline only attaches timed tokens on the English (misaki) path; the espeak path yields Result objects with tokens=None, so KokoroV1.generate() silently skips timestamp generation.

Insight

The model already knows the timing in every language: it predicts a duration for each phoneme (pred_dur), and the audio is rendered from exactly those durations. The espeak phoneme string keeps spaces between words, so the mapping back to words is recoverable — pred_dur[0] is BOS, pred_dur[1+i] covers phonemes[i], each unit is 2/80 s (same constants as KPipeline.join_timestamps). Summing per-character durations and splitting at spaces yields word timestamps that are exact by construction, since they're the same durations the audio was generated from.

What this PR does

  • Adds _espeak_word_timestamps() and an elif branch in KokoroV1.generate() that fires only when the pipeline's G2P is EspeakG2P and the result has no timed tokens. The English path is untouched.
  • Words espeak expands into several spoken words (e.g. 1863mil ochocientos sesenta y tres) are reconciled by re-phonemizing per word and merging the groups, so the caller still gets one timestamp per input word.
  • If the counts can't be reconciled, it emits no timestamps — exactly the previous behavior, so clients' fallbacks keep working.
  • Japanese/Chinese (non-espeak G2Ps) are deliberately excluded: their phoneme strings have no space-separated word groups to map, so they also keep the previous behavior.
  • Unit tests for the exact path, the expansion path, the give-up path, and degenerate inputs.

Validation

Running in production on a GPU deployment (v0.5.0 base). Example, Spanish ef_dora:

El 0.07-0.14 | corazon 0.19-0.67 | me 0.72-0.82 | late 0.87-1.17 | muy 1.22-1.39 | ...

versus timestamps: null before. Number expansion: "En 1863 el profesor encontro 25 mapas antiguos." returns 8 word timestamps with 1863 spanning its three spoken words (0.19–2.02 s). English output is byte-identical to before the patch. api/tests/test_kokoro_v1.py passes: 13 passed.

🤖 Generated with Claude Code

KPipeline only attaches timed tokens for English (misaki) voices, so
/dev/captioned_speech silently returned timestamps: null for Spanish,
French, Italian, Hindi and Portuguese. The model does predict a duration
for every phoneme in every language (pred_dur) - the audio is rendered
from exactly those durations - but the espeak path discarded them.

Derive word timestamps for espeak pipelines from pred_dur directly:
pred_dur[0] is BOS and pred_dur[1+i] covers phonemes[i], so summing
per-character durations and splitting at the phoneme string's spaces
yields exact word times. Words espeak expands into several spoken words
(e.g. "1863") are reconciled by re-phonemizing per word; if counts still
disagree, no timestamps are emitted (previous behavior). English is
untouched, and ja/zh (non-espeak G2Ps, no space-separated word groups)
deliberately keep the previous behavior.

Fixes remsky#331

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@remsky
remsky merged commit c0acb91 into remsky:master Jul 12, 2026
1 check passed
@remsky

remsky commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Thanks for this fix, LGTM

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.

captioned_speech endpoint is not returning the timestamps for non-english languages

2 participants