feat(dictate): the microphone closes when you stop talking - #58
Merged
Conversation
Reported as "there was a break before, but no punctuation", and it is the cost the last commit named out loud rather than a new defect. A mark rides on the word in front of it, and `stable_prefix` will not type the mark on a word still touching the end of the audio — a pause is how whisper decides a sentence ended, and it takes that decision back the moment the speaker carries on. So the word landed bare and nothing could ever put the mark on afterwards: the word is on screen and there is no un-type. A LATER pass answers the question the earlier one could not. If the word carrying the mark is no longer at the end of the transcript — real speech follows it, and whisper STILL ends the sentence there — the mark was decided WITH the following audio, which is the same test every other word passes before it is typed. `missing_mark` returns it, joined to its word with no space in front, and only ever in the same breath as the word that proves it. So it can never be the lone full stop of #55: no confirming word, no mark. `_reached` is split out of `stream_tail` because both now ask the same question about the same two sequences — where does the screen END inside this transcript — and two answers to that would drift apart word by word. Driven through the reported sequence, the streamed text is now identical to the whole-clip transcript, punctuation included: I did not say the three times. I did, however, say really three times. `_drive_stream` in the tests is the loop's four calls in its own order, so the three earlier reports are replayed against it too and none of them regressed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P7oJz8M9QzsdJimoM318cj
"We should close the microphone after not talking for 15 seconds or something like that. I don't know what is a good timing, you have to decide that yourself." So: fifteen seconds, and the number is the whole decision. Dictation apps that stop on silence sit around two to three, and two to three is WRONG HERE. The gesture is a TAP, not a held key, so nothing is telling the microphone you are still there; and this operator thinks mid-sentence — the pauses that produced every punctuation bug in this file were real. A clip cut at three seconds would have ended half of them mid-thought, with the rest of the sentence spoken into a closed microphone. That failure is worse than the one being fixed, because a forgotten microphone loses nothing and a truncated sentence loses the sentence. Fifteen is longer than any pause measured here and still closes a forgotten one in a quarter of a minute rather than two. `tail_dbfs` is the reader `wave` cannot be: while ffmpeg is appending, the RIFF header still holds the lengths it was born with — zero — so every header-respecting reader sees an empty file. Every byte past the header is a sample, so "the last fifteen seconds" is a seek from the END and nothing else. A clip too short to have been quiet that long returns 0.0, "no opinion", which is well above any floor: a fresh recording can never read as silence and close itself. `peak_dbfs` and it share one `_peak_dbfs`, so they cannot disagree about what quiet is. It rides the watchdog that was already there, so it is one loop with two reasons to fire and one `claim()` at the end of both. `silenceStop` moves it, 0 switches it off, and the 120s `maxHold` cap stays as the backstop for a microphone left open in a silent room the floor never quite reaches. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P7oJz8M9QzsdJimoM318cj
|
Warning Review limit reachedNext included review available in 54 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fifteen seconds, and the number is the whole decision.
Dictation apps that stop on silence sit around two to three. Two to three is wrong here:
A clip cut at three seconds would end half his sentences mid-thought, with the rest spoken into a closed microphone. That failure is worse than the one being fixed: a forgotten microphone loses nothing, a truncated sentence loses the sentence.
Fifteen is longer than any pause measured here, and still closes a forgotten microphone in a quarter of a minute instead of two.
tail_dbfs— the readerwavecannot beWhile ffmpeg is appending, the RIFF header still holds the lengths it was born with — zero — so every header-respecting reader sees an empty file.
Every byte past the header is a sample, so "the last fifteen seconds" is a seek from the END and nothing else.
A clip too short to have been quiet that long returns
0.0— no opinion — which is well above any floor, so a fresh recording can never read as silence and close itself.peak_dbfsand it share one_peak_dbfs, so they cannot disagree about what quiet is.Where it lives
It rides the watchdog #56 already added, so it is one loop with two reasons to fire and one
claim()at the end of both.silenceStopmoves it,0switches it off, and the 120smaxHoldcap stays as the backstop for a microphone left open in a silent room the floor never quite reaches.Gate
206 passed, ruff clean, mypy clean. The silence path is driven through the reallisten_loopwith no tap and the hold cap off, so only silence can have ended it.🤖 Generated with Claude Code
https://claude.ai/code/session_01P7oJz8M9QzsdJimoM318cj