fix(audio-cue): recover when resume() is rejected or wakes non-running#757
Open
appergb wants to merge 1 commit into
Open
fix(audio-cue): recover when resume() is rejected or wakes non-running#757appergb wants to merge 1 commit into
appergb wants to merge 1 commit into
Conversation
Long sessions park the shared AudioContext in 'suspended' / WebKit 'interrupted' after the system audio session is repeatedly preempted by ASR and recording. The earlier fix only recreated a 'closed' context: a rejected resume() was swallowed and a resume() that resolved without reaching 'running' scheduled voices on a frozen currentTime, both of which leave the start cue permanently silent until the app restarts. Treat both "won't wake" states as recoverable — discard the dead context and retry once on a fresh one, bounded to avoid infinite recreation. The decision is extracted into the pure, unit-tested cueActionAfterResume.
Contributor
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User description
问题
长时间使用后,「开始录音」提示音在 macOS 上会莫名消失,重启 App 才恢复。
根因
提示音是前端 Web Audio 即时合成(
src/lib/audioCue.ts),后端不参与。长时间运行中,本地 ASR / 录音反复抢占系统音频会话,WKWebView 的共享AudioContext被系统推进suspended或 WebKit 非标准的interrupted。此前的修复(b4636f9)只在closed时重建,漏掉了真实的退化路径:resume()被拒 → 旧逻辑.catch(() => undefined)把失败静默吞掉,不重建、不重试;resume()名义 resolve 但 ctx 仍非running→ 在冻结的currentTime上排期,oscillator 排到过去时刻,静默且堆积节点。两条路都让提示音永久静默,直到进程重启 —— 与用户「重启 App 后恢复」的现象吻合。
修复
把这两种「唤不醒」态统一判为可恢复:丢弃坏死的 ctx、用全新 ctx 重试一次(限一次,防止在坏死 ctx 上无限递归),让共享
AudioContext自愈。处置决策抽成纯函数cueActionAfterResume以便单测。仅改audioCue.ts,playRecordStartCue()对外签名与契约不变。测试
cueActionAfterResume回归用例:running→排期 / superseded 或迟到→丢弃 / resume 被拒或唤不醒→重建重试 / 重试后仍失败→放弃(防死循环)。npx tsx src/lib/audioCue.test.ts全绿;tsc --noEmit零报错(均在干净beta上验证)。验证建议
此 bug 需长时间暴露。建议出测试版后:频繁触发录音(尤其切到本地 ASR,最重度抢占音频会话)数十~上百次,或挂后台长时间,确认「开始叮咚」不再消失;若设置页「试听」也哑,即共享 ctx 已退化,本修复会在下次播放时自动重建恢复。
PR Type
Bug fix, Tests
Description
Introduce
cueActionAfterResumefor resume outcome decisionsHandle resume rejection or non-running state by recreating context (once)
Add unit tests for the new decision logic
Fix silent audio cue failures due to frozen AudioContext
Diagram Walkthrough
flowchart LR start["start"] --> getContext["getContext"] getContext --> isRunning{"ctx running?"} isRunning -- "yes" --> schedule["scheduleCueVoices"] isRunning -- "no" --> resume["ctx.resume()"] resume --> settle{"settle(runningAfterResume)"} settle -- "running & shouldPlay" --> schedule settle -- "running & !shouldPlay" --> drop["drop"] settle -- "!running & shouldPlay" --> allowRecreate{"allowRecreate?"} allowRecreate -- "yes" --> recreate["discardContext + playRecordStartCueOnce(false)"] allowRecreate -- "no" --> dropFile Walkthrough
audioCue.test.ts
Add unit tests for resume recovery logicopenless-all/app/src/lib/audioCue.test.ts
cueActionAfterResumefunction!shouldPlay, not running & allowRecreate, not running & !allowRecreate
audioCue.ts
Fix audio cue resume recovery with bounded retryopenless-all/app/src/lib/audioCue.ts
cueActionAfterResumepure function to decide action afterresume
discardContexthelper to clean up and recreate dead AudioContextplayRecordStartCueintoplayRecordStartCueOncewithbounded retry (once)
instead of silent failure