WSL2+Ubuntu 20.04環境から音声を出力する

2020年8月8日WSL 2Linux,Ubuntu,Windows,WSL2

Windows 10のWSL2(Windows Subsystem for Linux)のUbuntu 20.04から、音を出せるように設定してみました。

先日のGUIアプリ実行と同様に、Windows側にソフトを入れて接続受け入れ設定をして、Ubuntu側にはWindows宛てに音を出力するように設定します。

これを行うと、Ubuntu側にインストールしたChromeなどから音を出力できるようになります。

WindowsのInsider Preview参加者の方へ(追記)

Windows 10のInsider Preview(ビルド21362以降)やWindows 11のInsider Previewをお使いの方は、「WSLg (Windows Subsystem for Linux GUI)」のプレビュー版を利用してGUIアプリを実行すれば、そのまま音声も出力されます。

Windows 10 Insider Previewの方向けのインストール方法は別記事にまとめていますので、こちらをご覧ください。

また、Windows 11 Insider Previewでのインストール方法はこちらをご覧ください。

2021/06/14時点の通常リリース版である「21H1」でWSLgは利用できませんので、本記事(次項以降)の通りにセットアップを進めてください。

Windows側の準備

この記事では、既にWindows 10にWSL2をインストール済み、という所から説明します。WSL2のインストールは、こちらの記事をご覧ください。

PulseAudio on Windowsをダウンロード・解凍

Windows用のPulseAudioをダウンロードします。

こちらのサイトから「zipfile containing preview binaries」のリンクをクリックすると、バージョン1.1がダウンロードできます。かなり古いバージョンですが、Windows用バイナリとしてはこれが最新のようです。

ダウンロードしたZIPファイルを任意の場所に解凍します。今回は、C:\ProgramFilesX86\PulseAudio-1.1に解凍しました。

PulseAudioの設定

解凍したフォルダを開いていくと、default.paという設定ファイルがあります(今回の例では C:\ProgramFilesX86\PulseAudio-1.1\etc\pulse\default.pa です)。これを参考サイト[2]に従って編集していきます。ただし、auth-ip-aclの部分は参考サイト[1]を元に変えています。

default.paをテキストエディタで開いて、下記の通り変更します。

43行目の
load-module module-waveout sink_name=output source_name=input

load-module module-waveout sink_name=output source_name=input record=0
に変更します。Windows 10のApril 2018 Update以降、録音デバイスへのアクセスに制限がかかっているらしく、それを回避するために追加しています。単に音を聞くだけなら大丈夫ですが、録音したい場合は何か代替案を見つける必要があります。

61行目の
#load-module module-native-protocol-tcp

load-module module-native-protocol-tcp auth-ip-acl=127.0.01;10.0.0.0/8;172.16.0.0/12;192.168.0.0/16
に変更します。行頭の#はコメント行を示すものですので、これを消して設定を有効にします。書き足している部分は、Windows側から見て、どのIPアドレスからの接続を許可するか指定しています。WSL2は仮想イーサネットでWindows側とつながっていますので、Windowsから見たWSL2のネットワークを指定します。WSL2のIPアドレスは、再起動ごとに変わる可能性がありますので、決め打ちではなく範囲指定しています。

default.paの編集が終わったら、保存して閉じます。

続いて、daemon.confを編集します。これも同じフォルダにあります(今回の例では C:\ProgramFilesX86\PulseAudio-1.1\etc\pulse\daemon.conf です)。

39行目の
; exit-idle-time = 20

exit-idle-time = -1
に変更します。通常、PulseAudioは、20秒間 非接続状態が続くと自動的に終了するそうです。それを無効にするため、この変更を行います。

daemon.confの編集が終わったら、保存して閉じます。

PulseAudioを起動する

設定が終わったら、PulseAudioを起動します。コマンドプロンプト等でC:\ProgramFilesX86\PulseAudio-1.1\etc\pulseに行って、pulseaudio.exeを実行します。なぜか、一発目は即終了してしまったので、もう一度実行しています。いろいろ警告やエラーが出るものの、起動しっぱなしになればOKです。

PS C:\> cd C:\ProgramFilesX86\PulseAudio-1.1\bin
PS C:\ProgramFilesX86\PulseAudio-1.1\bin> .\pulseaudio.exe
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
PS C:\ProgramFilesX86\PulseAudio-1.1\bin> .\pulseaudio.exe
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
W: [(null)] pulsecore/core.c: failed to allocate shared memory pool. Falling back to a normal memory pool.
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
E: [(null)] daemon/main.c: Failed to load directory.

初回起動時、Windowsのファイアウォールから、外部からのアクセスを許可するか問われます。WSL2のネットワークはパブリックネットワーク扱いなので、「パブリックネットワーク」にチェックを入れてアクセスを許可します。

「パブリックネットワーク」にチェックを入れてアクセスを許可

pulseaudio.exeを終了する場合は、Ctrl+Cを押します。

pulseaudio.exeのスタートアップ設定

WSL2から音を出したい場合は、常にpulseaudio.exeを実行しておく必要があります。

私は、Windows起動時にpulseaudio.exeがスタートアップするように、次のスクリプトをスタートアップフォルダに保存しました。ちなみに、スタートアップフォルダは、Win+Rからshell:startupで開けます。このスクリプトは、コマンドプロンプトの画面を表示せずに、裏でpulseaudio.exeを起動してくれます。(このスクリプトは、こちらのサイトを参考にさせていただきました)

pulseaudio.exeのファイルパスは、ご自身の環境に合わせて変更してください。

Set objWShell=CreateObject("Wscript.Shell")
Set objFSO=CreateObject("Scripting.FileSystemObject")
set ObjNetwork=CreateObject("WScript.Network")
pidFilePath=objWShell.ExpandEnvironmentStrings("%USERPROFILE%\.pulse\" & ObjNetwork.ComputerName & "-runtime\pid")
If objFSO.FileExists(pidFilePath) then
	objFSO.DeleteFile(pidFilePath)
End If
objWShell.run "cmd /c ""C:\ProgramFilesX86\PulseAudio-1.1\bin\pulseaudio.exe""", vbHide

Ubuntu側の設定

続いて、WSL2のUbuntu 20.04側でも、音が出せるように準備していきます。

まず、pulseaudioをインストールします。

$ sudo apt install -y pulseaudio

続いて、オーディオの出力先を設定するため、環境変数PULSE_SERVERを設定します。環境変数は、PULSE_SERVER=tcp:192.168.240.1のように、「tcp」とWSL2から見たWindowsのIPアドレスを指定します。これを.profileに書き込むため、次のコマンドを実行します。ただし、Windows側のIPアドレスは変更される場合がありますので、IPアドレスの部分は動的に指定します。

$ echo 'export PULSE_SERVER=tcp:$(grep nameserver /etc/resolv.conf | awk '\''{print $2}'\'')' >> ~/.profile

.profileを再読み込みするため、source ~/.profileを実行したら準備完了です。

試しに、wavファイルを再生してみて、Windows側から音が流れてきたら完了です。

$ paplay /mnt/c/path/to/test.wav

トラブルシューティング

Ubuntu側でpaplayが動かない

paplayがうまく動かない場合、次のようなエラーが表示されます。

$ paplay /mnt/c/path/to/test.wav
Connection failure: Connection refused

Ubuntu側からサウンドを出力する時に、Windows側のPulseAudioへの接続に失敗しています。

これらの原因が考えられますので、一つ一つ確認してみてください。

  • Ubuntu側の環境変数PULSE_SERVERが間違っている:
    echo $PULSE_SERVERで、Ubuntuから見たWindowsのIPアドレスが指定されているか確認してみてください。
  • Windows側でpulseaudio.exeが起動していない:
    タスクマネージャーの[詳細]タブでpulseaudio.exeが動いているか確認してください。
  • Windows側のファイアウォールで接続をはじいている:
    パブリックネットワークからpulseaudio.exeへのアクセスが認められているか確認してください。設定は、
    スタート → 設定 → 更新とセキュリティ → Windowsセキュリティ → Windowsセキュリティを開く → ファイアウォールとネットワーク保護 → ファイアウォールによるアプリケーションの許可 から行えます。
    「設定の変更」ボタンを押してpulseaudio.exeのパブリックのチェックを入れて、OKを押せば設定完了です。
あとから「パブリックネットワーク」からのアクセスを許可する設定

Windows側でpulseaudio.exeが「Daemon already running」と言って起動しない

PulseAudioは、実行中であることを示すために一時ファイルを作成するようです。この一時ファイルは、Ctrl+CでPulseAudioを停止すれば削除されますが、コマンドプロンプトのウィンドウの×を押した場合は削除されずに残ってしまい、次回以降、次のようなエラーを出して起動しなくなります。

PS C:\ProgramFilesX86\PulseAudio-1.1\bin> .\pulseaudio.exe
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
W: [(null)] pulsecore/core-util.c: Secure directory creation not supported on Win32.
E: [(null)] pulsecore/pid.c: Daemon already running.
E: [(null)] daemon/main.c: pa_pid_file_create() failed.

この場合は、ユーザーフォルダにある一時ファイルを削除してあげればOKです。

うちの環境の場合、C:\Users\ユーザー名\.pulse\コンピューター名-runtimepidというファイルが残っていました。これを削除すれば、pulseaudio.exeが起動するようになります。

参考サイト

参考サイト[1]

参考サイト[2]

記事の変更履歴

default.paの記述変更(2020/8/14)

default.paの61行目の設定について、当初「Ubuntu側でip aコマンドでIPアドレスを見て、そのネットワーク範囲をipcalcコマンドで調べて記載する」としていました。

記事執筆時は192.168.240.0/20の範囲で大丈夫だったのですが、パソコンを再起動したら172.24.192.0/20に変わっていました。範囲指定すれば良いと思っていましたが、それでは不十分のようなので、ローカルIPをすべて指定するように変更しました。

pulseaudio.exeの自動起動VBSを変更(2020/8/14)

pulseaudio.exeを自動起動するVBSファイルを書き換えました。当初はpulseaudio.exeを起動するだけだったのですが、既存のpidファイルが存在する場合、削除してから起動するようにしました。多重起動してしまう恐れがありますが、実害はなさそうです。

export文を.profileに移動(2020/8/28)

コマンドプロンプトやショートカットからwsl.exe -d "Ubuntu-20.04" <Ubuntu上のコマンド>を実行して直接Ubuntu上のコマンドを実行した場合、.bashrcは読み込まれません。なので、.bashrcにexport文を書いて、この方法で起動しても音が出ません。

ということで、このような起動方法でもexport文が実行されるよう、export文を.profileに移動しました。(GUIアプリを動かす記事と同様の変更です)

Insider Preview(ビルド21362以降)の方向けの案内を追記しました(2021/6/14)

Windows 10 Insider Preview(ビルド21362以降)ではWSLgのプレビュー版が利用できるようになりました。これに関する案内を追記しました。

Windows 11 Insider Previewの方向け案内を追記しました(2021/7/10)

Windows 11 Insider PreviewでのWSLgインストール方法の紹介記事も執筆しましたので、その案内を追記しました。