Nagrywaj wyjście programu za pomocą PulseAudio

49

Chciałbym nagrać wyjście programu za pomocą PulseAudio przy użyciu wiersza poleceń / skryptu bash. Ważne jest, aby nie rejestrować wszystkich danych wyjściowych, a tylko dane wyjściowe z jednego określonego programu.

Pomyślałem, że będę musiał utworzyć nowy zerowy zlew i przenieść dane wyjściowe programu do tego nowego zlewu. Następnie powiedz parec, aby używał tego konkretnego monitora do nagrywania.

Pierwszym krokiem byłoby coś takiego:

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

Ale jak przenieść teraz wyjście programu do tego zlewu?
A jak nagrać konkretny zlew za pomocą skryptu bash?

użytkownik5950
źródło

Odpowiedzi:

52

Wypróbuj coś takiego:

W terminalu wpisz

pacmd

(jest to CLI serwera PulseAudio-Server), a następnie użyj

list-sink-inputs

(gdzie otrzymujesz indeksy bieżących danych wejściowych) Teraz znajdź indeks danych wejściowych. Teraz określany jako $ INDEX

część skryptowa to:

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 -

Objaśnienia:

  • Pierwsze polecenie doda zlew zerowy, jak już wiesz.
  • Drugie polecenie przenosi wejście zlewu ze standardowego zlewu audio do pary
  • Trzecie polecenie rejestruje monitor pary urządzenia (-d) i umieszcza dane wyjściowe (nieprzetworzony strumień falowy) w oggenc, który koduje ten strumień falowy do pliku oga. (dla mp3 użyj lame)
Waschtl
źródło
Świetnie, dziękuję bardzo za tę wspaniałą odpowiedź! :)
Force
2
czy możesz wyjaśnić, jak cofnąć tę operację? moje zlewozmywaki zerowe są nadal mapowane do różnych aplikacji, a teraz nie mam dźwięku!
ixtmixilix,
@ixtmixilix: najprostszym sposobem na przywrócenie wszystkich ustawień do wartości domyślnych jest po prostu zabicie i zrestartowanie serwera pulseaudio. Jeśli ustawione na autospawn (jest to ustawienie domyślne), po prostu wydajesz pulseaudio -kw terminalu.
Takkat
1
@ixtmixilix Po uruchomieniu list-sink-inputszanotuj sinkwartość. Aby zamienić z powrotem, po prostu biegnij pactl move-sink-input $INDEX $SINK. Coś w stylupactl move-sink-input 4719 1
Ciaran
27

Poprawianie odpowiedzi Waschtl w tym wątku, abyś mógł ZARÓWNO SŁUCHAĆ I NAGRYWAĆ dźwięk aplikacji:

Najpierw szukamy naszego domyślnego wyjścia i umieszczamy jego nazwę ujścia w $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

Następnie tworzymy połączony zlew, który ma tylko jedno urządzenie podrzędne: $ DEFAULT_OUTPUT . Dźwięk generowany przez aplikację (źródło) zostanie przesłany do zlewu podrzędnego (tj. Rzeczywista moc wyjściowa), a my również go nagramy. Różni się od zlewu zerowego, w którym dźwięk źródłowy nie jest przekazywany.

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

sink_properties jest opcjonalny i może powodować błędy, jeśli używasz spacji w nazwie opisu.

Następnie moglibyśmy użyć pactl move-sink-input ...polecenia odpowiedzi Waschtla (z funkcją Record-n-Play zamiast Steam ), ale GUI pavucontroljest prostsze (i doskonałe do sprawdzania / rozwiązywania problemów):

$ sudo apt-get install pavucontrol
$ pavucontrol &

Następnie odtwarzamy dźwięk w aplikacji, którą chcemy nagrać. W pavucontrol Playbackzakładce wybieramy z rozwijanej listy aplikacji: „Record-and-Play” .

Wreszcie, jesteśmy w stanie nagrywać i słuchać jednocześnie! ( lame przykład mp3, uruchom na pierwszym planie)

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

Lub możemy nagrywać w tle i zatrzymać w dowolnym momencie:

$ 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:

  • Aby cofnąć wiadomość lub ponowić procedurę: Usuń lub zresetuj zlewy za pomocą tej odpowiedzi . pulseaudio -kdziała świetnie, aby zresetować wszystko do ustawień domyślnych sesji.
  • Jeśli zmienimy domyślne wyjście w Ustawieniach dźwięku systemu, niestandardowe ustawienie Odtwarzania aplikacji zostanie zastąpione i będziemy musieli wrócić w pavucontrol, aby przywrócić łączny interfejs.
  • Aby móc słuchać dźwięku z kilku „prawdziwych” interfejsów (np. Słuchawek, wyjścia HDMI itp.), Powinniśmy uwzględnić wszystkie „rzeczywiste” wyjścia, których możemy użyć do słuchania, jako slink slave z funkcją nagrywania i odtwarzania , takich jak: pactl load-module module-combine-sink sink_name=record-n-play slaves=real-output-1,real-output-2.

EDYCJA: Uważaj, ponieważ od Ubuntu 18 (być może również 17), połączony zlew staje się domyślnym systemowym urządzeniem wyjściowym, a nie rzeczywistym urządzeniem wyjściowym. Dlatego zmiana głośności za pomocą ikony dźwięku w zasobniku systemowym wpływa na dźwięk nagrania. Obejście: Po utworzeniu połączonego zlewu otwórz pavucontrolkartę Wyjście. Wybierz „Widok: wirtualne urządzenia wyjściowe” i zresetuj głośność połączonego zlewu do 100%. Następnie wybierz „Widok: sprzętowe urządzenia wyjściowe” i naciśnij zieloną ikonę „Zdefiniuj jako alternatywę” na rzeczywistym urządzeniu wyjściowym.

KrisWebDev
źródło
9

Odpowiedź Waschtla jest fantastyczna. @ixtmixilix zapytał o przywrócenie normalnego dźwięku po zakończeniu nagrywania. Oto najprostszy sposób, jaki znam:

Zainstaluj i uruchom pavucontrolGUI. Powinieneś zobaczyć swoją aplikację do odtwarzania dźwięku i jej miernik głośności pod Playbackzakładką. Obok będzie przycisk pokazujący, że gra na Null Output . Kliknij na to i zmień na zwykłe wyjście audio, W moim przypadku Wbudowane Audio Analogowe Stereo .

Oto zrzut ekranu tego, czego szukasz:

zrzut ekranu

Możesz również użyć tego podejścia, aby skonfigurować nagranie w przyszłości, po uruchomieniu load-modulepolecenia w odpowiedzi @ Waschtl, aby utworzyć zlew.

Jack O'Connor
źródło
Jeśli możesz, prześlij zrzut ekranu w Imgur i umieść go w swojej odpowiedzi.
Lucio
Nie wiem, czy jest to wykonalne, ale myślę, że najlepszym sposobem jest zwolnienie modułu wyjściowego o wartości zerowej, aby nowe odtwarzanie nie odbierało go domyślnie
Jack
6

Poprawiając odpowiedź KrisWebDev , jeśli chcesz, aby funkcja nagrywania i odtwarzania była zawsze dostępna, najpierw sprawdź domyślne wyjście:

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

która wyświetli coś takiego:

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

Następnie utwórz plik ~/.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"

Proszę zamienić na alsa_output.pci-0000_00_1b.0.analog-stereodowolny wynik otrzymany z pacmdpolecenia. Pulse nie odczytuje domyślnego pliku konfiguracyjnego, gdy istnieje niestandardowy plik konfiguracyjny - dlatego pierwsza linia powyżej zawiera domyślny plik konfiguracyjny. W ten sposób pulseaudio nadal ładuje domyślną konfigurację jako pierwszą.

Uruchom, pulseaudio -kaby zabić bieżącą instancję pulseaudio, aby nowa została uruchomiona z nową konfiguracją.

Jeśli w dowolnym momencie chcesz cofnąć zmiany tutaj, po prostu usuń ~/.config/pulse/default.paplik i uruchom pulseaudio -k.

Jeśli chcesz, aby funkcja record-n-play była domyślnym ujściem dla wszystkich wyjść, możesz to zrobić, dodając jeszcze jeden wiersz na końcu ~/.config/pulse/default.pa:

set-default-sink record-n-play

W przypadku programów, w których pulseaudio już zapisało informacje, pamięta, na jakim urządzeniu wyjściowym używali ostatnio, więc będziesz musiał ręcznie przekonfigurować te, używając jednej z metod opisanych w odpowiedzi KrisWebDev.

Jonas Berlin
źródło
2

Stworzyłem ten skrypt bash na podstawie odpowiedzi udzielonych przez @Waschtl i @KrisWebDev.

Dostępne tutaj: https://gist.github.com/ramast/4be3314bc73f28f55e3604497188b007

Jak używać?

$ ./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

Nowa wersja

Stworzyłem skrypt Pythona, który oferuje kilka ulepszeń w stosunku do starego. https://gist.github.com/ramast/c47bd5e57586e9c2deb74975e27089f0

Jak używać?

$ ./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

Po naciśnięciu Enter nagrywanie rozpocznie się natychmiast. jeśli do czasu wciśnięcia wejdziesz aplikacja została już zatrzymana (np. zamknąłeś mplayera) skrypt zaczeka, aż aplikacja pojawi się ponownie i rozpocznie nagrywanie.

Jedyną wadą tego skryptu (w porównaniu do oryginalnego) jest to, że jeśli lista zawiera dwa wpisy o tej samej nazwie, skrypt nie będzie działał poprawnie. Na przykład

$ ./pulse-recorder.py                                                                                                      

1 - ALSA plug-in [mplayer]
2 - ALSA plug-in [mplayer]
Ramast
źródło
W przypadku, gdy masz wiele wyjść (np. Głośniki, kilka zestawów słuchawkowych, monitor audio), możesz zastąpić w linii 21 np.: Default_output = alsa_output.pci-0000_00_1b.0.analog-stereo, gdzie pochodzi z wyjścia listy pacmd -sinks
smaudet