Linuxでマイクオーディオストリームを共有する

Aug 23 2020

重要なのは、私のシナリオは、悪意のある盗聴ではなく、アクセシビリティアプリケーションを開発することですが、このシナリオには、さまざまな研究開発の暗黙のシナリオがあります。これらはすべて、マイクのオーディオストリームを複数回読み取ることができることで大きなメリットが得られるはずです。記録ツールや自分のコードの異なるバージョンなど、無関係なプロセスを同時に実行します。

問題文

次のような高レベルのPythonAPIを使用してマイク入力ストリームを読み取っています。

import sounddevice

audio_stream = sounddevice.InputStream(
  device=self.microphone_device,
  channels=max(self.channels),
  samplerate=self.audio_props['sample_rate'],
  blocksize=int(self.audio_props['frame_elements_size']),
  callback=self.audio_callback)

(Linuxで)マイクのオーディオストリームを、Google Meet / Zoomなどの別のプログラムで同時に読み取ることができるかどうかを知りたいです。つまり、オーディオストリームを効果的に共有します。

前述のPythonラッパーと同様に、ビデオコールの進行中に上記のコードを開始すると、ストリームを開くことができなくなるのは当然のことです。

Expression 'paInvalidSampleRate' failed in 
'src/hostapi/alsa/pa_linux_alsa.c', line: 2043 
Expression 'PaAlsaStreamComponent_InitialConfigure( &self->playback, outParams, self->primeBuffers, hwParamsPlayback, &realSr )' 
failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2716 
Expression 'PaAlsaStream_Configure( stream, inputParameters, outputParameters, sampleRate, framesPerBuffer, &inputLatency, &outputLatency, &hostBufferSizeMode )' 
failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2837

確かに、私はALSAの用語と、一般的にはLinuxのサウンドスタックにまだ精通していません。

私の質問は、これはALSAライブラリAPIを使用して直接実行できますか、それとも他のサウンドスタックまたはサウンドシステム構成を介して実行できますか?または、オーディオストリームのレイテンシーを著しく低下させることなく、オーディオバッファーを複数のコンシューマーに公開できるプロキシプログラム/ドライバーを介して、他のすべてが機能することを意図していない場合はどうでしょうか。

回答

5 MatthewSalvatoreViglione Aug 26 2020 at 02:14

これはALSAで直接行うことができます。Dsnoopがそのトリックを実行する必要があります。これは、入力ストリームの共有を可能にするALSAに含まれているプラ​​グインです。

上でリンクしたページから:

dsnoopdmixプラグインと同等ですが、録音用です。dsnoopプラグインは、いくつかのアプリケーションが同時に同じデバイスから録音することができます。

ALSAドキュメントから:

複数の入力(キャプチャ)クライアントを使用する場合は、dsnoopプラグインを使用する必要があります。

使い方の詳細については、あちこちを見て回ることができます。GitHubのこの問題は、開始するのにも役立ちます。dsnoopインターフェイスを構成して、から読み取ることができるようにする方法について詳しく説明しますpyaudio

更新

ALSAを構成するには/etc/asound.conf、次のように編集します(ALSAのドキュメントからdsnoop):

pcm.mixin {
         type dsnoop
         ipc_key 5978293 # must be unique for all dmix plugins!!!!
         ipc_key_add_uid yes
         slave {
                 pcm "hw:1,0"
                 channels 2
                 period_size 1024
                 buffer_size 4096
                 rate 44100
                 periods 0
                 period_time 0
         }
         bindings {
                 1 1
                 1 0
         }
 }

構成が次のようなもので機能するかどうかをテストして確認できます。

arecord -d 30 -f cd -t wav -D pcm.mixin test.wav 
2 ArjaanAuinger Aug 23 2020 at 19:27

ですから、これは私が推測するPythonの質問というよりも音声の質問です。:) APIに応じて、ストリームはデバイス専用にすることも、しないこともできます。たとえば、プロフェッショナルオーディオ用のASIOはデバイス専用であることが多いため、1つのアプリケーション(DAWなど)だけがアクセスできます。たとえばWindowsでは、次のようにこれをオンまたはオフにできます。

https://help.ableton.com/hc/en-us/articles/209770485-Disabling-exclusive-mode-for-ASIO-interfaces

pyaudioなどのほとんどのPythonパッケージは、portaudioのバインディングを提供しているだけなので、手間がかかるので、portaudioのドキュメントも参照してください。Portaudioは、ASIO、ALSA、WASAPI、CoreAudioなどのさまざまなAPIをすべて「結合」します。

ALSAが同時に複数のストリームを作成するためにdmixが必要になる場合は、次のStackoverflowの質問をご覧ください。 https://unix.stackexchange.com/questions/355662/alsa-doesnt-work-when-multiple-applications-are-opened