Bagaimana cara mengganti pulseaudio sink dengan "pacmd set-default-sink" selama pemutaran?

55

Saya perlu mengganti server pulseaudio dari aliran audio yang sedang diputar.

Server Pulseaudio diatur dengan 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
...

Di sisi sumber VLC media player sedang memainkan lagu.

Saya membuat sink tunnel baru dengan pulseaudio di sisi sumber.

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

Tetapi saat memutar audio server tidak dapat segera diubah. Hanya setelah menghentikan pemain dan memutar ulang, tidak masalah.

Dari peralihan "gnome-volume-control" atau "gnome-control-center sound" perangkat output segera diterapkan.

Bagaimana saya bisa menerapkan peralihan wastafel keluaran langsung dari baris perintah selama pemutaran file suara?

wasakwasak
sumber

Jawaban:

83

PulseAudio pacmdtidak mampu mengalihkan bak cuci default saat ada aliran pemutaran yang aktif ke input bak cuci. Namun ada cara untuk tetap mencapai ini.

Mengubah bak cuci standar dari baris perintah

Pertama kita perlu menentukan nomor indeks dari sink yang ingin kita ganti. Ini dapat dilakukan dengan menelepon:

pacmd list-sinks

Bergantung pada sistem kami, ini akan memberi Anda daftar sink dan properti yang kurang lebih panjang yang saat ini dapat diakses:

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

The indexatau namediberikan di sini adalah apa yang kita butuhkan untuk adressing wastafel dengan baris perintah. Wastafel default sekarang ditandai dengan asterix (di sini 0).

Untuk dapat mengalihkan bak cuci default dari baris perintah, kita mungkin perlu menonaktifkan aliran target perangkat dengan mengedit baris yang sesuai di /etc/pulse/default.pa:

load-module module-stream-restore restore_device=false

Untuk mengubah wastafel keluaran default ke wastafel 1kami kemudian jalankan

pacmd set-default-sink 1

Sukses dapat divisualisasikan dengan membuka menu Pengaturan Suara .

Memindahkan aliran air ke bak cuci yang lain

Mengubah wastafel default sementara kami memiliki aliran input aktif yang diputar ke wastafel yang diberikan tidak berpengaruh . Ini lebih baik dilakukan dengan memindahkan input ini ke sink lainnya.

pacmd list-sink-inputs

akan memberi tahu kami indeks aliran input

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

Kita sekarang tahu bahwa kita ingin memindahkan aliran input 5ke sink 1dengan menelepon

pacmd move-sink-input 5 1

atau kembali tenggelam 0jika kita mau. Ini akan segera dilakukan tanpa perlu menghentikan pemutaran.

Mengubah bak cuci bawaan saat bermain

Tentu saja kita dapat menggabungkan kedua perintah itu untuk segera mengganti bak cuci default selama pemutaran misalnya dengan

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

Kelemahan dari metode ini adalah bahwa indeks aliran input berubah setiap kali kita menghentikan dan memulai ulang pemutar musik. Jadi kita selalu harus mencari tahu indeks aliran saat ini sebelum kita bisa beralih menggunakan garis commmand.

Takkat
sumber
Anda dapat mereferensikan bak cuci dengan indeksnya ATAU dengan namanya pactl list short sinks> 4 bluez_sink.FC_A8_9A_2C_EB_0B module-bluez5-device.c s16le 1ch 8000Hz IDLEsekarang hanya merujuk namapactl set-default-sink bluez_sink.FC_A8_9A_2C_EB_0B
Leif Liddy
@LeifLiddy: Terima kasih atas catatannya. Dalam versi Pulseaudio yang lebih baru, Anda memang bisa merujuk ke nama bak cuci set-default-sinktetapi Anda masih membutuhkan nomor indeks move-sink-input.
Takkat
Dan bagaimana jika 0 sink input(s) available.? Tapi flash player yang menyebalkan itu masih memutar audio?
Zhigalin
Dan saya melihat flash player di client(s) logged inbagianpacmd list
Zhigalin
@Zhigalin Flash sudah lama mati di sistem saya, jadi saya tidak bisa mengatakannya ... itu dapat diputar langsung melalui ALSA.
Takkat
27

