Skip to content

feat(dictate): the microphone closes when you stop talking - #58

Merged
hannesreinsch merged 2 commits into
mainfrom
feat/the-mic-closes-when-you-stop-talking
Sep 9, 2026
Merged

feat(dictate): the microphone closes when you stop talking#58
hannesreinsch merged 2 commits into
mainfrom
feat/the-mic-closes-when-you-stop-talking

Conversation

@hannesreinsch

Copy link
Copy Markdown
Collaborator

"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 and take inspiration from similar apps."

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:

  • the gesture is a tap, not a held key, so nothing is telling the microphone you are still there;
  • this operator thinks mid-sentence — the pauses that produced every punctuation bug in this repo were real speech behaviour, not idleness.

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 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.0no opinion — which is well above any floor, so 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.

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. 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.

Gate

206 passed, ruff clean, mypy clean. The silence path is driven through the real listen_loop with no tap and the hold cap off, so only silence can have ended it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P7oJz8M9QzsdJimoM318cj

hannesreinsch and others added 2 commits September 9, 2026 15:17
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
@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 54 minutes.

Check out review usage here.

View limit details

Limit 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.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 9151344e-499c-4f11-a408-911646862d21

📥 Commits

Reviewing files that changed from the base of the PR and between f554f4d and 9a77bd1.

📒 Files selected for processing (2)
  • murmurflow/dictate.py
  • tests/test_murmurflow.py

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hannesreinsch
hannesreinsch merged commit 8ae8b1d into main Sep 9, 2026
2 checks passed
@hannesreinsch
hannesreinsch deleted the feat/the-mic-closes-when-you-stop-talking branch September 9, 2026 13:33
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