Comment changer de puits pulseaudio avec «pacmd set-default-sink» pendant la lecture?

55

Je dois changer le serveur pulseaudio d'un flux audio en cours de lecture.

Le serveur Pulseaudio est configuré avec IP 192.168.1.105

$>cat /etc/pulse/default.pa
...
load-module module-esound-protocol-tcp auth-anonymous=1
load-module module-native-protocol-tcp auth-anonymous=1
load-module module-zeroconf-publish
...

Du côté source, le lecteur multimédia VLC lit une chanson.

J'ai créé un nouvel évier de tunnel avec pulseaudio du côté source.

pacmd load-module module-tunnel-sink server=192.168.1.105
pacmd set-default-sink 1

Mais lors de la lecture audio, le serveur ne pouvait pas être changé immédiatement. Seulement après avoir arrêté le joueur et rejoué, c'est bon.

Depuis "gnome-volume-control" ou "gnome-control-center sound", la commutation des périphériques de sortie est appliquée immédiatement.

Comment appliquer la commutation immédiate du récepteur sur la ligne de commande lors de la lecture d’un fichier son?

wasakwasak
la source

Réponses:

83

PulseAudio pacmdn'est pas capable de commuter les puits par défaut tant qu'il y a un flux en cours de lecture sur l'entrée du puits. Cependant, il existe toujours un moyen d'y parvenir.

Changer le récepteur par défaut à partir de la ligne de commande

Nous devons d’abord déterminer le numéro d’indice des puits à changer. Cela peut être fait en appelant:

pacmd list-sinks

Selon notre système, vous obtiendrez une liste plus ou moins longue de puits et de propriétés actuellement accessibles:

 >>> 2 sink(s) available.
      * index: 0
            name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1>
            driver: <module-alsa-card.c>
    :
    :
        index: 1
            name: <alsa_output.pci-0000_00_14.2.analog-stereo>
            driver: <module-alsa-card.c>

Le indexou le namedonné ici est ce dont nous avons besoin pour adresser le récepteur par ligne de commande. Le puits par défaut actuel est marqué d'un astérisque (ici 0).

Pour pouvoir changer les récepteurs par défaut à partir de la ligne de commande, il peut être nécessaire de désactiver la restauration du périphérique cible du flux en modifiant la ligne correspondante /etc/pulse/default.papour:

load-module module-stream-restore restore_device=false

Pour changer le puits de sortie par défaut, 1nous lançons ensuite

pacmd set-default-sink 1

Sucess peut être visualisé en ouvrant le menu Sound Settings .

Déplacer un flux vers un autre lavabo

Changer le récepteur par défaut alors qu'un flux d'entrée actif en cours de lecture sur un récepteur donné n'a aucun effet . Cela devrait plutôt être fait en déplaçant cette entrée dans un autre puits.

pacmd list-sink-inputs

va nous dire l'index du flux d'entrée

>>> 1 sink input(s) available.
    index: 5
    driver: <protocol-native.c>

Nous savons maintenant que nous voulons déplacer le flux d’entrée 5vers le puits 1en appelant

pacmd move-sink-input 5 1

ou retour à couler 0si on aime. Cela se fera immédiatement sans qu'il soit nécessaire d'arrêter la lecture.

Changer l'évier par défaut en jouant

Bien sûr, nous pouvons combiner ces deux commandes pour changer immédiatement les puits par défaut pendant la lecture, par exemple avec

pacmd set-default-sink 1 & pacmd move-sink-input 5 1

Un inconvénient de cette méthode est que l' index du flux d'entrée change chaque fois que nous arrêtons et redémarrons le lecteur de musique. Nous devons donc toujours trouver l’index de flux actuel avant de pouvoir passer à l’aide de la ligne de commande.

