Preserve word-level timing on spelling edits

When the edited text has the same word count as the original (e.g. fixing
"Whisper" to "wisper"), each word keeps its original start/end timestamps.
Only falls back to segment-level timing when words are added or removed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-03-20 22:21:52 -07:00
parent 727107323c
commit 67fc23e8aa

View File

@@ -60,21 +60,28 @@
function finishEditing(segmentId: string) { function finishEditing(segmentId: string) {
const trimmed = editText.trim(); const trimmed = editText.trim();
if (trimmed) { if (trimmed) {
// Update the segment text and rebuild words from the edited text.
// The display renders segment.words, so we must update them too.
segments.update(segs => segs.map(s => { segments.update(segs => segs.map(s => {
if (s.id !== segmentId) return s; if (s.id !== segmentId) return s;
// Rebuild words from the edited text, preserving timing from the const newWordTexts = trimmed.split(/\s+/);
// original segment boundaries (individual word timing is lost on edit) let newWords;
const newWords = trimmed.split(/\s+/).map((word, widx) => ({ if (newWordTexts.length === s.words.length) {
id: `${s.id}-word-${widx}`, // Same word count (e.g. spelling fix) — preserve each word's timing
segment_id: s.id, newWords = s.words.map((w, widx) => ({
word, ...w,
start_ms: s.start_ms, word: newWordTexts[widx],
end_ms: s.end_ms, }));
confidence: 1.0, } else {
word_index: widx, // Word count changed — fall back to segment-level timing
})); newWords = newWordTexts.map((word, widx) => ({
id: `${s.id}-word-${widx}`,
segment_id: s.id,
word,
start_ms: s.start_ms,
end_ms: s.end_ms,
confidence: 1.0,
word_index: widx,
}));
}
return { return {
...s, ...s,
text: trimmed, text: trimmed,