Automatyczne wyciszanie dźwięku w PulseAudio

Spis treści

Wszystkie główne dystrybucje, a może raczej ich środowiska graficzne, wykorzystują do odtwarzania dźwięku serwer PulseAudio. Niektóre wręcz są tak z nim zżyte, że nie idzie ich oddzielić od siebie. Ja generalnie uważam, że ten kawałek oprogramowania jest jak najbardziej przydatny człowiekowi i potrafi realizować kilka kwestii, które bez niego, albo by nie były możliwe do osiągnięcia, albo trzeba by się natrudzić przy ich implementacji, np. przesyłanie dźwięku przez sieć. U siebie na debianie nigdy nie miałem większych problemów z PulseAudio, z kolei zaś te, które się przytrafiały na drodze jego użytkowania, szło w miarę prosty sposób wyeliminować. Jest jednak jeden problem, z którym prawdopodobnie spotkaliśmy się wszyscy, przynajmniej jeśli wykorzystujemy mikrofon w stopniu większym niż przeciętny użytkownik komputera. Chodzi o to, że po odpaleniu pewnych aplikacji (lub też i w trakcie ich działania), takich jak np. Skype, Mumble, czy TeamSpeak3, dźwięk we wszystkich pozostałych programach potrafi zwyczajnie zdechnąć.

Moduły zarządzające dźwiękiem

"Problem" leży oczywiście po stronie PulseAudio, a konkretnie jego modułów. W tej chwili interesują nas dwa z nich -- module-role-cork oraz module-role-ducking. Ten pierwszy nie ma, co prawda, dokumentacji ale wiemy, że jego zadaniem jest zatykać (mutować) strumienie pewnych aplikacji, które odtwarzają dźwięk w danej chwili, tak by inny program nie był przez nie zakłócany w żaden sposób. Raczej zdarzało nam się wyłączyć choć raz muzykę, gdy dzwonił do nas telefon, prawda? I właśnie to zachowanie próbuje zreprodukować za pośrednictwem tego modułu PulseAudio. Kłopot w tym, że nie zawsze chcemy tłumić wszelki dźwięk wydobywający się z głośników i zamiast mutować go, chcielibyśmy go nieco przyciszyć i za tego typu zachowanie odpowiada ten drugi moduł.

Blokada modułu odpowiedzialnego za wyciszenie dźwięku

Domyślnie w PulseAudio jest aktywny jedynie moduł module-role-cork, co sprawia, że cały dźwięk, za wyjątkiem tego jednego strumienia, np. Skype, jest wyciszany. Naturalnie możemy odmutować go ręcznie i wtedy oba strumienie powinny być odtwarzane bez problemu, przynajmniej do momentu wystąpienia jakiegoś zdarzenia, które znów przykręci śrubę wszystkim innym aplikacjom.

Jeśli drażni nas tego typu zachowanie i wolelibyśmy sami zatroszczyć się o zarządzanie poziomem dźwięku w aplikacjach, to mamy kilka wyjść z tej sytuacji. Jedno z nich zakłada całkowite usunięcie PulseAudio, co w wielu przypadkach może nie być możliwe ale lepszym wyjściem będzie nakazanie PulseAudio by zwyczajnie nie ładował modułu module-role-cork podczas swojego uruchamiania.

Konfiguracja modułów dla PulseAudio trzymana jest w pliku /etc/pulse/default.pa . Przechodzimy zatem do jego edycji i odszukujemy pozycję z module-role-cork , po czym komentujemy tę linijkę:

### Cork music/video streams when a phone stream is active
#load-module module-role-cork

Jeśli chcemy jedynie sprawdzić czy faktycznie problem tkwi w tym module, możemy wyładować go przy pomocy poniższego polecenia:

$ pactl load-module module-role-cork

Tak czy inaczej, problem automatycznego wyciszania dźwięku powinniśmy mieć raczej z głowy.

Aktywacja modułu ściszającego dźwięk

Generalnie rzecz biorąc, jestem za rozgraniczeniem aplikacji na te, które w obecnej chwili powinny być na pierwszym planie od tych wszystkich pozostałych ale znowu nie lubię absolutnej ciszy i przydałoby się zaprogramować PulseAudio, tak by jedynie ściszył szereg aplikacji bez ich kompletnego mutowania. By tego typu zachowanie wypracować, dodajemy poniższy kod do pliku /etc/pulse/default.pa :

load-module module-role-ducking trigger_roles=phone ducking_roles=music,video volume=60%

Możemy również ten moduł, wraz z jego opcjami, załadować w celu testowania regulacji:

$ pactl load-module module-role-ducking trigger_roles=phone ducking_roles=music,video volume=60%

Parę słów o module-role-ducking

Przydało by się kilka słów wyjaśnienia odnośnie samego modułu module-role-ducking i użytych w nim opcji. Przede wszystkim, PulseAudio potrafi rozróżniać strumienie dźwięku na podstawie ich właściwości, wobec czego każdy program odtwarzający dźwięk może być traktowany indywidualnie, choć ze względów praktycznych lepiej jest je sobie pogrupować. Kompletna lista właściwości, jakie możemy ustawić, znajduje się tutaj.

Pierwszy parametr jaki widzimy wyżej, tj. trigger_roles , wskazuje ona na właściwość aplikacji, której odpalenie objawiać się będzie ściszeniem dźwięku innych programów, które aktualnie coś nadają. Z tym, że niekoniecznie z automatu muszą to być wszystkie aplikacje dźwiękowe. Przy pomocy opcji ducking_roles określamy, które aplikacje mają być ściszane. Zatem w powyższym przypadku, jeśli strumień, który ma ustawioną opcję PA_PROP_MEDIA_ROLE na phone (czyli np. Skype), zostanie zainicjowany, spowoduje on automatyczne przyciszenie strumieni, które mają tę samą właściwość ustawioną na music lub video . Parametr volume określa co zrobić z dźwiękiem i w tym przypadku zostanie on przyciszony do poziomu 60% Z tym, że wartość tutaj możemy podawać w % , dB , albo jako zwykłą liczbę z zakresu 0-65536.

Tylko pozostaje jeden problem -- sporo programów w debianie (czy w ogóle linux'ie) nie ma ustawionych odpowiednich właściwości, co będzie się objawiać w taki sposób, że cześć z nich zwyczajnie zignoruje politykę, którą wyżej sobie ustawiliśmy, a ludzie winą obarczą jak zwykle PulseAudio... By uniknąć tego typu sytuacji, możemy ręcznie nadać wszystkim aplikacjom odtwarzającym dźwięk (w tym też i playery video) odpowiednie właściwości poprzez wyeksportowanie zmiennych systemowych. I tak dla przykładu, jako że potrzebujemy zmienić/nadać PA_PROP_MEDIA_ROLE , przepiszmy właściwości SMPlayer'owi:

PULSE_PROP='media.role=video' smplayer film.mp4

W przypadku jakichkolwiek błędów dobrze jest odpalić pulseaudio w trybie verbose via pulseaduio -D -v i prześledzić komunikaty pojawiające się przy odtwarzaniu strumieni. Przykładowo:

pulseaudio[61212]:     media.role = "video"
pulseaudio[61212]:     media.name = "audio stream"
pulseaudio[61212]:     application.name = "Amarok"
pulseaudio[61212]:     native-protocol.peer = "UNIX socket client"
pulseaudio[61212]:     native-protocol.version = "30"
pulseaudio[61212]:     application.id = "org.kde.phonon.amarok"
pulseaudio[61212]:     application.version = "2.8.0"
pulseaudio[61212]:     application.icon_name = "amarok"
pulseaudio[61212]:     application.language = "C"
pulseaudio[61212]:     application.process.id = "61277"
pulseaudio[61212]:     application.process.user = "morfik"
pulseaudio[61212]:     application.process.host = "morfikownia"
pulseaudio[61212]:     application.process.binary = "amarok"
pulseaudio[61212]:     window.x11.display = ":0"
pulseaudio[61212]:     application.process.machine_id = "159815709bbc46c29ef786cfc497afd4"
pulseaudio[61212]:     application.process.session_id = "1"
pulseaudio[61212]:     module-stream-restore.id = "sink-input-by-media-role:video"

I jak widzimy, amarok ma przypisaną rolę video .

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.