Saya telah menulis skrip sederhana untuk memindahkan semua input-sink secara otomatis.

Pemakaian: ./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
sumber
1
Luar biasa! Saya memperpanjang ini sedikit lebih jauh untuk saya gunakan sendiri: Saya ingin ikon di taskbar saya yang akan beralih di antara dua kartu audio. Saya menulis skrip kecil di Ruby untuk menentukan wastafel saat ini dan memanggil skrip shell ini untuk melakukan perubahan ( pastebin.com/xb3i2ejW ). Setelah itu, saya meletakkan kedua skrip di ~ / bin dan mengkustomisasi ikon KDE untuk menjalankan skrip ruby. Ini bisa dilakukan dengan lebih elegan, atau seluruhnya dalam skrip shell, tetapi ini berhasil untuk saya.
Pathogen
2
Terima kasih untuk ini. Berikut adalah versi yang beralih ke yang terakhir (? - Saya hanya punya dua) keluaran yang tidak digunakan: pastebin.com/raw/sidH7QPb yaitu beralih ke output, cocok untuk pemetaan ke hot key.
Julian
4

Versi perbaikan skrip @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

salinan runtime saya ada di github dan termasuk juga pengalihan otomatis saluran Master untukkmix

mpapis
sumber
2

Saya mengumpulkan beberapa hal dari beberapa tempat berbeda dan membuat skrip ini untuk mengatur JAMBOX bluetooth setelah dipasangkan. MAC Anda tentu saja akan berbeda. Karena saya mengontrol volume JAMBOX melalui aplikasi Clementine, 130% volume berfungsi paling baik dalam kasus saya. Anda mungkin ingin mengubah ini, bersama dengan rhythmbox.png (itu adalah satu-satunya gambar speaker yang dapat saya temukan di komputer saya). Pemeriksaan kesalahan belum sempurna, tetapi berfungsi dengan cukup andal. Saya meletakkan ini di peluncur desktop untuk kenyamanan di 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
sumber
+1 untuk digunakan pactl list short. Anda dapat menyederhanakan baris berikut dengan melakukan cut langsung setelah: pactl list short sink-inputs | cut -f1 | while read streamIdberfungsi untuk saya.
Bodo
1

SINKS LINGKARAN LINGKARAN.

Script Gaco dengan hanya satu baris lagi untuk lingkaran-beralih melalui sink yang tersedia.

#!/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
pengguna512557
sumber
hebat, sederhana dan scaling!
Paul Bastian
1

Dan inilah skrip yang akan beralih di antara sink juga:

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

Berikut skrip di bawah ini:

#!/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
sumber
1
Selamat Datang di Tanya Ubuntu! Sementara ini secara teoritis dapat menjawab pertanyaan, akan lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
ζ--
Selesai, meskipun sayangnya ini berarti skrip tidak diperbarui di sini kecuali saya ingat itu ada di sini. Sebagai contoh, ruby ​​mengubah cara menangani .each untuk string (di bagian backtick) jadi saya perlu memperbarui baris 53 di atas. Atau cukup unduh skrip untuk memastikannya terbaru.
David Ljung Madison Stellar
1

Berdasarkan jawaban Gaco, saya menulis ulang sedikit untuk penggunaan pribadi saya. Mungkin seseorang menganggapnya berguna. Ini untuk mengaktifkan Speaker USB dan headset Gaming USB saya.

#!/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
sumber
0

Saya pikir ada satu opsi lagi yang perlu disebutkan dan tersedia di halaman resmi untuk FAQ tentang PulseAudio di freedesktop.org . Di bawah Judul berikut:

Bagaimana cara mengganti kartu suara default, memindahkan semua aplikasi?

Mereka menyediakan skrip berikut untuk melakukannya:

#/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
sumber
0

Saya mengadaptasi @mpapis ke "toggle sink0 atau sink1" sederhana ketika dijalankan:

#!/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
sumber