6 ポイント 投稿者 GN⁺ 2025-02-17 | 1件のコメント | WhatsAppで共有
  • LinuxノートPCのホワイトノイズを追跡したところ、実際の音がなくてもFirefoxのタブがPulseAudioのオーディオシンクを起こし続けている問題が明らかになった
  • module-suspend-on-idleは10秒後にオーディオデバイスを停止するよう設定されていたが、ウェブサイトがAudioContextを作成すると、シンクがIDLE/SUSPENDEDに下がらない
  • Outlookのウェブ通知、x.comのクリック、Google Translateの音声再生、Discordウェブアプリで同じ現象が見られ、new AudioContext()だけでもノイズが始まる
  • 測定上、ノイズがないときのpulseaudioのCPU使用率は0.0%だったが、ノイズがあるときは4.7%で、システム電力はおおよそ1.5W増加した
  • AudioContext.suspend()はオーディオハードウェアへのアクセスを止め、CPU/バッテリー使用量を減らせるが、FirefoxはChromeのように一定時間後に自動で浪費を止めない

オーディオシンクがスリープしない問題

  • 新しいノートPCで音楽やオーディオが再生されていないときでも、スピーカーからかすかながら耳障りなホワイトノイズが聞こえる
  • LinuxのPulseAudioの状態を確認するためにpactl list sinks shortを使用した
    • オーディオシンクの状態はIDLESUSPENDEDRUNNINGのいずれかで表示される
    • シンクがSUSPENDEDのときはスピーカーは静かだった
    • IDLEまたはRUNNINGのときは、実際の再生音がなくてもホワイトノイズが発生することがあった
  • /etc/pulse/default.pa/etc/pulse/system.paにはmodule-suspend-on-idleがロードされていた
    • 設定上、10秒間非アクティブならオーディオシンクは自動停止するはずだった
    • しかし一部の状況ではシンクがIDLEにならず、SUSPENDEDにも到達しなかった

アイドル状態のオーディオが電力を使う理由

  • module-suspend-on-idleは、一定時間ストリームに接続されていないシンクとソースをバックエンドから切り離す
  • 主要な効果は省電力である
    • PulseAudioがアイドル状態でもサウンドカードへ空のデータを送ると、ALSAがより多くのCPUサイクルを使う
    • 常にアクティブなストリームを維持する予定がないなら、タイマーを短く設定するほうが省電力に有利である

原因はFirefoxのタブとウェブサイトに絞られた

  • ホワイトノイズが聞こえるたびに、pactl list sink-inputsでどのプログラムがオーディオシンクを使用しているか確認した
  • 原因は常にFirefoxだった
    • 開いているタブの中に、実際に音を再生する必要があるタブはなかった
    • ミュートされた動画もなかった
  • i3のステータスバーに小さなスクリプトを追加し、オーディオシンクがRUNNINGになると赤い表示が出るようにした
  • 最初は、固定タブとして開いていたoutlook.office.comの通知音が原因のように見えた
    • メールを受信するとホワイトノイズが始まる
    • タブを再読み込みするかFirefoxを再起動するまで止まらなかった
  • その後、他のウェブサイトでも同じ現象が確認された

CPUと電力の測定結果

  • ホワイトノイズがないとき、pulseaudioのCPU使用率は**0.0%**と表示された
  • 同じ環境での電力測定値は、おおむね4.2〜5.1Wの範囲だった
  • ホワイトノイズがあるとき、pulseaudioのCPU使用率は**4.7%**に上がった
  • このときの電力測定値は、おおむね5.8〜6.7Wの範囲だった
  • 差は「取るに足らないレベル」ではなく、おおよそ1.5W増加と整理できる

WebAudio APIとAudioContext

  • HTML/JavaScriptでオーディオを再生する方法は、<audio>タグとWebAudio APIの2つに分かれる
  • Outlookのように動的に音を再生する場合はWebAudio APIを使い、オーディオ処理を行うにはまずAudioContextを作成する必要がある
  • 問題は、const audioCtx = new AudioContext();を実行するだけでもスピーカーからホワイトノイズが発生する点である
  • テストページとしてhttps://editor.43z.one/sqare/iが提供されている
  • AudioContext.suspend()はオーディオコンテキストの時間進行を止め、オーディオハードウェアへのアクセスを一時停止してCPU/バッテリー使用量を減らす
  • AudioContext.resume()は停止したオーディオコンテキストの時間進行を再開する

FirefoxとChromeの違い

  • 多くのウェブサイトはすぐに音を出す必要がなくてもAudioContextを作成し、その後これをsuspendしない
  • Chromeは一定時間が過ぎるとCPU/バッテリーの浪費を自動で止める
  • Firefoxは自動で止めず、ホワイトノイズを出し続ける状態を維持する
  • ウェブサイトが直接の原因ではあるが、Firefoxがこうしたリソース浪費からユーザーを保護できていないという不満が残る
  • Bluetoothヘッドホンが接続されている場合でも、x.comをクリックした後にホワイトノイズの送信が始まり、ヘッドホンのバッテリーを浪費する可能性があるとの疑いがある

一時的な対策: AudioContext Suspender

1件のコメント

 
GN⁺ 2025-02-17
Hacker Newsのコメント
  • これは計画済みで重要なもので、可能なら近いうちに修正する予定。すでに長く先延ばしになっていて、まだ対応できていない点は申し訳ない。いつも優先順位のせめぎ合いなので、全員を期限どおり満足させるのは難しいが、個人的な優先順位リストではかなり高いほう
    想像できるように、一定時間無音なら AudioContext を一時停止する、というだけの話よりはるかに複雑だが、それでも修正は可能だと思っている。他のブラウザはすでにやっているし、受け入れられるトレードオフもあるため
    出典: Firefoxでこの周辺機能を多く実装しており、Web Audio API標準のエディターでもある
    • こうした批判を個人的に受け止めないでほしい。最近、あるオープンソースのメンテナーがこうした批判をフラストレーションとして受け止め、大きく爆発した出来事があった
      ほとんどの人は、ここで述べられた事情を理解している。やるべきことは多く、時間は有限だ
      Firefox開発者たちが、利用者の多いサイトがユーザーにきちんと動作するよう、期待以上に努力しているのを直接経験したことがある。問題がユーザーに影響するとき、どこまで対応してくれるか知っているので、引き続き頑張ってほしい
    • Firefoxをもっと上手に使うユーザーになりたいので、ローカルで見つけた問題をデバッグしてみたい。どこから始めればよいか案内がほしい
  • Webサイトが実際の再生なしにオーディオコンテキストを開くのは、おそらくボット検知のためである可能性が高い
    ブラウザエンジンやOSごとにオーディオ処理の実装が異なるため、完全には聞こえない音を再生してからAPIで録音し直すと、シグネチャが生まれる
    そのシグネチャによって、ブラウザがユーザーエージェントを偽装しているか、ヘッドレスモードか、本物のユーザーが商品を買っている状況ではないさまざまな特殊ケースかを確認できる
    https://github.com/fingerprintjs/fingerprintjs/blob/3201a7d6...
    • ブラウザ/Web標準側がAPIをあまりにも無秩序に増やしすぎ、世の中がこのように悪用することを十分に考えていなかったように思う
    • 実際に出回っているボット用プラグインの中には、ボット検知を欺くためにAudio Contextをシミュレートするものもすでにある。狂っている
    • Cloudflareがこれを導入して、ブラウジングの自由をさらに妨げ、CPUサイクルを浪費させる日が今から待ち遠しい
  • このホワイトノイズのせいで長いことおかしくなりそうだったが、原因をまったく見つけられずにいた
    タブには再生中アイコンが出ず、タブをミュートしてもノイズが止まらない
    Windowsの音量ミキサーでFirefoxをミュートしても音が止まらない
    修正: デスクトップユーザーにとって、この拡張機能は実際かなり微妙だ。ホワイトノイズが何度もオン・オフするほうがずっと気になる
    • Windowsの音量ミキサーでFirefoxをミュートしても止まらないなら、それはFirefoxよりもっと深いところのバグではないかと思う
    • デスクトップでその拡張機能を問題なく使っている。訪問するサイトによって違うようだ。音を頻繁に再生/停止するサイトでは、拡張をオフにすればよさそう
  • 出力がアイドル状態になると、デジタルSPDIF信号が同期を失う。再生開始時に再同期するのは即時ではなく、音声の最初の1秒ほどを失う
    そこで、データをラインには流さないが出力を開いたままにするプログラムを自作し、出力がアイドル状態に入らないようにした
    ただしノートPCの文脈ではあまり意味がないので、そこでは省エネが妥当だ
    • MacBookでFiiO K3 DACを使っていたとき、これが本当に延々と鬱陶しかった。通知音のようなシステム音は、遅延のせいで事実上再生されなかった
      WindowsドライバにはストリームをAlways Onに設定するオプションがある。macOSにもあってほしい
    • 以前USB DACで同じことをした。ただログイン時に play -qn & が起動するようにしただけ
  • Android版Firefoxで、ときどきスマホが1日に10GBのデータをランダムに使い切ってしまう問題は、これで説明がつくように思う。通信料金がとんでもないことになった
    ニュースサイトが音声を再生しながら新しい広告を繰り返し読み込み、音声のせいでタブが省電力状態に入らなかったのだと思う。予想外のデータ料金が続いたため、結局Chromeに乗り換えざるを得なかった
  • macOSでも以前、これと同じか非常によく似た現象を見た。サイトが実際にオーディオコンテキストを開いたままにしていたのか、Firefox内部の問題なのかは確かではない。Web Audio APIを使っていないYouTubeのようなサイトでも発生したため
    つまりホワイトノイズはないが、オーディオによる電力消費があった: https://bugzilla.mozilla.org/show_bug.cgi?id=1821102
    今もMacで何も再生していないのに coreaudiod がCPUを20%使っている。バッテリー持ちを本当に台無しにしているので、直るまで別のブラウザに乗り換えようかと思うが、こんな些細に見えることでFirefoxを諦めたくはない
    更新: 関連はあるが別のバグに見える
  • Chromiumでこの一時停止を処理するコードはここにある:
    https://source.chromium.org/chromium/chromium/src/+/main:med...
    基本的に30秒ほど無音を検知すると、OSのオーディオデバイスが支えるシンクからヌルシンクに切り替える
    ちなみにこの方式はオーディオデバイスとは別のクロックを使うため、コンテキストが後で実際に使われる際、特定のトーンで歪みが生じるという報告が何度かあった。回避策は、サイトが記事で言及されているsuspend/resume APIを使うこと
  • audioContext が内部的にどう実装されているかは詳しく知らないが、かなり賢く動的に処理しようとする要素が多く入っているようだ。通知音を再生することが、img href *.svg の代わりにD3でSVGを描く感じに似て見える
    通知ハンドラのように単純で反復可能なものを、より低レイヤーの効率的なAPIに登録できるService Workerフックのようなものがあるのか気になる
  • 実際に何かが聞こえるはずなのか?
    macOSのFirefox 134.0.1では何も聞こえない
    • 自分のほうでも音はしないが、筆者のデモページで音声再生ボタンを押すと消費電力が約1W増える
    • Android版Firefoxでは小さなホワイトノイズが聞こえる
  • これで https://www.dr.dk/ のトップページ問題が直った