Skip to content

feat(voice): an optional sound tells you dictation is listening - #34265

Closed
screen-gd wants to merge 1 commit into
pingdotgg:maria/redesign/6-workspace-panesfrom
screen-gd:feat/voice-recording-cue
Closed

screen-gd wants to merge 1 commit into
pingdotgg:maria/redesign/6-workspace-panesfrom
screen-gd:feat/voice-recording-cue

Conversation

@screen-gd

Copy link
Copy Markdown
Contributor

Problem

Dictation gives no sound when recording starts, so you have to watch the composer to know it is listening.

Change

Voice settings get an optional Sound cue, off by default, with seven sounds to pick from. Picking a sound or turning the switch on previews it. Available on web and desktop.

The cue plays and finishes before capture begins, so it never lands in the recording or the live stream:

 start()
   prepare transcriber, open microphone
+  beforeRecord()          # web: play cue, wait for it to end (max 1s)
   recorder.record()
   state -> recording

Mobile does not pass beforeRecord, so it is unchanged. Retrying saved audio skips this step and stays silent.

The sounds are unchanged from Hex. Its MIT license permits reuse with attribution; the notice ships in apps/web/src/assets/speech-cues/LICENSE and the web and desktop third-party notices.

Scope and approval

Split out of #32484 as the review there asked. The model folder restore in that PR is dropped because #34096 already covers it. No maintainer approval for the sound cue is linked yet.

Verification

  • controller.test.ts: the five-minute-cap case now asserts beforeRecord runs before recorder.record(). It failed before the change and passes after. The file and settings.test.ts pass (87 tests).
  • Format, lint and knip pass on the changed files; typecheck passes for contracts, client-runtime and web.
  • Not checked: the Voice settings and speech hook browser tests (Playwright browser not installed locally; CI runs them), audible playback, and before/after screenshots of the settings row.

Created with Claude Opus 5.5 in Claude Code, through T3 Code.

Plays one of Hex's start sounds when recording is about to begin, off by
default, on web and desktop. The controller waits for the cue to finish
before capture starts so the sound stays out of the recording and live
stream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Nov 11, 2026
audio.removeEventListener("ended", finish);
resolve();
};
const limit = setTimeout(finish, CUE_WAIT_LIMIT_MS);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High speech/recordingCue.ts:50

When cue playback is delayed or stalls, playRecordingCue resolves after 1 second while the audio can still play into the recording and live transcription. The timeout only calls finish, which does not stop the audio; pause and reset it on the timeout path before resolving.

-  const limit = setTimeout(finish, CUE_WAIT_LIMIT_MS);
+  const limit = setTimeout(() => {
+    audio.pause();
+    audio.currentTime = 0;
+    finish();
+  }, CUE_WAIT_LIMIT_MS);
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/speech/recordingCue.ts around line 50:

When cue playback is delayed or stalls, `playRecordingCue` resolves after 1 second while the audio can still play into the recording and live transcription. The timeout only calls `finish`, which does not stop the audio; pause and reset it on the timeout path before resolving.

@macroscopeapp

macroscopeapp Bot commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — Adds an off-by-default dictation start sound with selectable previews, preserving existing silent recording behavior. The reported playback-timeout issue remains subject to the separate correctness blocking gate.

Needs human approval because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge

Copy link
Copy Markdown
Member

Thanks for this. #33097 makes the same change and is the one being kept.

The overlapping #33097 also adds a cue before dictation starts, and it stops playback when the wait expires. That is the deciding difference: this version releases the wait without stopping the sound, so delayed playback can enter the recording.

Your off-by-default switch and selectable previews remain useful differences. Those could be proposed on top of the shared cue implementation rather than maintaining a second playback path.

Closing as a duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants