Grave a saída de um programa com o PulseAudio

49

Gostaria de gravar uma saída de um programa com o PulseAudio usando script de linha de comando / bash. É importante não registrar toda a saída, mas apenas a saída de um programa específico.

Eu pensei que teria que criar um novo coletor nulo e depois mover a saída do programa para esse novo coletor. Diga ao parec para usar este monitor específico para gravar.

O primeiro passo seria algo como isto:

pactl load-module module-null-sink sink_name=steam

Mas como mover a saída do programa agora para esse coletor?
E como gravar o coletor específico com um script bash?

user5950
fonte

Respostas:

52

Tente algo como isto:

Em um terminal, digite

pacmd

(esta é a CLI do PulseAudio-Server), use

list-sink-inputs

(onde você obtém os índices das entradas em execução) Agora encontre o índice da sua entrada. Agora referido como $ INDEX

a parte programável é:

pactl load-module module-null-sink sink_name=steam
pactl move-sink-input $INDEX steam
parec -d steam.monitor | oggenc -b 192 -o steam.ogg --raw -

Explicações:

  • O primeiro comando adicionará um coletor nulo, como você já sabia.
  • O segundo comando move a entrada do coletor do coletor de áudio padrão para o vapor
  • O terceiro comando registra o monitor do dispositivo steam (-d) e coloca a saída (raw-wave-stream) em oggenc, que codifica esse wave-stream em um arquivo oga. (para mp3 use coxo)
Waschtl
fonte
Brilhante, muito obrigado por esta ótima resposta! :)
Força
2
você pode explicar como desfazer esta operação? meus sumidouros nulos ainda estão mapeados para várias aplicações e agora não tenho som!
Ixtmixilix
@ixtmixilix: a maneira mais fácil de restaurar todas as configurações padrão é simplesmente matar e reiniciar o servidor pulseaudio. Se definido como autospawn (esse é o padrão), basta emitir pulseaudio -kem um terminal.
Takkat 02/03
1
@ixtmixilix Ao executar, list-sink-inputsanote o sinkvalor. Para trocar de volta, basta executar pactl move-sink-input $INDEX $SINK. Algo comopactl move-sink-input 4719 1
Ciaran
27

Melhorando a resposta Waschtl deste tópico, para que você possa ouvir e gravar o som do aplicativo:

Primeiro, procuramos nossa saída padrão e colocamos seu nome de coletor em $DEFAULT_OUTPUT:

$ pacmd list-sinks | grep -A1 "* index"
  * index: 1
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
$ DEFAULT_OUTPUT=$(pacmd list-sinks | grep -A1 "* index" | grep -oP "<\K[^ >]+")
$ echo $DEFAULT_OUTPUT
alsa_output.pci-0000_00_1b.0.analog-stereo

Em seguida, criamos um coletor combinado que possui apenas um escravo: $ DEFAULT_OUTPUT . O som gerado pelo aplicativo (fonte) será encaminhado para o coletor de escravos (ou seja, saída real) e também será gravado. É diferente de um coletor nulo onde o som da fonte não é encaminhado.

$ pactl load-module module-combine-sink \
  sink_name=record-n-play slaves=$DEFAULT_OUTPUT \
  sink_properties=device.description="Record-and-Play"

sink_properties é opcional e pode apresentar erros se você usar espaços no nome da descrição.

Em seguida, poderíamos usar o pactl move-sink-input ...comando Waschtl answer (com record-n-play em vez de steam ), mas a GUI pavucontrolé mais simples (e ótima para verificar / solucionar problemas):

$ sudo apt-get install pavucontrol
$ pavucontrol &

Em seguida, reproduzimos algum som no aplicativo que queremos gravar. Na pavucontrol Playbackguia, selecionamos na lista suspensa do aplicativo: "Record-and-Play" .

Por fim, é bom gravar e ouvir ao mesmo tempo! ( exemplo mp3 coxo , executado em primeiro plano)

$ parec --format=s16le -d record-n-play.monitor | \
  lame -r --quiet -q 3 --lowpass 17 --abr 192 - "temp.mp3"

Ou podemos gravar em segundo plano e parar a qualquer momento:

$ parec --format=s16le -d record-n-play.monitor | \
  lame -r --quiet -q 3 --lowpass 17 --abr 192 - "temp.mp3" \
   > /dev/null &1>/dev/null
$ killall -q parec lame

NB:

  • Para desfazer tudo ou tentar novamente o procedimento: Exclua ou redefina os coletores usando esta resposta . pulseaudio -kfunciona muito bem para redefinir tudo para os padrões da sessão.
  • Se alterarmos a saída padrão nas Configurações de som do sistema, a configuração de reprodução do aplicativo personalizado será substituída e teremos que voltar no pavucontrol para configurá-la novamente na interface combinada.
  • Para poder ouvir o som de várias interfaces "reais" (por exemplo, fones de ouvido, saída HDMI, etc ...), devemos incluir todas as saídas "reais" que podemos usar para ouvir, como slaves de gravação e reprodução , como: pactl load-module module-combine-sink sink_name=record-n-play slaves=real-output-1,real-output-2.