Takkat
la source
Vous pouvez référencer un évier par son index OU par son nom pactl list short sinks> 4 bluez_sink.FC_A8_9A_2C_EB_0B module-bluez5-device.c s16le 1ch 8000Hz IDLEmaintenant il suffit de référencer le nompactl set-default-sink bluez_sink.FC_A8_9A_2C_EB_0B
Leif Liddy
@LifLiddy: Merci pour la note. Dans les versions les plus récentes de Pulseaudio, vous pouvez effectivement faire référence au nom d’un évier, set-default-sinkmais vous aurez toujours besoin du numéro d’index move-sink-input.
Takkat
Et si 0 sink input(s) available.? Mais ce lecteur flash merdique joue encore de l'audio?
Zhigalin
Et je vois flash player dans la client(s) logged insection depacmd list
Zhigalin le
@Zhigalin Flash est mort depuis longtemps sur mes systèmes, donc je ne peux pas vraiment dire… il peut jouer directement via ALSA.
Takkat
27

J'ai écrit un script simple pour déplacer automatiquement toutes les entrées-puits.

Usage: ./movesinks.sh <sink number>

#!/bin/bash 
echo "Setting default sink to: $1";
pacmd set-default-sink $1
pacmd list-sink-inputs | grep index | while read line
do
echo "Moving input: ";
echo $line | cut -f2 -d' ';
echo "to sink: $1";
pacmd move-sink-input `echo $line | cut -f2 -d' '` $1

done
Gaco
la source
1
Impressionnant! Je l'ai étendu un peu plus pour mon propre usage: je voulais une icône dans ma barre des tâches permettant de basculer entre deux cartes audio. J'ai écrit un petit script en Ruby pour déterminer le puits actuel et appeler ce script shell pour effectuer le changement ( pastebin.com/xb3i2ejW ). Après cela, j'ai mis les deux scripts dans ~ / bin et personnalisé une icône KDE pour exécuter le script ruby. Cela pourrait être fait plus élégamment, ou entièrement en script shell, mais cela fonctionne pour moi.
Pathogen
2
Merci pour cela. Voici une version qui bascule vers la dernière sortie (? - Je n'en ai que deux) inutilisée: pastebin.com/raw/sidH7QPb, c’est-à-dire qu’elle bascule la sortie, ce qui convient au mappage sur une touche de raccourci.
Julian
4

Version améliorée du script @Gaco

#!/usr/bin/env bash

case "${1:-}" in
  (""|list)
    pacmd list-sinks |
      grep -E 'index:|name:'
    ;;
  ([0-9]*)
    echo switching default
    pacmd set-default-sink $1 ||
      echo failed
    echo switching applications
    pacmd list-sink-inputs |
      awk '/index:/{print $2}' |
      xargs -r -I{} pacmd move-sink-input {} $1 ||
        echo failed
    ;;
  (*)
    echo "Usage: $0 [|list|<sink name to switch to>]"
    ;;
esac

ma copie d'exécution est sur github et il comprend également la commutation automatisée du canal principal pourkmix

mpapis
la source
2

J'ai bricolé des objets provenant de plusieurs endroits différents et j'ai imaginé ce script pour configurer une JAMBOX bluetooth une fois qu'elle a été appariée. Votre MAC sera différent bien sûr. Étant donné que je contrôle le volume de JAMBOX via l'application Clementine, 130% du volume fonctionne mieux dans mon cas. Vous voudrez peut-être changer cela, ainsi que rhythmbox.png (c'était la seule image de haut-parleur que je pouvais trouver sur mon ordinateur). La vérification des erreurs est rudimentaire, mais fonctionne de manière assez fiable. Je mets cela dans un lanceur de bureau pour plus de commodité sur un netbook ASUS.

#!/bin/bash
# setjambox connection setup
# Find the particulars of your environment with 'pactl list sinks'
# This script uses the sink name instead of the index number
# You also need libnotify-bin to run this script

# Enter the bluetooth MAC address of your device here
MAC=00:21:3C:9F:19:AD

# Make ready
# Convert device address per pulseaudio standards
DEV=$(echo $MAC|tr ':' '_')
TITLE="JAMBOX $MAC"
CONNECTED="Audio connection updated."
PROBLEM="Unable to update settings."
JBLOGO=/usr/share/icons/hicolor/48x48/apps/rhythmbox.png

# And go

pactl list short sink-inputs | while read stream; do
    streamId=$(echo $stream | cut '-d ' -f1)
    pactl move-sink-input "$streamId" bluez_sink.$DEV
done

pactl set-default-sink bluez_sink.$DEV
pactl set-card-profile bluez_card.$DEV a2dp
pactl set-sink-volume  bluez_sink.$DEV 130%

if [ $? -eq 0 ]
then
   notify-send -i $JBLOGO -t 3000 "$TITLE" "$CONNECTED" 
else
   notify-send -i gtk-dialog-warning -t 3000 "$TITLE" "$PROBLEM"
fi
Ray M
la source
+1 pour utiliser pactl list short. Vous pouvez simplifier la ligne suivante en coupant directement après: pactl list short sink-inputs | cut -f1 | while read streamIdfonctionne pour moi.
Bodo
1

LES PUITS DE CERCLE

Le script Gaco ne contient plus qu’une ligne pour encercler les éviers disponibles.

#!/bin/bash 

new_sink=$(pacmd list-sinks | grep index | tee /dev/stdout | grep -m1 -A1 "* index" | tail -1 | cut -c12-)

echo "Setting default sink to: $new_sink";
pacmd set-default-sink $new_sink
pacmd list-sink-inputs | grep index | while read line
do
echo "Moving input: ";
echo $line | cut -f2 -d' ';
echo "to sink: $new_sink";
pacmd move-sink-input `echo $line | cut -f2 -d' '` $new_sink

done
utilisateur512557
la source
génial, simple et évolutif!
Paul Bastian le
1

Et voici un script qui bascule également entre les puits:

http://marginalhacks.com/index.0.html#pulse-switch-out

Voici le script ci-dessous:

#!/usr/bin/ruby
# Filename: pulse-switch-out
# Author:   David Ljung Madison <DaveSource.com>
# See License:  http://MarginalHacks.com/License/
# Description:  Switch pulse audio output (sink) using pacmd

PACMD = %w(pacmd)

##################################################
# Usage
##################################################
def fatal(*msg)
    msg.each { |m| $stderr.puts "[#{$0.sub(/.*\//,'')}] ERROR: #{m}" }
    exit(-1);
end

def usage(*msg)
    msg.each { |m| $stderr.puts "ERROR: #{m}" }
    $stderr.puts <<-USAGE

Usage:  #{$0.sub(/.*\//,'')} [sink]
  Switch sound playback device for ALSA/pulseaudio

    [sink]   Specify sink number to use (see 'pacmd list-sinks')

    USAGE
    exit -1;
end

def parseArgs
    opt = Hash.new
    loop {
        if (arg=ARGV.shift)==nil then break
        elsif arg == '-h' then usage
        elsif arg == '-?' then usage
        #elsif arg == '-arg' then opt[:arg] = true
        elsif arg =~ /^(\d)$/ then opt[:sink] = arg.to_i
        else
            usage("Unknown arg [#{arg}]")
        end
    }

    opt
end

# Unfortunately you can't return or break from the yield without leaving
# the pipe open, maybe use some sort of ensure and figure out how to close?
def pipe(cmd)
        # This is leaving files open
    #IO.popen(cmd.join(' ')).each { |l|
    a = `#{cmd.join(' ')}`
    ret = $?
    a.split("\n").each { |l|
        yield l
    }
    $?
end

def getSinks(ins=false)
    cmd = PACMD.dup
    cmd.push(ins ? 'list-sink-inputs' : 'list-sinks')
    curr = nil
    sinks = Array.new
    pipe(cmd) { |l|
        next unless l=~/\s*(\*)?\s*index:\s+(\d+)/
        i = $2.to_i
        sinks.push(i)
        curr = i if $1
    }
    return sinks,curr
end

##################################################
# Main code
##################################################
def main
    opt = parseArgs

    sinks,curr = getSinks

    usage("No sinks found?") if sinks.empty?
    usage("Only one sink found") if sinks.size==1

    if opt[:sink]
        usage("Unknown sink [#{opt[:sink]}] (out of #{sinks.join(' ')})") unless sinks.index(opt[:sink])
    else
        # Find next sink after curr
        opt[:sink] = sinks[0]
        sinks.each { |s|
            next unless s>curr
            opt[:sink] = s
            break
        }
    end

    # Set default sink
## For some reason this doesn't change the behavior of new apps.
    puts "Set sink: #{opt[:sink]}"
    system("#{PACMD} set-default-sink #{opt[:sink]} > /dev/null")
    usage("Couldn't set default sink [#{opt[:sink]}]") unless $?==0

    # And move all sink-inputs to the new sink
    ins,ignore = getSinks(true)
    ins.each { |i|
        puts "Move playback #{i} to sink #{opt[:sink]}"
        system("#{PACMD} move-sink-input #{i} #{opt[:sink]} > /dev/null")
        usage("Couldn't move playback #{i} to sink [#{opt[:sink]}]") unless $?==0
    }
end
main
David Ljung Madison Stellar
la source
1
Bienvenue sur Ask Ubuntu! Bien que cela puisse théoriquement répondre à la question, il serait préférable d’inclure ici les parties essentielles de la réponse et de fournir le lien à titre de référence.
ζ--
C'est fait, mais malheureusement, cela signifie que le script ne sera pas mis à jour ici à moins que je ne m'en souvienne. Par exemple, ruby ​​a changé la façon dont il gère .each pour les chaînes (dans la partie de contrôle), donc je devais mettre à jour la ligne 53 ci-dessus. Ou téléchargez simplement le script pour vous assurer qu'il est à jour.
David Ljung Madison Stellar
1

Sur la base de la réponse de Gaco, je l'ai un peu réécrite pour mon usage personnel. Peut-être que quelqu'un trouve cela utile. C'est pour basculer entre mes haut-parleurs USB et mon casque USB Gaming.

#!/bin/bash

# get list of sinks/cards (for settings CARD1/CARD2)
# pacmd list-sinks | awk '/name:/ {print $0};' | awk '{ print $2}' | sed 's/<//g; s/>//g'

CARD1="alsa_output.usb-C-Media_INC._C-Media_USB_Audio-00"
CARD2="alsa_output.usb-Kingston_HyperX_Virtual_Surround_Sound_00000000-00"

CURRENT_SINK=$(pacmd stat | awk -F": " '/^Default sink name: /{print $2}' | awk 'BEGIN{FS=OFS="."} NF--' | sed 's/alsa_output/alsa_output/g')


function setCard() {

  if [ "$CURRENT_SINK" == "$1" ]
   then
     echo "Already using this Sink"
     exit 1
  fi

  NEW_SINK=$(pacmd list-sinks | awk '/index:/ {print $1 $2 $3} /name:/ {print $0};' | grep -m1 -B1 $1 | grep index | awk '{print $1}' | cut -d ":" -f2)
  SINK=$(pacmd set-default-sink $NEW_SINK)
  INPUT=$(pacmd list-sink-inputs | grep index | awk '{print $2}')

  pacmd move-sink-input $INPUT $NEW_SINK
  echo "Moving input: $INPUT to sink: $NEW_SINK";
  echo "Setting default sink to: $NEW_SINK";

  notify-send --urgency=low "Audio Switching" "SINK: $NEW_SINK"
}

function toggleSinks() {
  if [ "$CURRENT_SINK" == "$CARD1" ]
    then
      setCard $CARD2
    else
      setCard $CARD1
    fi
}


function showHelp() {
  echo "------------------------------------"
  echo "AUDIO SINK SWITCHER"
  echo " "
  echo "$0 [options]"
  echo " "
  echo "options:"
  echo "-h  --help        What you are looking at.."
  echo "-g, --gaming      Sets Gaming headset as output device"
  echo "-s, --speakers    Sets Speakers as output device"
  echo "-t, --toggle      Toggles the different output devices"
  echo " "
  echo "------------------------------------"
}

# check args length
if [ $# -eq 0 ]
  then
    echo "Toggling output devices (Speakers/Headset)"
    toggleSinks
fi


# arg options
while test $# -gt 0; do
    case "$1" in

                -h|--help)
                        showHelp
                        exit 1
                        ;;

                -g|--gaming)
                        setCard $CARD2
                        exit 1
                        ;;

                -s|--speakers)
                        setCard $CARD1
                        exit 1
                        ;;

                -t|--toggle)
                        toggleSinks
                        echo "Toggling output devices (Speakers/Headset)"
                        exit 1
                        ;;
                 *)
                        showHelp
                        exit 1
                        ;;
    esac
