Skip to content

feat(capsule): 录音开始播放合成提示音 + 录音与输入设置开关#560

Merged
appergb merged 2 commits into
betafrom
feat/audio-cue-on-record
May 31, 2026
Merged

feat(capsule): 录音开始播放合成提示音 + 录音与输入设置开关#560
appergb merged 2 commits into
betafrom
feat/audio-cue-on-record

Conversation

@appergb
Copy link
Copy Markdown
Collaborator

@appergb appergb commented May 31, 2026

User description

背景 / 目标

新增「音频播放提醒」功能:按下录音热键开始录音时,用一段即时合成的提示音提醒用户「已开始录音」。听写场景里热键是隐形的,加一个开始音能明确告诉用户录音真的起来了(业界听写类 App 普遍如此)。

  • (a) 按下后通过播放音频提醒 ✅
  • (b) 支持播放音频 / 关闭音频 ✅(playRecordStartCue / stopAudioCue 两个操作 + 设置开关)
  • (c) 合成音频、实现播放与关闭、提供提示 ✅(Web Audio 合成,不打包任何音频文件;设置页含说明 + 「试听」按钮)

改动

前端

  • lib/audioCue.ts(新):Web Audio API 即时合成上升双音(A5→C#6)。
    • playRecordStartCue() 播放、stopAudioCue() 关闭。
    • 纯函数 recordStartCueTones() / cueTotalDurationMs() 便于单测(audioCue.test.ts)。
    • suspended 的 AudioContext 先 resume() 再排期(避免 WKWebView/WebView2 上排到冻结时钟);无 Web Audio 时静默降级,绝不抛进录音主流程。
  • components/Capsule.tsx:在 capsule 窗口监听 capsule:state,检测进入 recording 的边沿就播放、离开就停。capsule 窗口始终存活并恒收事件,因此独立于 showCapsule——胶囊隐藏时仍会响。开关通过 getSettings() + prefs:changed 实时同步。
  • pages/settings/RecordingInputSection.tsx:「录音与输入」里新增开关 + 说明 + 「试听」按钮。
  • lib/types.tsUserPreferences.audioCueOnRecord: boolean
  • i18n 五语补齐(en / zh-CN / zh-TW / ja / ko)。

后端(持久化)

  • src-tauri/src/types.rsUserPreferences 与持久化用的 UserPreferencesWire 都新增 audio_cue_on_record#[serde(default = "default_true")] —— 默认开启,老 preferences.json 缺字段也按开启。两处 Default impl 与 Wire→Prefs 转换同步更新。
  • 单测:missing_audio_cue_on_record_pref_defaults_to_enabledaudio_cue_on_record_pref_round_trips_explicit_false(证明设置关闭后存盘往返不丢字段)。

设计取舍

  • 用 Web Audio 合成而非打包音频文件:零新增二进制资源、跨三平台走 webview、契合「合成音频」要求。
  • 默认开启:这是「提醒」功能,开着才有意义;用户可随时在设置关闭,关闭状态经单测保证持久化。
  • 不耦合 muteDuringRecording:提示音是 UI 反馈,单独由 audioCueOnRecord 控制。

影响面(GitNexus 影响分析)

UserPreferences upstream 直接引用 14 处,全部是 commands.rs 里的测试,0 条执行流受影响;且所有构造点都用 ..Default::default(),新增带默认值的字段向后兼容。实际风险:低。

测试计划

已在本地验证(与 CI cross-platform 任务一致):

  • npm run build(tsc + vite)通过
  • cargo test --lib audio_cue → 2 passed
  • npx tsx src/lib/audioCue.test.ts → all assertions passed
  • 版本号五处一致(本 PR 不动版本,发版在后续 bump 提交)

手动 QA(建议在合并后的 beta 包上覆盖):

  • 默认开启时按下热键能听到提示音;连按不叠音;离开 recording 不留尾音
  • 设置关闭后不再响,重启 App 后仍为关闭(持久化)
  • 「试听」按钮可即时听到效果
  • 隐藏胶囊(showCapsule=off)时提示音仍会响
  • mac / Windows / Linux 三端 webview 均可发声(autoplay 策略)

PR Type

Enhancement, Tests


Description

  • Add recording start chime

  • Expose toggle and preview

  • Persist new user preference

  • Cover audio cue behavior


Diagram Walkthrough

flowchart LR
  P["User preferences"]
  S["Recording settings UI"]
  C["Capsule window"]
  A["Web Audio cue"]
  T["Tests and fixtures"]
  P -- "toggle persists" --> S
  S -- "save preference" --> P
  S -- "preview sound" --> A
  P -- "prefs:changed / getSettings" --> C
  C -- "enter recording" --> A
  A -- "tone generation" --> T
Loading

File Walkthrough

Relevant files
Configuration changes
3 files
types.rs
Persist recording cue preference in backend                           
+36/-0   
ipc.ts
Default mock settings include audio cue                                   
+1/-0     
types.ts
Add audio cue preference to types                                               
+3/-0     
Enhancement
8 files
Capsule.tsx
Play cue on recording transitions                                               
+51/-3   
en.ts
Add English recording cue strings                                               
+3/-0     
ja.ts
Add Japanese recording cue strings                                             
+3/-0     
ko.ts
Add Korean recording cue strings                                                 
+3/-0     
zh-CN.ts
Add simplified Chinese cue labels                                               
+3/-0     
zh-TW.ts
Add traditional Chinese cue labels                                             
+3/-0     
audioCue.ts
Synthesize recording start chime in Web Audio                       
+162/-0 
RecordingInputSection.tsx
Add recording cue toggle and preview                                         
+29/-0   
Tests
2 files
audioCue.test.ts
Test cue tone timing and shape                                                     
+49/-0   
stylePrefs.test.ts
Update preference fixture for new field                                   
+1/-0     

按下录音热键进入 recording 状态时,capsule 窗口用 Web Audio API 即时合成
一段上升双音提示音,提醒「已开始录音」;离开 recording 即停。提示音独立于
showCapsule —— 胶囊隐藏时仍会响。

- 新增 audioCueOnRecord 偏好(默认开启),可在「录音与输入」设置里开关,
  并提供「试听」按钮即时听效果。
- 后端 UserPreferences / UserPreferencesWire 持久化该字段并默认 true,
  老配置缺字段按开启;补两条单测(缺字段默认开启 + 显式 false 往返保真)。
- 提示音合成抽成 lib/audioCue.ts:playRecordStartCue / stopAudioCue 两个
  操作 + 纯函数音符规划(recordStartCueTones / cueTotalDurationMs),附
  .test.ts。suspended 的 AudioContext 先 resume 再排期,无 Web Audio 时静默降级。
- i18n 五语(en / zh-CN / zh-TW / ja / ko)补齐 label / desc / preview。
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

PR Reviewer Guide 🔍

(Review updated until commit 2784e97)

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis ❌

6 - Not compliant

Non-compliant requirements:

  • 录音热键短按/长按兼容模式
  • 直接输入功能
  • 关闭大模型二次优化的开关
  • 基于正则的句子优化
  • 整体性能/体感提升
  • 简化模型与接入配置
  • 本地语音识别可选开关
  • 修复文本输入区插入错误的问题
⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Spurious cue on mount

The cue is triggered whenever state is recording and the previous ref is not recording, including the first render. If the capsule window is recreated or the component mounts while recording is already in progress, users will hear the start sound even though no new recording just began.

// 提示音触发:检测 capsule 状态进入 recording 的边沿就播放(提醒「已开始录音」);
// 离开 recording 则停掉,避免连按热键时残留尾音。独立于 showCapsule —— 胶囊隐藏也会响。
useEffect(() => {
  const prev = prevStateRef.current;
  prevStateRef.current = state;
  if (!isTauri) return;
  if (state === 'recording' && prev !== 'recording') {
    if (audioCueEnabledRef.current) playRecordStartCue();
  } else if (state !== 'recording' && prev === 'recording') {
    stopAudioCue();
  }
}, [state]);

suspended 的 AudioContext 先 resume 再排期,若等待 resume 期间录音已结束
(stopAudioCue)或有新一轮播放,旧的 resume 回调不再排期,避免「录音已停、
提示音晚到」。引入 playGeneration 代号:stopAudioCue 自增并停节点;
scheduleCueVoices 只 stopVoices 不动代号;deferred 播放回调比对代号决定是否排期。
@github-actions
Copy link
Copy Markdown

Persistent review updated to latest commit 2784e97

@appergb appergb merged commit 4bc94ec into beta May 31, 2026
4 checks passed
@appergb appergb deleted the feat/audio-cue-on-record branch May 31, 2026 06:01
appergb pushed a commit that referenced this pull request May 31, 2026
本次只动版本号,功能改动已在 #560 落盘:
- 按下录音热键进入 recording 即播放 Web Audio 合成提示音,提醒「已开始录音」
- 新增 audioCueOnRecord 开关(默认开启),录音与输入设置可关闭 + 试听
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant