Emulando entrada de microfone para o Chrome dentro do contêiner do Docker

3

Antecedentes

Estou tentando controlar a entrada para um aplicativo da Web WebRTC em execução no Chrome, controlado pelo Selenium, dentro de um contêiner do Docker.

Isso faz parte de um teste automatizado do aplicativo WebRTC.
Como parte do teste, eu preciso ser capaz de verificar se o áudio está sendo recebido do outro lado quando deveria ser.
Basicamente, quero verificar se um cliente fala, o outro cliente o ouve e vice-versa, a menos que o cliente esteja em silêncio.

Agora, posso fazer com que o Chrome emule facilmente a entrada de microfone (e câmera) iniciando-o com os parâmetros da linha de comando:

--use-fake-ui-for-media-stream
--use-fake-device-for-media-stream

Qual tem o problema que o exemplo padrão tem muito silêncio nele (mais difícil de detectar). Eu posso resolver isso fornecendo meu próprio arquivo de áudio com áudio mais consistente:

--use-file-for-fake-audio-capture=/opt/media/audio1.wav

Mas isso tem outro problema: se o Chrome está enviando e recebendo áudio ao mesmo tempo, o áudio recebido é severamente afetado, quase em completo silêncio, como parte da funcionalidade de cancelamento de eco do Chrome. (O cancelamento de eco é definido como parte do aplicativo WebRTC e não como parte do próprio Chrome, e eu não quero fazer alterações no código que está sendo testado para facilitar o teste.)
Usando duas amostras diferentes (uma para cada cliente) ajuda um pouco, mas não muito.

O verdadeiro problema é que ambos os clientes "falam" sem parar enquanto estão em execução, o que atrapalha o áudio por causa do cancelamento de eco mencionado anteriormente, e também não é um cenário realista para testar porque as pessoas não geralmente não se falam constantemente.

Eu poderia teoricamente usar amostras especialmente criadas com seções intencionais de ruído / silêncio nelas, mas alinhar essas amostras entre clientes e com a validação do teste seria um pesadelo.

Problema

O que eu realmente preciso é poder iniciar e parar a reprodução de áudio no cliente sob demanda.

Parece não haver nenhuma maneira de controlar o fluxo de mídia falso no Chrome, então parece que minha melhor opção é provavelmente criar um dispositivo de entrada de áudio "microfone" falso dentro do contêiner do Docker e controlar isso .

Em um Linux padrão, você pode usar o pulseaudio para fazer o loop da saída de áudio de volta como um dispositivo de captura, o que parece promissor, mas não sei como usá-lo em um contêiner Docker.
O contêiner do Docker nem tem dispositivos de áudio para usá-lo. Eu encontrei vários guias sobre como configurar um Docker para usar o hardware de áudio da máquina host, mas isso não é muito útil, pois esses contêineres estão sendo executados em servidores eSXI e não possuem placas de som para usar. br> O Pulseaudio também suporta dispositivos virtuais, mas esses precisam de drivers / módulos do kernel para funcionar. Eu posso estar errado, mas eu não acho que você pode usá-los dentro de um contêiner Docker.

Pergunta

Desculpe se o acima foi um pouco prolixo, mas eu estava tentando explicar o problema e as várias direções que eu já olhei.

Então, alguém sabe como controlar a entrada de áudio no dispositivo de captura do Chrome dentro de um contêiner Docker, usando um dispositivo de captura falso ou por outros meios?

    
por Nameless Voice 23.06.2017 / 17:21

1 resposta

2

Consegui encontrar uma solução para isso. O conceito básico é bastante simples, mas tem algumas dicas para contornar.

A solução envolve o uso da capacidade do pulseaudio de criar fontes de áudio virtuais e a ferramenta paplay para reproduzir mídia nesse dispositivo de áudio.

Configurando o contêiner docker

Eu precisava criar minha própria imagem do Docker, com base na imagem do Ubuntu / Chrome / Selenium que eu já estava usando, para instalar o pacote pulseaudio, ajustar o ponto de entrada para iniciá-lo e adicionar alguns arquivos de áudio para reproduzir. / p>

dockerfile:

FROM selenium/standalone-chrome-debug

# Install pulse audio
RUN apt-get -qq update && apt-get install -y pulseaudio

# Copy some media files into place
RUN mkdir -p /opt/media
COPY audio1.wav /opt/media/audio1.wav
COPY audio2.wav /opt/media/audio2.wav

# Use custom entrypoint
COPY entrypoint.sh /opt/bin/entrypoint.sh

ENTRYPOINT /opt/bin/entrypoint.sh

Depois, precisei de um ponto de entrada personalizado para iniciar o servidor pulseaudio e configurar uma fonte de áudio personalizada, antes de iniciar o ponto de entrada de inicialização padrão do Selenium.
Há dois dispositivos virtuais aqui para que um possa ser usado para reprodução de áudio sem que seja canalizado para o microfone virtual.

entrypoint.sh

# Load pulseaudio virtual audio source
pulseaudio -D --exit-idle-time=-1

# Create virtual output device (used for audio playback)
pactl load-module module-null-sink sink_name=DummyOutput sink_properties=device.description="Virtual_Dummy_Output"

# Create virtual microphone output, used to play media into the "microphone"
pactl load-module module-null-sink sink_name=MicOutput sink_properties=device.description="Virtual_Microphone_Output"

# Set the default source device (for future sources) to use the monitor of the virtual microphone output
pacmd set-default-source MicOutput.monitor

# Create a virtual audio source linked up to the virtual microphone output
pacmd load-module module-virtual-source source_name=VirtualMic

# Allow pulse audio to be accssed via TCP (from localhost only), to allow other users to access the virtual devices
pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1

# Configure the "seluser" user to use the network virtual soundcard
mkdir -p /home/seluser/.pulse
echo "default-server = 127.0.0.1" > /home/seluser/.pulse/client.conf
chown seluser:seluser /home/seluser/.pulse -R


# Start Selenium-Chrome-Standalone
/opt/bin/entry_point.sh

Como desejo usar o dispositivo de áudio em uma instância controlada pelo Selenium do Chrome, que é executada como o usuário "seluser", precisei expor a placa de som virtual via TCP (somente para conexões localhost) e, em seguida, configurar seluser para usar essa placa de som em rede. Nenhuma configuração adicional é necessária. A fonte virtual é o único dispositivo de entrada de áudio na imagem do Docker, pelo que o Chrome a utilizará automaticamente. Tudo o que resta é construir e executar o contêiner docker.

Reproduzindo o áudio

Quando o contêiner está em execução, usei paplay para enviar mídia para o dispositivo de saída virtual, que chamei de "MicOutput" acima. Isso pode ser acionado por meio de um comando exec:

docker exec -t -i TestContainerName paplay --device=MicOutput /opt/media/audio2.wav

E é isso.

Claro, eu também precisava usar a opção "--use-fake-ui-for-media-stream" nas capacidades do Chrome ao configurar meu Selenium WebDriver, para permitir que o Selenium usasse o dispositivo sem perguntar, mas tinha que fazer Certifique-se de não usar a opção "--use-fake-device-for-media-stream", pois isso substituiria o dispositivo de entrada falso pelo built-in do Chrome.

Obrigado à resposta da spacepickle à esta pergunta por me colocar no caminho certo, e ao post de Eli Billauer on usando o pulso de áudio para vários usuários

    
por 26.06.2017 / 17:12