about://tracing
と Audion(Chrome DevTools の WebAudio 拡張機能)を使用して、Chrome でウェブ オーディオ アプリのパフォーマンスをプロファイリングする方法について説明します。
この記事は、Web Audio API を使用するアプリを開発していて、出力からポンという音が聞こえるか、予期しない音が聞こえるなどの予期しない不具合が発生したために遭遇したと思われます。すでに crbug.com のディスカッションに参加していて、Chrome のエンジニアから「トレースデータ」をアップロードするか、グラフの可視化について調べてほしいと依頼されたかもしれません。この記事では、Google が問題を把握して根本的な問題を解決できるように、関連情報を取得する方法について説明します。
ウェブ オーディオ プロファイリング ツール
ウェブ オーディオのプロファイリングに役立つツールとして、about://tracing
と、Chrome DevTools の WebAudio 拡張機能の 2 つがあります。
about://tracing
を使用する状況
謎の「不具合」が発生したとき。トレースツールを使用してアプリをプロファイリングすると、次の分析情報が得られます。
- さまざまなスレッドの特定の関数呼び出しが費やしたタイムスライス
- タイムライン ビューの音声コールバックのタイミング
通常は、オーディオ コールバックの期限の遅れや、予期しないオーディオの不具合を引き起こす可能性がある大規模なガベージ コレクションを示します。この情報は根本的な問題を把握するために役立つため、Chromium のエンジニアは特にローカルで再現できない場合に、この質問をすることがよくあります。一般的なトレース手順については、こちらをご覧ください。
Web Audio DevTools 拡張機能を使用する場面
オーディオ グラフを可視化し、オーディオ レンダラの動作をリアルタイムでモニタリングする場合。オーディオ ストリームを生成して合成するための AudioNode
オブジェクトのネットワークであるオーディオ グラフは複雑になることがよくありますが、グラフのトポロジは設計上不明瞭です。(Web Audio API には、ノードやグラフのイントロスペクションの機能はありません)。グラフに変化がいくつかあり、無音が聞こえるようになりました。次に、リッスンしてデバッグします。これは決して容易なことではなく、オーディオ グラフが大きいほど難しくなります。Web Audio DevTools 拡張機能を使用すると、グラフを可視化できます。
この拡張機能を使用すると、レンダリング容量の現在の推定値をモニタリングできます。これは、特定のレンダリング バジェット(48 KHz で約 2.67 ms)におけるウェブ音声レンダラのパフォーマンスを示します。容量が 100% に近づくと、レンダラが所定の予算内で作業を完了できないため、アプリでグリッチが発生する可能性が高くなります。
about://tracing
トレースデータをキャプチャする方法
以下の手順は Chrome 80 以降を対象としています。
他のタブとウィンドウをすべて閉じ、拡張機能を無効にしてください。 または、Chrome の新しいインスタンスを起動するか、さまざまなリリース チャンネルの他のビルド(Beta や Canary など)を使用することもできます。ブラウザの準備ができたら、次の手順を行います。
- アプリケーション(ウェブページ)をタブで開きます。
- 別のタブを開いて
about://tracing
に移動します。 - [録音] ボタンを押して、[設定を手動で選択] を選択します。
- [Record Categories] セクションと [Disabled by Default Categories] セクションの両方で [None] ボタンを押します。
- [Record Categories] セクションで、以下を選択します。
audio
blink_gc
media
v8.execute
(AudioWorklet
JS コードのパフォーマンスに関心がある場合)webaudio
- [Disabled by Default Categories] セクションで、次のように選択します。
audio-worklet
(AudioWorklet
スレッドの開始位置に関心がある場合)webaudio.audionode
(各AudioNode
の詳細なトレースが必要な場合)
- 下部の [Record] ボタンを押します。
- アプリケーションのタブに戻り、問題の原因となっていた手順をやり直します。
- 十分なトレースデータがある場合は、[トレース] タブに戻って [停止] をクリックします。
[トレース] タブに結果が可視化されます。
[保存] をクリックして、トレースデータを保存します。
トレースデータの分析方法
トレースデータは、Chrome のウェブ オーディオ エンジンが音声をどのようにレンダリングするかを可視化します。 レンダラには、オペレーティング システム モードとワークレット モードの 2 種類のレンダリング モードがあります。各モードは異なるスレッドモデルを使用するため、トレース結果も異なります。
オペレーティング システム モード
オペレーティング システム モードでは、AudioOutputDevice
スレッドがすべてのウェブ オーディオ コードを実行します。AudioOutputDevice
は、ブラウザのオーディオ サービスからのリアルタイム優先度スレッドであり、オーディオ ハードウェア クロックによって駆動されます。このレーンのトレースデータに不規則がある場合、デバイスからのコールバックのタイミングにジッターが発生している可能性があります。Linux と Pulse Audio の組み合わせで、この問題が報告されています。詳しくは、Chromium の問題(#825823、#864463)をご覧ください。
ワークレット モード
1 つのスレッドが AudioOutputDevice
から AudioWorklet
スレッドにジャンプするワークレット モードでは、以下に示すように 2 つのスレッドレーンに適切に配置されたトレースが表示されます。ワークレットを有効にすると、すべてのウェブ オーディオ オペレーションが AudioWorklet
スレッドによってレンダリングされます。このスレッドは現在、リアルタイムの優先度ではありません。
ここでの一般的な異常は、ガベージ コレクションやレンダリング期限の遅れが原因で発生する大きなブロックです。どちらの場合も、音声ストリームに不具合が発生します。
いずれの場合も、オーディオ デバイスのコールバック呼び出しとレンダリング タスクが所定のレンダリング バジェット内で適切に完了することが、トレースデータとして理想的です。上記の 2 つのスクリーンショットは、理想的なトレースデータの好例です。
実例から学ぶ
例 1: レンダリング バジェットを超えるレンダリング タスク
以下のスクリーンショット(Chromium の問題 #796330)は、AudioWorkletProcessor
のコードに時間がかかりすぎ、特定のレンダリング バジェットを超える場合の一般的な例です。コールバックのタイミングは正常ですが、Web Audio API のオーディオ処理関数呼び出しが、次のデバイスのコールバックまでに処理を完了できませんでした。
選択肢:
- 使用する
AudioNode
インスタンスの数を減らして、オーディオ グラフのワークロードを軽減します。 AudioWorkletProcessor
のコードのワークロードを軽減します。AudioContext
のベース レイテンシを長くします。
例 2: ワークレット スレッドでの重要なガベージ コレクション
オペレーティング システムのオーディオ レンダリング スレッドとは異なり、ガベージ コレクションはワークレット スレッドで管理されます。つまり、コードがメモリの割り当て/割り当て解除(新しい配列など)を行うと、最終的にガベージ コレクションがトリガーされ、スレッドが同期的にブロックされます。ウェブ オーディオ オペレーションとガベージ コレクションのワークロードが特定のレンダリング バジェットを超える場合、音声ストリームに不具合が発生します。次のスクリーンショットは、このケースの極端な例です。
選択肢:
- メモリは事前に割り当てて、可能な限り再利用します。
SharedArrayBuffer
に基づいて、さまざまなデザイン パターンを使用します。これは完全なソリューションではありませんが、一部のウェブ オーディオ アプリでは、負荷の高いオーディオ コードを実行するために、SharedArrayBuffer
で同様のパターンを使用しています。例:
例 3: AudioOutputDevice
からのオーディオ デバイスのコールバックにジッターが発生する
ウェブ オーディオでは、オーディオ コールバックの正確なタイミングが最も重要です。これは、システムで最も精度の高い時計になります。オペレーティング システムまたはそのオーディオ サブシステムで確実なコールバックのタイミングが保証されない場合、後続のすべてのオペレーションが影響を受けます。次の画像は、ジッターが発生する音声コールバックの例を示しています。前の 2 つの画像と比較すると、各コールバックの間隔は大きく異なります。
選択肢:
latencyHint
オプションを調整して、システム オーディオ コールバックのバッファサイズを増やします。- 問題が見つかった場合は、トレースデータについて crbug.com で問題を報告してください。
Web Audio DevTools 拡張機能を使用する
また、Web Audio API 専用に設計された DevTools 拡張機能を使用することもできます。トレースツールとは異なり、グラフとパフォーマンス指標をリアルタイムで検査できます。
この拡張機能は Chrome ウェブストアからインストールする必要があります。
インストール後、Chrome DevTools を開いてトップメニューの [Web Audio] をクリックすると、パネルにアクセスできます。
[ウェブ オーディオ] パネルには、コンテキスト セレクタ、プロパティ インスペクタ、グラフ ビジュアライザ、パフォーマンス モニターの 4 つのコンポーネントがあります。
コンテキスト選択ツール
1 つのページに複数の BaseAudioContext
オブジェクトを含めることができるため、このプルダウン メニューで検査するコンテキストを選択できます。左側のゴミ箱アイコンをクリックして、ガベージ コレクションを手動でトリガーすることもできます。
プロパティ インスペクタ
サイドパネルには、ユーザーが選択したコンテキストまたは AudioNode
のさまざまなプロパティが表示されます。AudioParam
での動的な値の検査はサポートされていません。
グラフ ビジュアライザー
このビューには、ユーザーが選択したコンテキストの現在のグラフ トポロジが表示されます。この可視化は、リアルタイムで動的に変化します。可視化の要素をクリックすると、プロパティ インスペクタで詳細情報を調べることができます。
パフォーマンス モニター
下部のステータスバーは、選択した BaseAudioContext
が AudioContext
の場合にのみアクティブになり、これはリアルタイムに実行されます。このバーは、選択した AudioContext
の瞬間的な音声ストリームの品質を示し、1 秒ごとに更新されます。次の情報が表示されます。
コールバック間隔(ミリ秒): コールバック間隔の加重平均/分散を表示します。平均が安定していて、分散が 0 に近いことが理想的です。ばらつきが大きい場合は、システムレベルのオーディオ コールバック関数のタイミングが不安定で、音声ストリームの品質が低下することを意味します。(上記の例 3 を参照)。
レンダリング容量(パーセント): 容量が 100% に近づくということは、特定のレンダリング バジェットに対してレンダラが処理しすぎていることを意味します。そのため、レンダリング能力を減らすことを検討する必要があります(グラフで使用する
AudioNodes
オブジェクトを減らすなど)。
ゴミ箱アイコンをクリックすると、ガベージ コレクタを手動でトリガーできます。
以前の WebAudio DevTools パネル
現在、この拡張機能は Chrome ウェブ オーディオ チームが推奨する方法ですが、以前の WebAudio DevTools パネルも使用できます。このパネルにアクセスするには、DevTools の右上にあるその他メニューをクリックし、[その他のツール]、[WebAudio] の順に選択します。
おわりに
オーディオのデバッグは困難です。ブラウザ内でのオーディオのデバッグはさらに困難です。ただし、これらのツールを使用すると、ウェブ オーディオ コードのパフォーマンスに関する有益な分析情報が得られ、問題を軽減できます。ただし、Chrome や拡張機能に問題が見つかることもあります。その後、恐れずに crbug.com でバグを報告するか、拡張機能の Issue Tracker でバグを報告してください。
写真撮影: Jonathan Velasquez(Unsplash)