1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ブラウザのエコー除去で別のアプリの音も消したくて、"all" にたどり着いた話(2026年版)

1
Posted at

はじめに

GMOコネクトの永田です。

ブラウザ上で動く、音声で話しかけるアプリを試作していました。マイクを開くときにブラウザのエコー除去をオンにしておけば、スピーカーから出た音はマイクの音から消えるだろうと思っていました。

ところが、同じ Mac の同じスピーカーから鳴った音でも、別のアプリが鳴らした音はほとんど減りませんでした😇
調べると、ブラウザのエコー除去が消していたのは、ブラウザ自身が鳴らした音だけでした。設定を1つ変えると、別のアプリの音も消えました。

Mac の Chrome で、誰が鳴らした音がどれだけ消えるかを測った記録です。

先にまとめ

鳴らした元 echoCancellation: true echoCancellation: "all"
同じページの <audio> 消えた 消えた
同じ Chrome の別のサイトのページ 消えた 消えた
別のアプリ(afplay) 消えない(0.3dB 減) 消えた
別の機器(スマホ) 消えない(0.4dB 減) 消えない(0.7dB 減)

「消えた」は、鳴らしている間のマイクの音が、鳴らす前の部屋の音より小さくなったことを指します(中央値。回ごとでは、物音が入った1回を除いて同じ)。

  • true で消えるのは、Chrome がスピーカーに鳴らした音だけでした。仕様は true で消す範囲をブラウザに任せていて、「システムの音を全部消す」は推奨(SHOULD)にとどまります
  • Chrome 141 から使える "all" にすると、別のアプリの音も Chrome の音と同じくらい消えました(5回とも 38.8dB 以上減)。macOS から「システムオーディオを収録するためのアクセス権」の許可を求められます
  • getSettings().echoCancellation は、macOS の許可に答える前から "all" を返しました。値だけでは、別のアプリの音まで消せているかは分かりません

1. 何をどう測ったか

同じ読み上げを4つの元から鳴らし、echoCancellation を false・true・"all" に変えて内蔵マイクで録りました。

項目 条件
観測日 2026年10月23日
機器 MacBook Pro の内蔵スピーカーと内蔵マイク
OS・ブラウザ macOS 26.6.2、Google Chrome 155.0.8059.86
Chrome の起動 使い捨てのプロファイル。マイクの許可の画面を省く --use-fake-ui-for-media-stream など
鳴らした音 macOS の say で作った日本語の読み上げ(15.6秒)。Mac の音量は50
スマホ 音量は最大、Mac の左側10〜15cm に置いた
回数 Mac で鳴らす3つは各設定5回、スマホは各設定3回。設定の順番は回ごとに入れ替えた
測った値 読み上げの始まりから2秒を除いた約13秒の、マイクの音の大きさ(dBFS)
部屋の音 鳴らす前の約1秒。中央値で約 -62 dBFS

4つの元は次のとおりです。

鳴らした元 中身
同じページ 測定ページの <audio>
別のサイトのページ 同じ Chrome で開いた別のページ。測定ページは 127.0.0.1、こちらは localhost で開いた(別のサイトになる)
別のアプリ macOS の afplay コマンド
別の機器 スマホ

マイクは次のように開きました。エコー除去だけの効き方を見るため、雑音の抑圧と音量の自動調整は切っています。

const stream = await navigator.mediaDevices.getUserMedia({ audio: {
  deviceId: { exact: mic.deviceId },   // 内蔵マイク
  echoCancellation: ec,                // false / true / "all"
  noiseSuppression: false,
  autoGainControl: false,
} });
// 実際に効いている値。"all" を求めると "all" が返った
console.log(stream.getAudioTracks()[0].getSettings().echoCancellation);

録った音は AudioWorklet で取り出し、そのまま保存しました。減りは、同じ回(1回目どうし、2回目どうし…)の false との差の中央値です。表の大きさ(中央値)どうしを引いた値とは、0.1〜0.2dB ずれることがあります。

2. true で消えるのは、Chrome が鳴らした音だけだった

true の結果です(5回の中央値)。

鳴らした元 false true 減り(最小〜最大)
同じページ -29.5 dBFS -67.2 dBFS 37.7dB(22.9〜42.6)
別のサイトのページ -27.1 dBFS -69.9 dBFS 42.8dB(31.4〜47.3)
別のアプリ(afplay) -29.4 dBFS -29.6 dBFS 0.3dB(0.0〜0.4)

同じページと別のサイトのページは、鳴らしている間のマイクの音が、部屋の音(約 -62 dBFS)より小さくなりました。エコーだけでなく、部屋の音ごと抑えられています。この減りは「エコーが消えた量」ではなく、マイクの音全体の下がり方です。最小値が小さい回は、測っている最中に部屋で物音が入った回でした。

