Condivisione di un flusso audio del microfono su Linux
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
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 deldmix
plugin, ma per la registrazione del suono. Ildsnoop
plug-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' dsnoop
interfaccia in modo da poter leggere da essa con pyaudio
.
Aggiornare
Per configurare ALSA, modifica /etc/asound.conf
con 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
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