Compartir una transmisión de audio de micrófono en Linux

Aug 23 2020

Por mucho que importe, mi escenario es desarrollar una aplicación de accesibilidad, no cualquier tipo de espionaje malicioso, mientras que también dentro de este escenario hay varios escenarios implícitos de investigación y desarrollo, todos los cuales deberían beneficiarse enormemente de poder leer el flujo de audio del micrófono por múltiples ejecutando simultáneamente procesos no relacionados, como herramientas de grabación y/o diferentes versiones de mi propio código.

Planteamiento del problema

Estoy leyendo un flujo de entrada de micrófono usando una API de Python de alto nivel como la siguiente:

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)

Me gustaría saber si es posible (en Linux) leer el flujo de audio del micrófono simultáneamente a otro programa como Google Meet / Zoom leyéndolo. Es decir, comparte efectivamente el flujo de audio.

Al igual que con el contenedor de python mencionado, no es una gran sorpresa que cuando se inicia el código anterior mientras una videollamada está en curso, simplemente no podrá abrir la transmisión:

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

Es cierto que todavía no estoy muy familiarizado con la terminología de ALSA y, en general, con la pila de sonido en Linux.

Mi pregunta es, ¿se puede lograr esto directamente usando la API de la biblioteca ALSA, o de otra manera a través de otras pilas de sonido o configuración del sistema de sonido? ¿O si todo lo demás no está destinado a funcionar, a través de un programa/controlador proxy que pueda exponer un búfer de audio a múltiples consumidores sin incurrir en una degradación notable en la latencia de la transmisión de audio?

Respuestas

5 MatthewSalvatoreViglione Aug 26 2020 at 02:14

Puedes hacerlo directamente con ALSA. Dsnoop debería hacer el truco. Es un complemento incluido con ALSA que permite compartir flujos de entrada.

De la página que vinculé arriba:

dsnoopes el equivalente al dmixcomplemento, pero para grabar sonido. El dsnoopcomplemento permite que varias aplicaciones graben desde el mismo dispositivo simultáneamente.

De los documentos ALSA :

Si desea utilizar múltiples clientes de entrada (captura), debe utilizar el complemento dsnoop:

Puede hurgar allí para obtener detalles sobre cómo usarlo. Este problema en GitHub también lo ayudará a comenzar, detalla cómo configurar la dsnoopinterfaz para que pueda leer desde ella con pyaudio.

Actualizar

Para configurar ALSA, edite /etc/asound.confcon algo como esto (de los documentos de ALSA en 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
         }
 }

Puede probar para ver si su configuración funciona con algo como esto:

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

Entonces, supongo que esta es más una pregunta de audio que una pregunta de Python. :) Dependiendo de la API, las transmisiones pueden ser exclusivas del dispositivo o no. ASIO para audio profesional, por ejemplo, a menudo es exclusivo del dispositivo, por lo que solo una aplicación (como un DAW) tiene acceso a él. En Windows, por ejemplo, puede activar y desactivar esto como se ve aquí:

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

La mayoría de los paquetes de Python como pyaudio, etc., solo proporcionan enlaces para portaudio, que hace el trabajo pesado, así que también eche un vistazo a la documentación de portaudio. Portaudio "combina" todas las diferentes API como ASIO, ALSA, WASAPI, Core Audio, etc.

Para que ALSA cree más de una transmisión al mismo tiempo, es posible que necesite dmix, eche un vistazo a esta pregunta de Stackoverflow:https://unix.stackexchange.com/questions/355662/alsa-doesnt-work-when-multiple-applications-are-opened