別のアプリが鳴らした音は、5回とも0.4dB 以下しか減りませんでした。同じスピーカーから同じ大きさで出ていて、マイクに届く音もほぼ同じです。違うのは、誰が鳴らしたかだけでした。

3. 消えるかどうかは、鳴らした音を知っているかで決まる

エコー除去は、スピーカーに送った音(参照信号)を手元に持っていて、それに似た成分をマイクの音から引きます。参照信号に無い音は、マイクに入っても話し声や物音と区別がつきません。

Chrome の true が参照にしている音は、Chromium のソース(2026年10月時点の media/base/media_switches.cc)のコメントに書かれています。

If echo cancellation for a mic signal is requested, mix and cancel all audio playback going to a specific output device in the audio service.

Chrome がその出力機器に鳴らした音は、タブやページをまたいでまとめて参照にします。別のサイトのページの音が消えたのはこのためです。afplay は Chrome の外で鳴っているので、参照に入りません。

仕様(W3C Media Capture and Streams)は、true で消す範囲をブラウザに任せています。

true means that the UA decides what audio will be removed from the signals recorded by the microphone. true MUST attempt to cancel at least as much as "remote-only" and SHOULD attempt to cancel as much as "all".

"remote-only" は WebRTC で受け取った相手の音、"all" はシステムが鳴らすすべての音です。Chrome の true は MUST(相手の音以上)を満たしていて、SHOULD(すべての音)までは届いていない、と読めます。仕様違反ではありません。

英語では、Electron の issue で同じ観察が報告されています("Chrome only cancels the system audio that Chrome itself is playing, rather cancelling system audio played by all apps.")。

4. "all" にすると、別のアプリの音も消えた

Chrome 141 から、echoCancellation に "all" と "remote-only" を指定できます。リリースノートには、true と false に加えて次の値を受け付けるようになったとあります。

now additionally accepts the values "all" and "remote-only".

"all" では、システムの出力を取り込んで参照にします。macOS では 14.2 以上が条件です。同じソース(2026年10月時点)のコメントです。

If echo cancellation for a mic signal is requested, use system loopback audio as reference signal to be able to cancel echo from all audio processes and not only audio from Chrome.

"all" の結果です(5回の中央値)。

鳴らした元 false "all" 減り(最小〜最大)
同じページ -29.5 dBFS -71.8 dBFS 42.3dB(29.3〜46.7)
別のサイトのページ -27.1 dBFS -73.6 dBFS 46.3dB(34.7〜50.8)
別のアプリ(afplay) -29.4 dBFS -71.8 dBFS 42.5dB(38.8〜47.6)

別のアプリの音も、Chrome が鳴らした音と同じように部屋の音より下まで下がりました。true と "all" の差(同じページで4.6dB、別のサイトのページで3.5dB)は、物音の入り方で動く範囲なので、差としては見ていません。

"all" でマイクを開くと、macOS が次のダイアログを出しました。

"Google Chrome" から、システムオーディオを収録するためのアクセス権を求められています。
Chrome にアクセスを許可すると、ウェブサイトからアクセスをリクエストできるようになります。

このダイアログに答える前から、getSettings().echoCancellation は "all" を返していました。ページの側からは、システムの音を参照にできているかまでは分かりません。許可しなかったときにどう動くかは、今度試したいことです。

5. 別の機器の音は、どちらの設定でも消えない

スマホで鳴らした結果です(3回の中央値)。

設定 大きさ 減り(最小〜最大)
false -42.5 dBFS 基準
true -43.0 dBFS 0.4dB(0.3〜0.5)
"all" -43.2 dBFS 0.7dB(0.6〜0.8)

スマホの音は Mac の出力を通らないので、"all" の取り込みにも入りません。参照が無いので、エコー除去からは話し声と同じに見えます。別の PC やスマートスピーカーなど、Mac 以外の機器が鳴らす音も同じ立場です(測ったのはスマホだけです)。

まとめ

echoCancellation: true で何を消すかは、仕様ではブラウザに任されています。Chrome の true が消すのは Chrome が鳴らした音だけで、同じスピーカーから出る別のアプリの音は消しませんでした。別のアプリの音も消したいなら、Chrome 141 以降で "all" を指定します。macOS ではシステムオーディオの収録の許可が要ります。許可の前から getSettings() は "all" を返すので、効いているかどうかは値だけでは確かめられません。


最後に、GMOコネクトではサービス開発支援や技術支援をはじめ、幅広い支援を行っておりますので、何かありましたらお気軽にお問合せください。

お問合せ:https://gmo-connect.jp/contactus/

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?