done
Ole Algoritme
la source
0

Je pense qu’une autre option mérite d’être mentionnée. Elle est disponible sur la page officielle de la FAQ sur PulseAudio sur freedesktop.org . Sous le titre suivant:

Comment changer de carte son par défaut en déplaçant toutes les applications?

Ils fournissent le script suivant pour le faire:

#/bin/bash
# paswitch 2011-02-02 by Ng Oon-Ee <[email protected]>
# I can't remember where I found this script, can't locate the original author.
# Please inform me if you know, so that I can give proper attribution.
# CHANGES: Added auto-move all inputs to new default sound card.
# WAS: Pulse Audio Sound Card Switcher v1.0 2010-01-13
#   Switches between soundcards when run. All streams are moved to the new default sound-card.

# $totalsc: Number of sound cards available
totalsc=$(pacmd "list-sinks" | grep card: | wc -l) # total of sound cards: $totalsc
if [ $totalsc -le 1 ]; then # Check whether there are actually multiple cards available
  notify-send -u critical -t 5000 "Nothing to switch, system only has one sound card."
  exit
fi
# $scindex: The Pulseaudio index of the current default sound card
scindex=$(pacmd list-sinks | awk '$1 == "*" && $2 == "index:" {print $3}')
# $cards: A list of card Pulseaudio indexes
cards=$(pacmd list-sinks | sed 's|*||' | awk '$1 == "index:" {print $2}')
PICKNEXTCARD=1 # Is true when the previous card is default
count=0 # count of number of iterations
for CARD in $cards; do
  if [ $PICKNEXTCARD == 1 ]; then
