Skip to content

Fill voice-mode silence with localized fillers and work sounds - #32

Draft
Piggidragon wants to merge 5 commits into
thecodacus:mainfrom
Piggidragon:feature/voice-thinking-fillers
Draft

Piggidragon wants to merge 5 commits into
thecodacus:mainfrom
Piggidragon:feature/voice-thinking-fillers

Conversation

@Piggidragon

@Piggidragon Piggidragon commented Sep 16, 2026

Copy link
Copy Markdown

Why

In voice mode, once the single "Let me think about that" phrase has played, nothing is heard while the agent reasons or runs tools. Long silences feel sterile and make it hard to tell whether anything is still happening.

What

Spoken fillers, tied to what is happening

Nothing plays on a timer alone. Wordless murmurs are not used: Chatterbox renders Hmm. and lone words like Okay. twice. The agent already announces each tool call itself (voice-first instructions), so fillers do not repeat that.

  • Acknowledgement 0.3 s after a request: Mal sehen. for a question (transcript ends in ?), Alles klar. / Mach ich. otherwise. One- and two-word replies (Danke) get none, and at most one plays every 15 s. It replaces the live "let me think" notice for that turn.
  • Slow tool after 6 s, naming what is still running where the call shows it: Die Tests laufen noch., installs, builds, commands, page loads, searches. slowFiller() in web/src/tool-kind.ts does the classification.
  • Tool result: Das hat nicht geklappt. 0.8 s after a failed call (at most twice per turn). Okay, mal sehen. 1.2 s after a tool stretch of 4 s or more, if the agent is quiet.
  • Still on it only after 15 s of silence, then after 30 s and 45 s.
  • A reply that arrives while a filler plays waits for it to finish.
  • The phrase tables in web/src/voice-phrases.ts cover en, de, es, fr, it, pt (BR), ru, zh, ja, ko, hi and ar. The thinking and compaction notices use the same tables. First-person phrases are worded gender-neutrally where the language marks gender (hi, ru, ar), since the voice may be either.
  • Language: the saved input language is used. With auto-detect, the browser's language is used instead. A language without a table gets wordless murmurs only, never guessed wording, and its status notices stay in English, as before.
  • Rendering happens once, on the portal. server/src/voice-clips.ts renders missing clips in the background when voice is set up (/voice/connect), its settings are saved or the portal starts. It pauses while live speech or transcription requests run (5 s quiet window) and keeps a managed runtime's lease while a batch runs. Clips are stored as PCM under DATA_DIR/voice-clips/<version>/<sha256(text)>.pcm. version is a fingerprint of the speech settings and the voice preset or Aria reference, so a voice or language change renders a new set. The four most recently used sets are kept. Auto-detect languages that clients asked for are remembered and kept rendered.
  • Voice mode only downloads clips. GET /api/voice/clips?languages=… returns the phrase list with a ready flag and the status notices in the voice language. GET /api/voice/clips/:version/:hash serves a clip as immutable. The browser loads the ready clips and checks back while the rest render. It never renders speech itself.
  • The phrase tables live in server/src/voice-phrases.ts. The speech handler's upstream request moved into upstreamSpeech(), which the handler and the renderer share.
  • Barge-in, compaction and End fade out a filler that is playing. VOICE_STATUS_SPEECH=false and the sequential pipeline turn all spoken fillers off.

Work sounds (follow the existing interface-sounds toggle)

  • web/src/work-sounds.ts synthesizes quiet sounds with WebAudio, so there are no downloads. There are irregular typing runs while a command or edit runs, and a page rustle when a read, search or browser call starts. Both play only during Thinking, never over speech.
  • Two soft voiceCue tones mark a tool the listener waited on (≥ 1.5 s) finishing. The failure tone is lower.

Refactors

  • web/src/tool-kind.ts: tool classification is shared with VoiceToolActivity.

Tests

  • tests/hands-free.test.mts: growing murmur gaps; a pre-rendered thinking phrase replaces live synthesis; barge-in aborts a filler; statusSpeech: false silences fillers; tool announcements (quick tools skipped, once per kind per turn, quiet window after speech); German compaction notices.
  • tests/voice-clips.test.mts: clips render once and survive a restart, rendering waits for live speech, a voice change mid-batch, disabled status speech, path safety, pruning, remembered languages.
  • tests/voice.test.mts: clip list in the requested language, immutable serving from disk, version changes with the voice.
  • tests/voice-fillers.test.mts: silence trimming; every language table is complete; language resolution; tool classification.
  • web tsc -b + vite build pass. The hands-free, fillers, speech-pipeline, voice, pcm-stream and voice-panels suites pass.

Not yet checked by ear. How natural the murmurs sound depends on the TTS backend, and the non-English phrases are worth a check by native speakers. Phrases, gains and timings are constants and easy to tune.

🤖 Generated with Claude Code

While the agent reasons or runs tools, voice mode went quiet after its single
"Let me think" phrase. Short murmurs ("Hmm...", "Mhm.") are now rendered once in
the selected voice when voice starts and played locally during long thinking
turns, spaced further apart the longer the turn runs. Barge-in, compaction and
End cut them off; VOICE_STATUS_SPEECH=false and the sequential pipeline disable
them.

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

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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.

Voice mode now fills long work with more than murmurs. Tool announcements
("Ich schau kurz im Browser nach.") play once per kind per turn for tools still
running after a second. Long turns mix in "still on it". The thinking phrase
plays from pre-rendered clips. Spoken fillers and the thinking and compaction
notices follow the input language (browser language on auto-detect) for twelve
languages. Other languages fall back to wordless murmurs only.

With interface sounds on, synthesized typing, a page rustle and completion
tones accompany tool calls. Clips render only between turns and are cached per
voice and language across voice restarts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Piggidragon Piggidragon changed the title Murmur during long voice-mode thinking instead of staying silent Fill voice-mode silence with localized fillers and work sounds Sep 16, 2026
Piggidragon and others added 3 commits September 17, 2026 00:04
The browser rendered every filler clip again on each page load, spending about
20 seconds of speech runtime per language. The portal now renders the clips in
the background when voice is set up, its settings are saved or the portal
starts. Rendering pauses while live speech or transcription runs. Clips live
under DATA_DIR/voice-clips, keyed by a fingerprint of everything that shapes
the voice. Voice mode only downloads them, as immutable responses, and picks up
the rest as rendering finishes.

The phrase tables move to the server, which also serves the status notices in
the voice language. The browser no longer renders or chooses wording.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Murmurs played on a timer regardless of context, and speech runtimes render
"Hmm." as two hums. The agent already announces its tool calls, so generic
tool announcements repeated it.

Fillers now each have a cause:
- an acknowledgement 0.3 s after a request ("Mal sehen." for a question,
  "Okay." otherwise), replacing the live thinking notice for that turn
- a note on what is still running when a tool takes over 6 s (tests,
  install, build, command, page load, search)
- a reaction to a failed call, or after a long tool once the agent goes quiet
- "still on it" only after 15 s of silence

A reply that arrives during a filler waits for it to finish. Clips for phrases
no longer in the tables are removed from disk.

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

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