Condivisione di un flusso audio del microfono su Linux

Aug 23 2020

Per quanto sia importante, il mio scenario è lo sviluppo di un'applicazione di accessibilità, non un qualsiasi tipo di intercettazione dannosa, mentre anche all'interno di questo scenario ci sono vari scenari impliciti di ricerca e sviluppo, ognuno dei quali dovrebbe trarre grande vantaggio dalla possibilità di leggere il flusso audio del microfono da più eseguire contemporaneamente processi non correlati come strumenti di registrazione e/o versioni diverse del mio codice.

Dichiarazione problema

Sto leggendo un flusso di input del microfono utilizzando un'API Python di alto livello come segue:

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)

Vorrei sapere se è possibile (su Linux) leggere il flusso audio del microfono contemporaneamente a un altro programma come Google Meet/Zoom che lo legge. Vale a dire condividere efficacemente il flusso audio.

Come per il wrapper python menzionato, non sorprende che quando il codice sopra viene avviato mentre è in corso una videochiamata, semplicemente non riuscirà ad aprire lo stream:

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

Devo ammettere che non sono ancora molto esperto della terminologia ALSA e in generale del sound stack su Linux.

La mia domanda è: è possibile farlo direttamente utilizzando l'API della libreria ALSA o in altro modo tramite altri stack audio o configurazione del sistema audio? O se tutto il resto non è pensato per funzionare, tramite un programma/driver proxy in grado di esporre un buffer audio a più consumatori senza incorrere in un notevole degrado della latenza del flusso audio?

Risposte

5 MatthewSalvatoreViglione Aug 26 2020 at 02:14

Puoi farlo direttamente con ALSA. Dsnoop dovrebbe fare il trucco. È un plugin incluso in ALSA che consente la condivisione di flussi di input.

Dalla pagina che ho linkato sopra:

dsnoopè l'equivalente del dmixplugin, ma per la registrazione del suono. Il dsnoopplug-in consente a più applicazioni di registrare contemporaneamente dallo stesso dispositivo.

Dai documenti ALSA :

Se si desidera utilizzare più client di input (acquisizione) è necessario utilizzare il plug-in dsnoop:

Puoi curiosare lì per i dettagli su come usarlo. Questo problema su GitHub ti aiuterà anche a iniziare, descrive in dettaglio come configurare l' dsnoopinterfaccia in modo da poter leggere da essa con pyaudio.

Aggiornare

Per configurare ALSA, modifica /etc/asound.confcon qualcosa di simile (dai documenti ALSA su 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
         }
 }

Puoi testare per vedere se la tua configurazione funziona con qualcosa del genere:

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

Quindi, questa è più una domanda audio che una domanda Python, immagino. :) A seconda dell'API, gli stream possono essere esclusivi o meno per dispositivo. ASIO per l'audio professionale, ad esempio, è spesso esclusivo del dispositivo, quindi solo un'applicazione (come una DAW) ha accesso ad esso. Su Windows, ad esempio, puoi attivarlo e disattivarlo come mostrato qui:

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

La maggior parte dei pacchetti Python come pyaudio e così via forniscono solo collegamenti per portaudio, che fa il lavoro pesante, quindi dai anche un'occhiata alla documentazione di portaudio. Portaudio "combina" tutte le diverse API come ASIO, ALSA, WASAPI, Core Audio e così via.

Affinché ALSA crei più di uno stream contemporaneamente potresti aver bisogno di dmix, dai un'occhiata a questa domanda di StackOverflow:https://unix.stackexchange.com/questions/355662/alsa-doesnt-work-when-multiple-applications-are-opened