วิธีการเปลี่ยน pulseaudio sink ด้วย“ pacmd set-default-sink” ในระหว่างการเล่น


55

ฉันต้องเปลี่ยนเซิร์ฟเวอร์ pulseaudio ของกระแสข้อมูลเสียงที่กำลังเล่นอยู่

เซิร์ฟเวอร์ Pulseaudio ตั้งค่าด้วย 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
...

ที่เครื่องเล่นสื่อ VLC ด้านต้นทางกำลังเล่นเพลงอยู่

ฉันสร้างที่เก็บอุโมงค์ใหม่พร้อม pulseaudio ที่ด้านแหล่งที่มา

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

แต่ในขณะที่เล่นเสียงเซิร์ฟเวอร์ไม่สามารถเปลี่ยนได้ทันที หลังจากหยุดเล่นและเล่นซ้ำก็ไม่เป็นไร

จากการสลับ "gnome-volume-control" หรือ "gnome-control-center-center" ของอุปกรณ์เอาต์พุตจะถูกนำไปใช้งานทันที

ฉันจะใช้การสลับซิงค์เอาต์พุตทันทีจากบรรทัดรับคำสั่งระหว่างการเล่นไฟล์เสียงได้อย่างไร

คำตอบ:


83

PulseAudio pacmdไม่สามารถสลับ sinks เริ่มต้นได้ในขณะที่มีสตรีมเล่นไปยังอ่างอินพุต อย่างไรก็ตามมีวิธีที่จะยังคงบรรลุเป้าหมายนี้อยู่

การเปลี่ยน sink เริ่มต้นจากบรรทัดคำสั่ง

ก่อนอื่นเราต้องกำหนดหมายเลขดัชนีของอ่างล้างมือที่เราต้องการเปลี่ยน สิ่งนี้สามารถทำได้โดยการโทร:

pacmd list-sinks

ขึ้นอยู่กับระบบของเราซึ่งจะให้รายการอ่างล้างมือและคุณสมบัติที่มีความยาวมากขึ้นหรือน้อยลงซึ่งคุณสามารถเข้าถึงได้ในปัจจุบัน:

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

indexหรือnameให้ที่นี่เป็นสิ่งที่เราต้องการสำหรับ adressing อ่างล้างจานโดยบรรทัดคำสั่ง sink เริ่มต้นปัจจุบันถูกทำเครื่องหมายด้วยเครื่องหมายดอกจัน (ที่นี่0)

เพื่อให้สามารถสลับ sinks เริ่มต้นจากบรรทัดคำสั่งเราอาจต้องปิดการสตรีมอุปกรณ์เป้าหมายคืนค่าโดยการแก้ไขบรรทัดที่เกี่ยวข้องใน/etc/pulse/default.paการ:

load-module module-stream-restore restore_device=false

ในการเปลี่ยน sink เริ่มต้นให้เป็น Sink 1เราก็ทำการรัน

pacmd set-default-sink 1

สามารถมองเห็นความสำเร็จได้โดยการเปิดเมนูการตั้งค่าเสียง

การย้ายกระแสไปยังอ่างอื่น

เปลี่ยนอ่างเริ่มต้นในขณะที่เรามีกระแสอินพุทที่ใช้งานการเล่นที่จะจมได้รับไม่มีผล สิ่งนี้ควรทำโดยการย้ายอินพุตนี้ไปยัง sink อื่น

pacmd list-sink-inputs

จะบอกดัชนีของสตรีมอินพุตให้เราทราบ

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

ตอนนี้เรารู้แล้วว่าเราต้องการย้ายกระแสข้อมูลเข้า5สู่การจม1โดยการโทร

pacmd move-sink-input 5 1

หรือกลับไปจม0ถ้าเราชอบ สิ่งนี้จะเกิดขึ้นทันทีโดยไม่จำเป็นต้องหยุดเล่น

เปลี่ยนอ่างเริ่มต้นในขณะที่เล่น

แน่นอนว่าเราสามารถรวมสองคำสั่งเหล่านั้นเพื่อเปลี่ยน sinks เริ่มต้นทันทีในระหว่างการเล่นเช่นกับ

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

ข้อเสียของวิธีนี้คือดัชนีอินพุทอินพุทเปลี่ยนทุกครั้งที่เราหยุดและรีสตาร์ทเครื่องเล่นเพลง ดังนั้นเราจึงต้องค้นหาดัชนีสตรีมปัจจุบันก่อนที่เราจะสามารถสลับโดยใช้บรรทัด commmand


คุณสามารถอ้างอิง sink โดยดัชนีหรือตามชื่อของมันpactl list short sinks> 4 bluez_sink.FC_A8_9A_2C_EB_0B module-bluez5-device.c s16le 1ch 8000Hz IDLEตอนนี้เพียงแค่อ้างอิงชื่อpactl set-default-sink bluez_sink.FC_A8_9A_2C_EB_0B
Leif Liddy

@LeifLiddy: ขอบคุณสำหรับการบันทึก ในรุ่นล่าสุดของ PulseAudio คุณแน่นอนสามารถอ้างอิงถึงชื่อของอ่างล้างจานในที่แต่คุณยังจะต้องมีหมายเลขดัชนีบนset-default-sink move-sink-input
Takkat

แล้วจะเป็น0 sink input(s) available.อย่างไร แต่โปรแกรมเล่นแฟลชที่ขี้เล่นก็ยังเล่นเสียงอยู่ใช่ไหม
Zhigalin

และฉันเห็นโปรแกรมเล่นแฟลชในclient(s) logged inส่วนของpacmd list
Zhigalin

@Zhigalin Flash ใช้งานได้นานมากในระบบของฉันดังนั้นฉันจึงไม่สามารถพูดซ้ำได้ ... มันอาจเล่นผ่าน ALSA โดยตรง
Takkat

