Linux でマイクの入力音量が勝手に下がる問題

概要

Linux で有線接続のマイクの入力音声のボリュームが勝手に下がる現象が発生しました. これは ZoomGoogle Chrome といったクライアントが勝手にデバイスの音量を操作することが原因であることが分かりました。 また Pulse Audio 側でクライアントによる音量操作を無効化するオプションは現時点では用意されていないようでした。

そこで以下のようなスクリプトを常時実行するという手法によりデバイス音量を一定に保つことでクライントによる音量操作を事実上無効化することに成功しました。 (alsa_input.???-?????.analog-stereo はデバイス名で適切に置換する必要があります)

$ while sleep 0.1; do pacmd set-source-volume alsa_input.???-?????.analog-stereo 65535; done

環境

以下のようなソフトウェアを使用している環境で検証しました.

  • OS : Ubuntu 20.04
  • デスクトップ環境 : GNOME 3.36.5
  • サウンドサーバー : pulseaudio 13.99.1
  • Zoom : Version: 5.9.3 (1911)
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.3 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
$ gnome-shell --version
GNOME Shell 3.36.9
$ pulseaudio --version
pulseaudio 13.99.1

事象の再現

Zoom Version: 5.9.3 (1911)

Zoom で会議に参加してマイクを有線接続。ミュートを解除して何かしらの音をマイクに拾わせたところ自動的にマイクの音量が小さくなりました。 音量の設定にはデバイスごとの設定とアプリごとの設定がありますが、今回自動的に下がったのはデバイスごとの設定のみでした。

以下のキャプチャは GNOME のデフォルトのシステム設定を行う GUI である 設定 (Setting)サウンド設定の画面です。 入力デバイスの音量が自動的に下がっていることが確認できます。(もちろん音量を手動で下げているわけではありません)

f:id:kira000:20220216211200g:plain

Google Chrome (Google Meet)

この問題は Zoom 固有の問題ではなく他のアプリケーションでも発生しました。 Google Chrome 上で Google Meet を起動し会議に参加してマイクに音声を拾わせた場合も同様の事象が発生しました。

f:id:kira000:20220216212306g:plain

原因

ググったら同様の事象についての質問が既にありました。

lists.freedesktop.org

askubuntu.com

どうやら ZoomGoogle Chrome といったクライアントアプリ側で自動で入力デバイスの音量を調節するという迷惑な機能があるようです。 Zoom の場合は以下のように Automaticcaly adjast microphone volume という設定項目があり, クライアント側でこの機能をオフにすることができました。

f:id:kira000:20220216213727p:plain

実際にこの機能をオフにした状態で Zoom で会議に参加してマイクに音を拾わせたところ自動的に音量が変化する現象はなくなりました。

しかし, Google ChromeGoogle Meet のようなアプリを起動している場合はアプリ側でこの機能をオフにすることはできなさそうでした。 以下に引用するように, Google Chrome ではおそらく WebRTC プロトコルが使われており, Chrome/Chromium の WebRTC 実装には Auto Gain Control という機能があり, ウェブアプリ自体にこの機能をオフにするオプションが無い限りオフにできないらしいです。

Unfortunately the WebRTC implementation in Chromium comes with a handy “feature” called Automatic Gain Control that tends to screw with your microphone volume. Unless the web app itself gives you an option to disable it, there is otherwise no way turn it off, and Chrome developers don't want to add a global “off switch” for it.

また, PulseAudio 側でクライアントによる音量操作を無効化するオプションは現時点では用意されていないようでした。issue がたっていました。

解決策

下記の質問の解答の内最も upvote が多いものを試したところクライアント側で入力デバイスの音量を変更を事実上禁止することができました。

手法は単純で以下のスクリプトを実行するだけです。

$ while sleep 0.1; do pacmd set-source-volume alsa_input.???-?????.analog-stereo 65535; done

なお, alsa_input.???-?????.analog-stereo のところは下記のコマンドで得られるデバイス名で適切に置換する必要があります。

$ pacmd list-sources | grep alsa_input
        name: <alsa_input.usb-USB_HD_Camera_USB_HD_Camera-02.iec958-stereo>
        name: <alsa_input.pci-0000_00_1b.0.analog-stereo>
        name: <alsa_input.usb-USB_HD_Camera_USB_HD_Camera-02.iec958-stereo.echo-cancel>

私の場合は alsa_input.pci-0000_00_1b.0.analog-stereo で置換しました。