# $nextsc: The pulseaudio index of the next sound card (to be switched to)
    nextsc=$CARD
    PICKNEXTCARD=0
# $nextind: The numerical index (1 to totalsc) of the next card
    nextind=$count
  fi
  if [ $CARD == $scindex ]; then # Choose the next card as default
    PICKNEXTCARD=1
  fi
  count=$((count+1))
done
pacmd "set-default-sink $nextsc" # switch default sound card to next

# $inputs: A list of currently playing inputs
inputs=$(pacmd list-sink-inputs | awk '$1 == "index:" {print $2}')
for INPUT in $inputs; do # Move all current inputs to the new default sound card
  pacmd move-sink-input $INPUT $nextsc
done
# $nextscdec: The device.description of the new default sound card
# NOTE: This is the most likely thing to break in future, the awk lines may need playing around with
nextscdesc=$(pacmd list-sinks | awk '$1 == "device.description" {print substr($0,5+length($1 $2))}' \
                         | sed 's|"||g' | awk -F"," 'NR==v1{print$0}' v1=$((nextind+1)))
notify-send "Default sound-card changed to $nextscdesc"
exit
# Below text was from original author and remains unaltered
# CC BY - creative commons
# Thanks God for help :) and guys lhunath, geirha, Tramp and others from irc #bash on freenode.net
Doron Behar
la source
0

J'ai adapté @mpapis à une simple "bascule sink0 ou sink1" à l'exécution:

#!/bin/bash
SINK_INDEX1=0
SINK_INDEX2=1
ACTIVE_SINK=$(pacmd list-sinks | grep '* index:' | grep -o '[0-9]*')
if [ "$ACTIVE_SINK" = $SINK_INDEX1 ] ; then
    pacmd set-default-sink $SINK_INDEX2
    pacmd list-sink-inputs | awk '/index:/{print $2}' | xargs -r -I{} pacmd move-sink-input {} $SINK_INDEX2
else 
    pacmd set-default-sink $SINK_INDEX1
    pacmd list-sink-inputs | awk '/index:/{print $2}' | xargs -r -I{} pacmd move-sink-input {} $SINK_INDEX1
fi
OCP001
la source