From 77333223269c9a48f308a64c1edc820f8b179280 Mon Sep 17 00:00:00 2001 From: Aditya Garud <153842990+yashranaway@users.noreply.github.com> Date: Sat, 17 Oct 2026 17:31:25 +0000 Subject: [PATCH] fix(desktop-gpui): count Unicode characters at caption boundaries --- apps/desktop-gpui/src/transcription.rs | 51 +++++++++++++++++++------- crates/verify/expectations.toml | 7 ---- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/apps/desktop-gpui/src/transcription.rs b/apps/desktop-gpui/src/transcription.rs index 3240295a91b..9f23b435244 100644 --- a/apps/desktop-gpui/src/transcription.rs +++ b/apps/desktop-gpui/src/transcription.rs @@ -1809,7 +1809,7 @@ fn caption_boundary_word_is_weak(word: &CaptionWord) -> bool { .collect::() .to_lowercase(); - normalized.len() <= 1 + normalized.chars().count() <= 1 || matches!( normalized.as_str(), "an" | "as" @@ -2313,21 +2313,44 @@ mod tests { #[test] fn caption_word_chunks_do_not_end_on_short_connector_when_more_words_follow() { - let words = [ - "This", "is", "where", "we", "record", "I", "want", "clean", "captions", - ] - .iter() - .enumerate() - .map(|(index, text)| word(text, index)) - .collect::>(); + for connector in ["I", "à", "à,", "a\u{300}", "日"] { + let words = [ + "This", "is", "where", "we", "record", connector, "want", "clean", "captions", + ] + .iter() + .enumerate() + .map(|(index, text)| word(text, index)) + .collect::>(); - let chunks = caption_word_chunks(&words); + let chunks = caption_word_chunks(&words); - assert_eq!( - caption_text_from_words(chunks[0]), - "This is where we record I want" - ); - assert_eq!(caption_text_from_words(chunks[1]), "clean captions"); + assert_eq!( + caption_text_from_words(chunks[0]), + format!("This is where we record {connector} want") + ); + assert_eq!(caption_text_from_words(chunks[1]), "clean captions"); + } + } + + #[test] + fn caption_word_chunks_merge_short_tail_starting_with_connector() { + for connector in ["I", "à", "à,", "a\u{300}", "日"] { + let words = [ + "These", "captions", "should", "stay", "grouped", "together", connector, "Paris", + ] + .iter() + .enumerate() + .map(|(index, text)| word(text, index)) + .collect::>(); + + let chunks = caption_word_chunks(&words); + + assert_eq!(chunks.len(), 1, "connector {connector}"); + assert_eq!( + caption_text_from_words(chunks[0]), + format!("These captions should stay grouped together {connector} Paris") + ); + } } // -- Model paths ---------------------------------------------------------- diff --git a/crates/verify/expectations.toml b/crates/verify/expectations.toml index 32dedfe7a42..d4d5b4b77b3 100644 --- a/crates/verify/expectations.toml +++ b/crates/verify/expectations.toml @@ -179,13 +179,6 @@ bound = { count = 1, missing = 30 } reason = "NEW: same as editing/mapping/duration-covered, end to end: a 1 s fullscreen text at 5.4 s and the clip trimmed to 3.2 s give a 4.2 s timeline, but the export stops at the first unmapped frame: 96 frames instead of 126, and the text card is never rendered" link = "" -[[xfail]] -case = "captions/app/segmentation/unicode" -class = "caption-segments" -bound = { count = [1, 3] } -reason = "NEW (minor): caption chunking decides that a boundary word is a weak one-letter word with String::len() (bytes), so a one-letter word outside ASCII such as the French preposition 'à' is not weak and a caption can end on it (apps/desktop-gpui/src/transcription.rs caption_boundary_word_is_weak). The case reports the first three failing token streams; an unexpected error from the product would add a problem beyond them. Repro: cargo test --manifest-path apps/desktop-gpui/Cargo.toml --bin cap-gpui segmentation_matches_reference_unicode -- --nocapture" -link = "" - [[xfail]] case = "captions/legacy-migration/ends-at-timeline-end" class = "caption-migration"