このスクリプトは 0.1 秒ごとに pacmd という PulseAudio の設定を変更するコマンドを実行してデバイスの音量を固定値としています。 65535 という値は 100% に該当します。上記の質問の解答者は 90000 (135%) に設定していました。

この手法は無駄に CPU リソースを使うのであまりエレガントな解決法とは呼べなさそうです。 しかし残念ながら現時点ではクライアントからデバイスの音量の制御を抑制する方法としてはこれくらいしかなさそうです。 今後 PulseAudio に新しいオプションが追加されることを期待したいです。(お前がコミットしろ)

このスクリプトを実行すると以下のように手動でデバイス音量を調節しようとしても固定値にすぐに戻されてしまいます。 バグっぽいですがこれは意図した通りの挙動です。

f:id:kira000:20220217200154g:plain

毎回このスクリプトを手動で実行するのは面倒なので, systemd により起動時に自動で実行するようにしてみます。

上記のシェルスクリプトを適当な場所に保存して chmod +x で実行権限を付与します。 次に、以下のように ~/.local/share/systemd/user/ に systemd ファイルを作成します。 ExecStart に渡す PATH は絶対PATHで指定しました。

$ vim ~/.local/share/systemd/user/no-agc.service
$ cat ~/.local/share/systemd/user/no-agc.service
[Unit]
After=pulseaudio.service
Requires=pulseaudio.service

[Service]
ExecStart=/home/kira924age/work/configs/saber/pulse-audio/no-agc.sh

ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT

TimeoutStopSec=5
KillMode=process
PrivateTmp=true
Restart=always

[Install]
WantedBy=default.target

次に以下のコマンドで自動起動を有効にします。

$ systemctl --user enable no-agc.service

再起動して service が起動していれば勝ちです。

$ sudo reboot
$ systemctl --user status no-agc.service
● no-agc.service
     Loaded: loaded (/home/kira924age/.local/share/systemd/user/no-agc.service;>
     Active: active (running) since Thu 2022-02-17 22:06:44 JST; 13s ago
   Main PID: 2141 (no-agc.sh)
     CGroup: /user.slice/user-1000.slice/user@1000.service/no-agc.service
             ├─2141 /bin/bash /home/kira924age/work/configs/saber/pulse-audio/n>
             └─4359 sleep 0.1

 2月 17 22:06:44 saber systemd[2083]: Started no-agc.service.
 2月 17 22:06:46 saber no-agc.sh[2190]: デーモンが応答しません

試したけどうまく行かなかった手法

ArchWiki の以下の項目に書いてあることも試しましたがうまく動作しませんでした。

wiki.archlinux.jp

  • /usr/share/pulseaudio/alsa-mixer/paths/analog-input*.conf に該当するファイルを検索. (Ubuntu の場合は Arch とは該当ファイルがあるディレクトリが異なっていました)
$ sudo ls /usr/share/pulseaudio/alsa-mixer/paths/ | grep -oE ^analog-input.*\.conf$
analog-input-aux.conf
analog-input-dock-mic.conf
analog-input-fm.conf
analog-input-front-mic.conf
analog-input-headphone-mic.conf
analog-input-headset-mic.conf
analog-input-internal-mic-always.conf
analog-input-internal-mic.conf
analog-input-linein.conf
analog-input-mic-line.conf
analog-input-mic.conf
analog-input-rear-mic.conf
analog-input-tvtuner.conf
analog-input-video.conf
analog-input.conf

検索に該当した全てのファイルについて以下のようにファイルを編集 (!!! PulseAudio の設定ファイルを編集する前にバックアップを取ることをおすすめします。何かあったときにすぐ元に戻せるようにしたほう良さそうです !!!)

  • [Element Capture] の下の volume を zero に設定
  • [Element Internal Mic Boost] の下の volume を zero に設定
  • [Element Int Mic Boost] の下の volume を zero に設定
  • [Element Mic Boost] の下の volume を zero に設定

(注意) [Element Headphone Mic Boost][Element Mic Boost (+20dB)] といった全てのバリエーションでも同様に設定する

PulseAudio を再起動して設定を反映させる。

$ pulseaudio -k
$ pulseaudio --start

この手法は PulseAudio の Auto Gain Cntorol を無効化する方法としていろいろなところで紹介されているものですが私の場合はうまく動作しませんでした。 音量が小さくなる現象はなくなりましたが、逆に大きくなる現象が発生しました。 また, /usr/share/pulseaudio/alsa-mixer/paths/ は PulseAudio のパッケージを更新するたびに上書きされるので, そのたびに編集する必要があります。

参考文献