Fajne sztuczki z PipeWire

W tym wpisie postanowiłem udokumentować parę sztuczek dotyczących PipeWire i WirePlumbera, które zastosowałem u siebie, zanim o nich zapomnę ;)

Jak zmienić nazwę urządzenia?

Jest to zmiana kosmetyczna, ale chyba możemy się zgodzić, że np. Starship/Matisse HD Audio Controller jako nazwa zintegrowanej karty dźwiękowej we wszystkich panelach głośności nie wygląda specjalnie ładnie, prawda? Na szczęście możemy to dość łatwo naprawić:

  1. Najpierw szukamy node.name dla wybranego urządzenia za pomocą używając komedy pw-dump (albo na przykład w pw-top). Po prostu szukamy jego nazwy i spisujemy wartość node.name znajdującą się poniżej. W moim przypadku było to alsa_output.pci-0000_09_00.4.analog-stereo.
  2. Tworzymy plik ~/.config/wireplumber/main.lua.d/51-alsa-config.lua (sama nazwa nie jest istotna, dopóki prefiks jest większy od 50 i jest rozszerzenie .lua) o treści:
    rule_hda = {
      matches = {
        {
          { "node.name", "equals", "alsa_output.pci-0000_09_00.4.analog-stereo" },
        },
        {
          { "node.name", "equals", "alsa_input.pci-0000_09_00.4.analog-stereo" },
        },
      },
      apply_properties = {
        ["node.description"] = "HDA",
      },
    }
    
    table.insert(alsa_monitor.rules,rule_hda)
    

    Jak widzicie, dodałem DWA warunki, jeden dla wejścia, drugi dla wyjścia, żeby mieć tę samą etykietę dla obu, ale jeśli chcecie, możecie zrobić inaczej. Najistotniejsza część to przypisanie node.description. W moim przypadku wybrałem podpis "HDA".Możecie też zmienić node.nick, który też jest czasem używany przy wyświetlaniu nazw urządzeń przez programy. Wystarczy, że dodacie analogiczną linijkę z tą zmienną w apply_properties.

Jak nie zapisywać domyślnych wyjść/wejść?

Domyślnie WirePlumber pamięta jakie wejścia i wejścia były powiązane z danym programem. Osobiście wolę, gdy używane jest domyślne wyjście i przenosić strumienie sam, jeśli zajdzie potrzeba. Dlatego wyłączyłem zapisywanie wyjść i wejść tworząc plik ~/.config/wireplumber/main.lua.d/41-stream-defaults.lua o następującej treści:

rule_restore_target = {
    matches = {
      {
        { "application.name", "matches", ".*" },
      },
    },
    apply_properties = {
      ["state.restore-target"] = false,
      ["state.restore-props"] = false,
    },
}

table.insert(stream_defaults.rules,rule_restore_target)

Jak wygodnie łączyć wejścia/wyjścia?

Chcecie połączyć wejścia w nietypowy sposób, np. puścić dźwięk z mikrofonu do dwóch różnych wyjść jednocześnie albo przekierować wyjście z przeglądarki internetowej do OBS albo Audacity? Moim zdaniem najprostszym sposobem jest użycie programu qpwgraph.

Jego okno przedstawia reprezentację wszystkich wejść i wyjść w systemie. Każdy szary prostokąt to jedno urządzenie. Zielone etykiety wyrównane do lewej oznaczają wejścia, a wyrównane do prawej wyjścia.

Aby połączyć wejście, klikamy Connect i przeciągamy linię między wybranym wejściem i wyjściem... i tyle! Jak widać, dla urządzeń stereo oba kanały wyświetlane są osobno, więc proces będziecie musieli powtórzyć dla obu.

Rozłączanie połączeń jest jeszcze prostsze - klikamy Disconnect, a potem linię, którą chcemy rozłączyć.

Domyślnie zmiany nanoszone w programie są ulotne, ale układ można zapisać i wczytać ponownie w menu Patchbay -> Open / Save. Jeśli chcemy, by program wymuszał nasz układ, gdy pojawią się odpowiednie strumienie (np. by nie musieć łączyć strumieni ponownie po restarcie przeglądarki), musimy zaznaczyć opcję Patchbay -> Activated. Oczywiście program musi być uruchomiony w tle, by ta funkcja działała. Taki patchbay może być bardzo przydatny dla streamerów albo osób nagrywających gameplay z gier. Warto dodać, że pod Waylandem to samo narzędzie powinno też umożliwiać zrobienie tego samego dla strumieni wideo z kamerek czy screen capture, ale nie miałem okazji tego sam przetestować.

No dobra, a co, jeśli nie potrzebujecie ładnego gui i wolicie odpalić drobny skrypt zamiast instalować kolejny program? Cóż, badając temat znalazłem też coś o nazwie pw-easylink. Jest to prosty skrypt działający w tle i łączący wejścia według podanych filtrów. Dla każdego coś miłego ;)

Jak wyłączyć usypianie nieaktywnych wejść/wyjść?

Domyślnie PipeWire usypia nieużywane wyjścia po paru sekundach nieaktywności. W przypadku niektórych urządzeń jest to o tyle uciążliwe, że powoduje drobne pyknięcia czy chwilę ciszy przy budzeniu urządzenia. Można to zmienić tworząc (a w moim przypadku uzupełniając) plik ~/.config/wireplumber/main.lua.d/51-alsa-config.lua o treści:

rule_suspend = {
    matches = {
      {
        -- Matches all sources.
        { "node.name", "matches", "alsa_input.*" },
      },
      {
        -- Matches all sinks.
        { "node.name", "matches", "alsa_output.*" },
      },
    },
    apply_properties = {
      ["session.suspend-timeout-seconds"] = 0,  -- 0 disables suspend
    },
}

table.insert(alsa_monitor.rules,rule_suspend)

Jak ustawić rnnoise?

Jeśli chcecie dodać do systemu wejście odszumiające dźwięk za pomocą rnnoise, możecie to zrobić w następujący sposób:

  1. Zainstalować librnnoise (w przypadku Gentoo jest to pakiet media-libs/noise-suppression-for-voice)
  2. Utworzyć plik ~/.config/pipewire/pipewire.conf.d/rnnoise.conf (zaadaptowane stąd) o następującej treści:
    context.modules = [
        { name = libpipewire-module-filter-chain
            args = {
                node.description =  "Noise Canceling source"
                media.name =  "Noise Canceling source"
                filter.graph = {
                    nodes = [
                        {
                            type = ladspa
                            name = rnnoise
                            plugin = /usr/lib64/ladspa/librnnoise_ladspa.so
                            label = noise_suppressor_stereo
                            control = {
                                "VAD Threshold (%)" 50.0
                            }
                        }
                    ]
                }
                capture.props = {
                    node.name =  "capture.rnnoise_source"
                    node.passive = true
                }
                playback.props = {
                    node.name =  "rnnoise_source"
                    media.class = Audio/Source
                }
            }
        }
    ]
    

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *