Como alternar entre diferentes hardwares de saída de áudio usando o shell?


34

Eu uso meu laptop com um monitor externo que possui alto-falantes. Quando o monitor é conectado via HDMI, posso alternar (usando a GUI: Configuração do som -> Hardware) entre a saída de áudio normal do laptop e a saída do monitor.

Repito esse procedimento muito tempo e comecei a pensar se posso automatizá-lo ou, de qualquer forma, executá-lo de maneira mais rápida usando o shell.

Minha distribuição é o Ubuntu 12.04 com o gnome 3.

EDITAR:

Tentei usar o pacmd, mas list-sinks me fornece apenas o dispositivo que estou usando atualmente:

pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_00_1b.0.hdmi-stereo>

Após uma mudança da GUI:

pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>

E se eu tentar mudar, recebo:

pacmd set-default-sink alsa_output.pci-0000_00_1b.0.hdmi-stereo
Welcome to PulseAudio! Use "help" for usage information.
Sink alsa_output.pci-0000_00_1b.0.hdmi-stereo does not exist.

Respostas:


28

Nesse caso, o cartão é sempre o mesmo. O que está mudando entre um switch e outro é o "perfil do cartão".

Portanto, a solução que realmente funcionou é:

pacmd set-card-profile <cardindex> <profilename>

No meu caso, encontrei todos os perfis de cartões com:

pacmd list-cards

E depois eu posso alternar entre os alto-falantes do monitor e do laptop com:

pacmd set-card-profile 0 output:hdmi-stereo

E:

pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo

Onde 0 é o índice do cartão:

pacmd list-cards
Welcome to PulseAudio! Use "help" for usage information.
>>> 1 card(s) available.
    index: 0
    name: <alsa_card.pci-0000_00_1b.0>

E, finalmente, para acelerar a troca, configurei dois alias no meu arquivo .bashrc:

alias audio-hdmi='pacmd set-card-profile 0 output:hdmi-stereo+input:analog-stereo'
alias audio-laptop='pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo'

Dessa forma, eu posso alternar entre o áudio do monitor ou do laptop (fones de ouvido) digitando no shell: audio-hdmi ou audio-laptop


Hum. Meu pacmd não tem opção 'list-cards' ...
ka3ak


3

Criei um script muito pequeno baseado nos anteriores, que não apenas alterna o áudio, mas também a saída de vídeo. Ele usa o disper para alternar entre os monitores.

Aqui está o código:

#!/bin/bash

CURRENT_PROFILE=$(pacmd list-cards | grep "active profile" | cut -d ' ' -f 3-)

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo>" ]; then
        pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo"
        disper -s
else 
        pacmd set-card-profile 0 "output:hdmi-stereo"
        disper -S        
fi

Para mim, é especialmente útil, pois não gosto de clonar as telas. Eu uso um ou outro. Pode ser necessário adaptar os perfis de áudio ao seu sistema específico.


2

Você pode usar pactl, leia sua página de manual para obter mais informações.




0

Como eu disse aqui (provavelmente uma duplicata), uma alternativa ao Sound Switcher Indicator (que requer a adição de um PPA):

Em uma linha

No meu caso foi hdmi-stereo-extra1+inputo perfil, assim, em uma linha seria: [[ $(pacmd list-cards | grep "active profile" | cut -d " " -f 3-) = "<output:hdmi-stereo-extra1+input:analog-stereo>" ]] && pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo" || pacmd set-card-profile 0 "output:hdmi-stereo-extra1+input:analog-stereo".

Você pode usar um atalho personalizado para executá-lo bash -c(avisará se houver algum conflito com outro atalho):

insira a descrição da imagem aqui

Além disso, você pode adicionar um aliasao seu .bashrc.

Em um script

Fiz algumas alterações com base na resposta @ user829996 (e aqui @ user56655):

#!/bin/bash
set -euo pipefail # strict mode

activeProfile() { pacmd list-cards | grep "active profile" | cut -d " " -f 3-; }
CURRENT_PROFILE="$(eval activeProfile)"

# If it doesn't work run  pacmd list-cards  and try the other outputs from profile section
ANALOG_PROFILE="output:analog-stereo+input:analog-stereo"
HDMI_PROFILE="output:hdmi-stereo-extra1+input:analog-stereo"

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo-extra1+input:analog-stereo>" ] ; then
  pacmd set-card-profile 0 "$ANALOG_PROFILE"
else
    pacmd set-card-profile 0 "$HDMI_PROFILE"
fi

activeProfile

0

Eu criei o seguinte script python que faz o seguinte:

  1. Alterne o dispositivo padrão para o próximo dispositivo da lista (com quebra automática), independentemente dos IDs
  2. Move todos os aplicativos em execução para este dispositivo.
  3. Envia uma notificação para a GUI com o nome do dispositivo.
#!/usr/bin/env python3
import subprocess
# Toggle default device to the next device (wrap around the list)
cards_info = subprocess.run(['pacmd','list-sinks'], stdout=subprocess.PIPE)
card_indexes = subprocess.run(['grep', 'index'], stdout=subprocess.PIPE, input=cards_info.stdout)
indexes_list = card_indexes.stdout.decode().splitlines()
card_descriptions = subprocess.run(['grep', 'device.description'], stdout=subprocess.PIPE, input=cards_info.stdout)
indices = [i for i, s in enumerate(indexes_list) if '*' in s]
if (len(indices) != 1):
    print("Error finding default device")
    exit(1)
default_index = indices[0]
next_default = 0
if (default_index != (len(indexes_list) - 1)):
    next_default = default_index + 1
next_default_index =  (indexes_list[next_default].split("index: ",1)[1])
subprocess.run(['pacmd','set-default-sink %s' %(next_default_index)], stdout=subprocess.PIPE)

# Move all existing applications to the new default device
inputs_info = subprocess.run(['pacmd','list-sink-inputs'], stdout=subprocess.PIPE)
inputs_indexes = subprocess.run(['grep', 'index'], stdout=subprocess.PIPE, input=inputs_info.stdout)
inputs_indexes_list = inputs_indexes.stdout.decode().splitlines()
for line in inputs_indexes_list:
    input_index =  (line.split("index: ",1)[1])
    subprocess.run(['pacmd','move-sink-input %s %s' %(input_index, next_default_index)], stdout=subprocess.PIPE)

# Send notification to the GUI
descriptions_list = card_descriptions.stdout.decode().splitlines()
if (len(descriptions_list) == len(indexes_list)):
    description =  (descriptions_list[next_default].split("= ",1)[1])[1:-1]
    args = ["notify-send", "Default audio card changed", 'Default audio card was set to %s' %(description)]
    subprocess.run(args, stdout=subprocess.PIPE)

Atribuí um atalho de teclado ao script e minha vida está feliz agora

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.