Skip to content

fix(audiotap): recover system tap silent-death via digital-zero watchdog#8

Merged
m5d215 merged 1 commit into
mainfrom
fix/audiotap-silent-death-digital-zero
Jul 9, 2026
Merged

fix(audiotap): recover system tap silent-death via digital-zero watchdog#8
m5d215 merged 1 commit into
mainfrom
fix/audiotap-silent-death-digital-zero

Conversation

@m5d215

@m5d215 m5d215 commented Jul 9, 2026

Copy link
Copy Markdown
Owner

症状

system tap(Core Audio process tap)で拾う system 音声が、起動してしばらくすると取れなくなる。mic 側は生存し続ける。実機では transcript の system 発話が起動 ~40s で沈黙し、以降 10-15 分単位で丸ごと欠落(手動 reset まで復帰しない)。

根本原因: tap silent-death

診断ログで死の瞬間を捕捉したところ、buffer は途切れず届いている(bufIdle≈0)のに中身が digital zero(rms=0.00000)で張り付く状態だった。既存の watchdog は

  • frames-stall(buffer 自体が来ない = 完全死)
  • device-rate 変化(BT profile 切替等)

しか見ておらず、「buffer は流れるが中身が無音」はどちらにも当たらない盲点だった。

修正: digital-zero watchdog

watchdog に silent-death 検知 (1b) を追加。digital zero(rms < 1e-6)が 15s + 出力中プロセスあり + backoff 30s で tap を recreate する。

過去に同種を撤去した経緯と、今回の誤発火回避

以前 rms < 閾値 + IsRunningOutput 判定の silent-death watchdog を入れたが、IsRunningOutput は held-open で常時 true・静かな生音が閾値を下回るため、通話の無音期に発話を取りこぼしながら永久 recreate(実機 1 日 679 回)して撤去した経緯がある。

今回は実測に立脚して誤発火を避ける:

  • 生きた経路はノイズフロアで rms が必ず非ゼロ(実測 ~0.0003)、死んだ経路はちょうど 0。よって閾値ではなく厳密ゼロ(< 1e-6)で切る。生音の pause はゼロにならないので踏まない。
  • 出力中プロセスがある時だけ発火(真の無音を除外)、backoff で連発防止。
  • 治療は tap の recreate のみ(手動 reset が transcriber を触らず tap 再作成だけで直る事実で裏取り済み)。private aggregate を作り直すだけで本体再生には触れない。

検証(実機)

  • silent-death を 15s で自己修復、手動 reset 不要。
  • 導入後 9 回発火 → 9 回とも自動復帰、誤発火 0。system 発話の取得件数が故障時の「40s で 7 件」から通常運用(数百件/時間)に回復。

既知の限界

引き金自体は未特定(メモリ逼迫との相関は見えたが、発火の瞬間と圧の急変が一致せず断定できない)。本 watchdog は引き金を問わず症状(digital zero)で治すため、原因非依存で復帰する。

🤖 Generated with Claude Code

system tap が buffer を出し続けるのに中身が digital zero で張り付く
silent-death を、watchdog が検知して tap を作り直すようにする。frames-stall
(完全死) と device-rate 変化しか見ていなかったため、この「buffer は来るのに
無音」は盲点で、手動 reset まで 10-15 分 system 音声が丸ごと欠落していた
(実機で transcript の system が起動 40s で沈黙、mic は継続を確認)。

過去に同種の watchdog を入れて撤去した経緯がある(rms<閾値 + IsRunningOutput
判定が、held-open で常時 true・静かな生音が閾値下 → 通話の無音期に発話を
取りこぼしながら永久 recreate、実機 1 日 679 回)。今回は実測に立脚して誤発火を
回避する:

- 生きた経路はノイズフロアで rms が必ず非ゼロ(実測 ~0.0003)、死んだ経路は
  ちょうど 0。よって「rms < 閾値」ではなく「rms < 1e-6 (digital zero)」で切る。
  生音の pause はゼロにならないので踏まない。
- 出力中プロセスがある時だけ発火(真の無音を除外)、backoff 30s で連発防止。
- 治療は tap の recreate のみ(manual reset が transcriber を触らず tap 再作成
  だけで直る事実で裏取り済み)。

実機で silent-death を 15s で自己修復(手動 reset 不要)、誤発火 0 を確認。
引き金自体は未特定(メモリ逼迫との相関は見えたが発火の瞬間と一致せず断定不可)。
本 watchdog は引き金を問わず症状で治すので原因非依存で守れる。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@m5d215
m5d215 merged commit 00d725c into main Jul 9, 2026
3 checks passed
@m5d215
m5d215 deleted the fix/audiotap-silent-death-digital-zero branch July 9, 2026 23:21
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