27

ฉันเขียนสคริปต์ง่าย ๆ เพื่อย้ายอินพุตทั้งหมดโดยอัตโนมัติ

การใช้งาน: ./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

1
น่ากลัว! ฉันได้ขยายสิ่งนี้ไปอีกเล็กน้อยเพื่อการใช้งานของตัวเอง: ฉันต้องการไอคอนบนทาสก์บาร์ที่จะสลับระหว่างการ์ดเสียงสองอัน ฉันเขียนสคริปต์เล็ก ๆ ใน Ruby เพื่อพิจารณา sink ปัจจุบันและเรียก shell script นี้เพื่อทำการเปลี่ยนแปลง ( pastebin.com/xb3i2ejW ) หลังจากนั้นฉันวางสคริปต์ทั้งสองไว้ใน ~ / bin และปรับแต่งไอคอน KDE เพื่อเรียกใช้สคริปต์ทับทิม สิ่งนี้สามารถทำได้อย่างสวยงามยิ่งขึ้นหรือในเชลล์สคริป แต่ก็ใช้ได้กับฉัน
Pathogen

2
ขอบคุณสำหรับสิ่งนี้. นี่คือเวอร์ชันที่สลับไปยังเอาต์พุตล่าสุด (? - ฉันมีเพียงสองรายการ): pastebin.com/raw/sidH7QPb เช่นมันสลับเอาต์พุตเหมาะสำหรับการทำแผนที่กับฮอตคีย์
Julian

4

รุ่นที่ปรับปรุงของสคริปต์@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

สำเนารันไทม์ของฉันคือบน GitHubและมันยังรวมถึงการสลับอัตโนมัติของช่องปริญญาโทสำหรับkmix



2

ฉันนำก้อนกรวดมารวมกันจากที่ต่างๆไม่กี่แห่งและเกิดขึ้นกับสคริปต์นี้เพื่อตั้งค่าบลูทู ธ JAMBOX เมื่อมีการจับคู่แล้ว MAC ของคุณจะแตกต่างกันอย่างแน่นอน เนื่องจากฉันควบคุมปริมาณ JAMBOX ผ่านแอป Clementine ปริมาณ 130% จึงเหมาะสมที่สุดในกรณีของฉัน คุณอาจต้องการเปลี่ยนแปลงสิ่งนี้พร้อมกับ rhythmbox.png (มันเป็นรูปลำโพงเดียวที่ฉันสามารถหาได้ในคอมพิวเตอร์ของฉัน) การตรวจสอบข้อผิดพลาดเป็นพื้นฐาน แต่ทำงานได้อย่างน่าเชื่อถือ ฉันใส่สิ่งนี้ในตัวเรียกใช้งานเดสก์ท็อปเพื่อความสะดวกในเน็ตบุ๊ก 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

+1 pactl list shortสำหรับใช้ คุณสามารถลดความซับซ้อนของบรรทัดต่อไปนี้โดยการตัดโดยตรงหลังจาก: ได้pactl list short sink-inputs | cut -f1 | while read streamIdผลสำหรับฉัน
bodo

1

ความผิดพลาดในวงรอบ

สคริปต์ Gaco ที่มีอีกหนึ่งบรรทัดเพื่อสลับเป็นวงกลมผ่าน sinks ที่พร้อมใช้งาน

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

ดีง่ายและปรับขนาด!
พอลบาสเตียน

1

และนี่คือสคริปต์ที่จะสลับไปมาระหว่างอ่างล้างมือด้วย:

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

นี่คือสคริปต์ด้านล่าง:

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

1
ยินดีต้อนรับสู่ถาม Ubuntu! ในขณะที่สิ่งนี้อาจตอบคำถามในทางทฤษฎีมันก็ควรที่จะรวมส่วนสำคัญของคำตอบที่นี่และให้ลิงค์สำหรับการอ้างอิง
ζ--

เสร็จสิ้น แต่น่าเสียดายที่นี่หมายความว่าสคริปต์จะไม่ได้รับการอัปเดตที่นี่จนกว่าฉันจะจำได้ว่ามันอยู่ที่นี่ ตัวอย่างทับทิมเปลี่ยนวิธีจัดการ. แต่ละสตริง (ในส่วน backtick) ดังนั้นฉันจำเป็นต้องปรับปรุงบรรทัด 53 ข้างต้น หรือเพียงดาวน์โหลดสคริปต์เพื่อให้แน่ใจว่าเป็นรุ่นล่าสุด
David Ljung Madison Stellar

1

จากคำตอบของ Gaco ฉันเขียนมันใหม่เพื่อประโยชน์ส่วนตัว บางทีบางคนอาจพบว่ามีประโยชน์ ใช้สำหรับสลับลำโพง USB และชุดหูฟัง USB สำหรับเล่นเกม

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

0

ผมคิดว่ามีหนึ่งในตัวเลือกอื่น ๆ อีกมากมายมูลค่าการกล่าวขวัญและก็สามารถดูได้ที่หน้าอย่างเป็นทางการสำหรับคำถามที่พบบ่อยเกี่ยวกับ PulseAudio ที่freedesktop.org ภายใต้หัวข้อต่อไปนี้:

ฉันจะเปลี่ยนการ์ดเสียงเริ่มต้นย้ายแอปพลิเคชันทั้งหมดได้อย่างไร

พวกเขาให้สคริปต์ต่อไปนี้ให้ทำ:

#/bin/bash
# paswitch 2011-02-02 by Ng Oon-Ee <ngoonee@gmail.com>
# 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

0

ฉันดัดแปลง @mpapis เป็น "toggle sink0 หรือ sink1" แบบง่ายเมื่อเรียกใช้:

#!/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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.