EDIT: Cuidado, desde o Ubuntu 18 (talvez 17 também), o coletor combinado tende a se tornar o dispositivo de saída do sistema padrão, em vez do dispositivo de saída real. Portanto, quando você altera o volume usando o ícone de som na bandeja do sistema, afeta o som da gravação. Solução alternativa: após criar o coletor combinado, abra pavucontrolna guia Saída. Selecione "Exibir: dispositivos de saída virtual" e redefina o volume do som do coletor combinado para 100%. Em seguida, selecione "Visualizar: dispositivos de saída de hardware" e pressione o ícone verde "Definir como alternativa" no dispositivo de saída real.

KrisWebDev
fonte
9

A resposta de @ Waschtl é fantástica. O @ixtmixilix perguntou sobre a restauração do áudio normal após o término da gravação. Aqui está a maneira mais fácil que eu conheço:

Instale e execute a pavucontrolGUI. Você deve ver seu aplicativo de saída de áudio e seu medidor de volume na Playbackguia lá. Haverá um botão próximo a ele mostrando que está sendo reproduzido na Saída Nula . Clique nele e altere-o para a sua saída de áudio comum, estéreo analógico de áudio embutido no meu caso.

Aqui está uma captura de tela do que você está procurando:

captura de tela

Você também pode usar essa abordagem para configurar sua gravação no futuro, depois de executar o load-modulecomando na resposta de @ Waschtl para criar o coletor.

Jack O'Connor
fonte
Se você puder, envie uma captura de tela no Imgur e vincule-a à sua resposta.
Lucio
Não sei se é viável, mas acho que a melhor maneira é descarregar o módulo de saída nulo, para que novas reproduções não o atinjam por padrão
Jack
6

Melhorando ainda mais a resposta do KrisWebDev , se você deseja que o Record-n-play esteja sempre disponível, primeiro descubra a saída padrão:

pacmd list-sinks | grep -A1 "* index" | grep -oP "<\K[^ >]+"

que produzirá algo como:

alsa_output.pci-0000_00_1b.0.analog-stereo

Em seguida, crie um arquivo ~/.config/pulse/default.pa:

.include /etc/pulse/default.pa

load-module module-combine-sink sink_name=record-n-play slaves=alsa_output.pci-0000_00_1b.0.analog-stereo sink_properties=device.description="Record-and-Play"

Substitua alsa_output.pci-0000_00_1b.0.analog-stereopor qualquer saída que você obteve do pacmdcomando. O Pulse não lê o arquivo de configuração padrão quando existe um arquivo de configuração personalizado - é por isso que a primeira linha acima inclui o arquivo de configuração padrão. Dessa forma, o pulseaudio ainda carrega a configuração padrão primeiro.

Execute pulseaudio -kpara eliminar a instância atual do pulseaudio para que uma nova seja iniciada com a nova configuração.

Se a qualquer momento você quiser desfazer as alterações aqui, basta remover o ~/.config/pulse/default.paarquivo e executar pulseaudio -k.

Se você deseja que o record-n-play seja o coletor padrão para todas as saídas, você pode fazer isso adicionando mais uma linha ao final de ~/.config/pulse/default.pa:

set-default-sink record-n-play

Para programas nos quais o pulseaudio já possui informações armazenadas, ele se lembra de qualquer dispositivo de saída que eles usaram por último, então você terá que reconfigurar manualmente aqueles usando um dos métodos descritos na resposta do KrisWebDev.

Jonas Berlin
fonte
2

Criei esse script bash com base nas respostas fornecidas pelas respostas @Waschtl e @KrisWebDev.

Disponível aqui: https://gist.github.com/ramast/4be3314bc73f28f55e3604497188b007

Como usar?

$ ./pulse-recorder.bash 
    index: 225
                application.name = "ALSA plug-in [mplayer]"
                module-stream-restore.id = "sink-input-by-application-name:ALSA plug-in [mplayer]"
Choose recording index: 225
temp.mp3 file already exist, replace (y/n)? y

Nova versão

Eu criei um script python que oferece algumas melhorias em relação ao antigo. https://gist.github.com/ramast/c47bd5e57586e9c2deb74975e27089f0

Como usar?

$ ./pulse-recorder.py 

1 - ALSA plug-in [mplayer]
2 - AudioIPC Server

Please enter a number: 1

Your selection was: ALSA plug-in [mplayer]
Please press enter when you are ready to start

Quando você pressiona enter, a gravação começará imediatamente. se, no momento em que você pressionar Enter, o aplicativo já estiver parado (por exemplo, você fechou o mplayer), o script aguardará até que o aplicativo apareça novamente e comece a gravar.

A única desvantagem desse script (vs original) é que, se a lista contiver duas entradas com o mesmo nome, o script não se comportará corretamente. Por exemplo

$ ./pulse-recorder.py                                                                                                      

1 - ALSA plug-in [mplayer]
2 - ALSA plug-in [mplayer]
Ramast
fonte
No caso de você ter várias saídas (por exemplo, alto-falantes, vários fones de ouvido, monitorar o áudio), você pode substituir na linha 21 por exemplo: default_output = alsa_output.pci-0000_00_1b.0.analog-stereo, onde está na saída da lista pacmd -sinks
smaudet 10/0318