Skip to content

Add dictation: speak into the message box without a spoken reply - #36

Open
Piggidragon wants to merge 1 commit into
thecodacus:mainfrom
Piggidragon:feature/dictation
Open

Piggidragon wants to merge 1 commit into
thecodacus:mainfrom
Piggidragon:feature/dictation

Conversation

@Piggidragon

Copy link
Copy Markdown

What

Dictation: speak into the message box without a spoken reply. Voice mode is a conversation; this is for when you only want words in the box.

A microphone button sits next to the voice-mode button, which becomes the waveform icon so the two are told apart. A line above the box shows whether you are heard and the words recognised so far, and switches where they go (remembered per browser):

  • Edit first (default): each phrase is typed into the box at the cursor, spaced like a word, and the cursor moves after it. Dictate mid-sentence, fix a word by keyboard, send with Enter. Dictation keeps listening after a send.
  • Send at once: a message is sent once you stop talking and it has been transcribed. Speaking again while a phrase is still being transcribed sends both together. A draft in the box is left alone, and a failed send puts the words back in the box instead of losing them.

How

Nothing new on the server. It reuses voice mode's in-browser Silero endpointing, LiveTranscription (speculative snapshots for the live words) and POST /api/sessions/:id/voice/transcribe, so it works as soon as Voice is enabled, needs no speech synthesis and loads nothing onto the GPU.

  • web/src/use-dictation.ts: the hook. One run owns the mic, audio context and VAD; transcriptions are queued so phrases land in order. Stopping pauses the VAD first, so a sentence in progress is still delivered, then releases the mic once the queue is drained.
  • web/src/dictation.ts: insertAtCaret and cleanTranscript (Whisper answers silence with [BLANK_AUDIO] / (silence); a transcript made only of such notes is dropped, brackets inside a sentence are kept).
  • web/src/components/Dictation.tsx: button and status line.
  • Chat.tsx: the caret and draft are tracked in refs so several phrases arriving before a render each land after the last; send is split into submit, so spoken text takes the same path as typed text (client commands included).

Voice mode and dictation share the microphone: starting voice mode stops dictation. Leaving the session aborts anything not yet transcribed, so words heard in one conversation cannot be sent to another.

Testing

  • tests/dictation.test.mts (8 cases): caret insertion spacing and selection replace, silence placeholders. The root npm test now runs tests/*.test.mts instead of one named file.
  • In a real Chrome, with a fake microphone playing recorded speech and Qwen3-ASR as the recogniser: strip states, phrase typed into the box, second phrase appended, insertion at the caret, mode remembered, send-at-once request contents (no voice flag), failed send restoring the text, mic tracks released on stop, voice mode releasing dictation's mic, refused microphone reported, no native dialogs.

Not tried with a physical microphone. The 60 s cap on a single recording (same as voice mode) is not exercised.

🤖 Generated with Claude Code

A microphone button next to the voice-mode button transcribes what is said
and either types it into the message box at the cursor (edit first) or
sends it when the speaker pauses. It reuses voice mode's in-browser speech
detection and transcription route, so it needs no speech synthesis and
loads nothing onto the GPU.

The voice-mode button becomes the waveform icon so the two are told apart.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 7 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews 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: 331a72ad-f45d-4dfe-b7a9-347133511f59

📥 Commits

Reviewing files that changed from the base of the PR and between 5b67cc9 and f196825.

📒 Files selected for processing (9)
  • docs/guide/voice.md
  • package.json
  • tests/dictation.test.mts
  • web/src/components/Chat.tsx
  • web/src/components/Dictation.tsx
  • web/src/components/VoiceControl.tsx
  • web/src/dictation.ts
  • web/src/index.css
  • web/src/use-dictation.ts

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.

@Piggidragon
Piggidragon marked this pull request as ready for review September 19, 2026 20:51

This branch has not been deployed

No deployments
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