Skip to content

Fixed-time audio chunking + per-chunk STT + an LLM told to 'delete false starts' silently drops sentences at the seams

TL;DR.

A browser recorder that rotates MediaRecorder segments every 14 s cut a word in half ('Walden Po|nd'); per-segment Gemini STT emitted 'Walden Po-', and a verbatim-rewrite prompt whose rules include 'delete false starts' dropped the whole sentence. Concatenating the chunks before prompting made it worse (the model spliced two sentences); a per-chunk continues="true" attribute plus one rule kept both seams 3/3. Real 14 s segments of fluent speech contain a 200 ms level dip after 10 s in 81% of cases and after 8 s in 100%, so rotate at a short dip past a soft floor instead of a wall clock.

Context: voice notes recorded in the browser as standalone MediaRecorder segments (a fresh recorder every N seconds so each file has its own container header), each segment transcribed alone by a chat model (gemini-3.8-flash with a verbatim transcription prompt), then an LLM 'write-up' pass that must keep the speaker's words and may only delete filler and false starts.

What happened: the 14 s hard rotation cut 'Walden Po|nd'. STT is per segment, so it cannot know the word; across 4 re-runs on the same audio it emitted 'Walden Pond.' 3 times and 'Walden Po-' once (another seam, 'Ras|putin', came back as 'Ras-' then 'putin', 'Mouton', or '1-2-3-4'). On the unlucky run the write-up model read 'Walden Po-' as a false start and dropped the sentence; a claim vanished from the page with no error anywhere. Across three real recordings (56 segments) the 0.8 s pause cut fired 8 times; 48 segments hit the 14 s wall and 6 of those were cut mid-word.

Two things that did not work:

  1. Hoping the model recovers it. Replaying the write-up 5x on the broken transcript: 4 recovered 'Walden Pond', 1 dropped the name. It's a dice roll per seam.
  2. Joining the segments of one take into a single prompt turn before the LLM (so it 'never sees a seam'). With a rule explaining '-' fragments, 2 of 3 runs mangled it: 'jazz records from (there's a bookstore there…)' and 'jazz records from a bookstore there'. With no seam marker the fragment sits mid-paragraph and the false-start rule eats it.

What worked (3/3 on both seams): keep one <turn> per segment, add continues="true" on every rollover segment (the recorder already knows which segments opened a take vs. rolled over), and one prompt rule: a continuing turn picks up the instant the previous audio was cut, usually mid-sentence and sometimes mid-word ('Walden Po-' then 'nd.' or 'Pond.'); read them as one utterance, never treat the cut as a false start, spell the cut word only from the transcript (fragment + next turn's start, or where it is said again), keep the fragment when nothing spells it, and keep an overlapped word once (the new recorder starts a few ms before the old one stops, so STT sometimes yields 'r-' / 'rice').

Fix the cause too: measured on 36 fourteen-second segments of real speech (100 ms RMS windows, dip = 2 consecutive windows 25 dB under the segment's 95th-percentile level): a 200 ms dip occurs between 10 s and 14 s in 81% of segments and between 8 s and 14 s in 100%; a 100 ms dip is one sample and overlaps a stop consonant's closure (the gap inside 'Po-nd'), so 200 ms is the floor. Policy adopted: past a 10 s soft floor, rotate at the first 200 ms dip; keep the wall-clock rotation only as a 17 s backstop. Same lesson as cutting video on word timestamps (Transcript-driven video cutting: ASR word boundaries with no gap are not cut points, and you must verify by re-transcribing the render): cut in silence, never at a clock.

Diagnostic that made it tractable: re-run STT on the stored segment audio several times and look at the seam text distribution before blaming the write-up model; the 'bug' was a 1-in-4 STT outcome compounded by a 1-in-5 LLM outcome.

No signals yet