Skip to content

Redesign live subtitles: roll-up display + provisional simultaneous translation - #10

Merged
ycosine merged 1 commit into
mainfrom
agent/live-subtitle-rollup
Jul 16, 2026
Merged

Redesign live subtitles: roll-up display + provisional simultaneous translation#10
ycosine merged 1 commit into
mainfrom
agent/live-subtitle-rollup

Conversation

@ycosine

@ycosine ycosine commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Problems

  1. Two-line clamp hid the newest words. The previous -webkit-line-clamp: 2 anchored the visible window to the head of the text, so once a live utterance wrapped past two lines, everything currently being spoken was clipped out of view.
  2. Bilingual lines were misaligned by a full sentence. ElevenLabs only commits an utterance after ~0.8s of VAD silence, and translation only started at commit — so the translation line always showed the previous sentence while the original line streamed the current one. (Checked the ElevenLabs realtime docs: there is no documented way to force earlier commits under commit_strategy=vad, so the fix has to happen on our side.)

Design

Broadcast-style roll-up captions (CEA-608 style), built around how people actually read live text:

  • Tail-anchored two-line window — each line is a fixed two-line viewport over a growing scroller, translated up so the freshest words always sit at the bottom edge. Rolling up animates (180ms); content resets snap instead of sliding down.
  • No reflow of read text — live mode left-aligns inside a fixed-width block, so already-rendered words never re-center or rewrap when new words stream in.
  • Continuous transcript stream — the original line renders previous + current utterance as one joined tail, so nothing jumps at the commit boundary.
  • Provisional simultaneous translation — a bounded slice of the growing partial is re-translated on a 1.2s throttle and shown immediately; when the committed cue's real translation streams in (and only once it's final), it takes over. Provisional units are marked transient and bypass the translation cache.

Testing

  • New pure-helper module live-text.ts with 10 unit tests (tail/word-boundary, transcript join, translation slice); full content-script suite passes (35 tests).
  • type-check, lint, and full pnpm build pass.

🤖 Generated with Claude Code

The two-line clamp from the previous attempt anchored the window to the
head of the text, so once an utterance wrapped past two lines the newest
words (the ones matching the audio) were hidden. And the translation
line only started after ElevenLabs committed an utterance on VAD
silence, leaving it a full sentence behind the original.

Display: each line is now a fixed two-line viewport over a growing
scroller that is translated up so the freshest words always sit at the
bottom edge, animating on roll-up and snapping on resets. Live mode
left-aligns inside a fixed-width block so rendered words never rewrap,
and the original line renders previous + current utterance as one
continuous transcript stream across commits.

Alignment: a bounded slice of the growing partial is re-translated on a
1.2s throttle (transient units that bypass the translation cache) and
shown as a provisional translation until the committed cue's real
translation streams in, so both lines track the same utterance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ycosine
ycosine merged commit f392a2f into main Jul 16, 2026
2 checks passed
@ycosine
ycosine deleted the agent/live-subtitle-rollup branch July 16, 2026 15:57
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