Làm cách nào để thay đổi chìm pulseaudio với cài đặt pacmd set-default-chìm trong khi phát lại?


55

Tôi cần chuyển đổi máy chủ pulseaudio của luồng âm thanh hiện đang phát.

Máy chủ Pulseaudio được thiết lập với 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
...

Về phía nguồn phát VLC media player đang phát một bài hát.

Tôi đã tạo ra một đường hầm chìm mới với pulseaudio ở phía nguồn.

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

Nhưng trong khi phát âm thanh, máy chủ không thể thay đổi ngay lập tức. Chỉ sau khi dừng trình phát và phát lại, nó vẫn ổn.

Từ việc chuyển đổi "gnome-volume-control" hoặc "gnome-control-centre" của các thiết bị đầu ra được áp dụng ngay lập tức.

Làm cách nào tôi có thể áp dụng chuyển đổi phần chìm đầu ra ngay lập tức từ dòng lệnh trong khi phát lại tệp âm thanh?

Câu trả lời:


83

PulseAudio pacmdkhông có khả năng chuyển đổi các mức chìm mặc định trong khi có một luồng phát tích cực đến đầu vào chìm. Tuy nhiên có một cách để vẫn đạt được điều này.

Thay đổi chìm mặc định từ dòng lệnh

Đầu tiên chúng ta cần xác định số chỉ mục của các bồn mà chúng ta muốn chuyển đổi. Điều này có thể được thực hiện bằng cách gọi:

pacmd list-sinks

Tùy thuộc vào hệ thống của chúng tôi, điều này sẽ cung cấp cho bạn một danh sách dài hơn hoặc ít hơn các bồn rửa và các thuộc tính hiện có thể truy cập được:

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

Các indexhoặc nameđưa ra ở đây là những gì chúng ta cần cho adressing bồn rửa bằng dòng lệnh. Các bồn rửa mặc định hiện tại được đánh dấu bằng một dấu sao (ở đây 0).

Để có thể chuyển các mức chìm mặc định từ dòng lệnh, chúng tôi có thể cần phải tắt khôi phục thiết bị đích luồng bằng cách chỉnh sửa dòng sửa lỗi /etc/pulse/default.pathành:

load-module module-stream-restore restore_device=false

Để thay đổi chìm đầu ra mặc định thành chìm, 1sau đó chúng tôi chạy

pacmd set-default-sink 1

Thành công có thể được hình dung bằng cách mở menu Cài đặt âm thanh .

Di chuyển một luồng đến bồn khác

Thay đổi mức chìm mặc định trong khi chúng ta có một luồng đầu vào hoạt động đang phát sang một mức chìm nhất định không có hiệu lực . Điều này nên được thực hiện bằng cách di chuyển đầu vào này sang bồn rửa khác.

pacmd list-sink-inputs

sẽ cho chúng ta biết chỉ số của luồng đầu vào

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

Bây giờ chúng tôi biết rằng chúng tôi muốn di chuyển luồng đầu vào 5bị chìm 1bằng cách gọi

pacmd move-sink-input 5 1

hoặc quay lại chìm 0nếu chúng ta thích. Điều này sẽ được thực hiện ngay lập tức mà không cần phải dừng phát lại.

Thay đổi chìm mặc định trong khi chơi

Tất nhiên chúng ta có thể kết hợp hai lệnh đó để chuyển ngay các mức chìm mặc định trong khi phát lại, ví dụ như với

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

Một nhược điểm của phương pháp này là chỉ số luồng đầu vào thay đổi mỗi khi chúng ta dừng và khởi động lại trình phát nhạc. Vì vậy, chúng tôi luôn phải tìm ra chỉ số luồng hiện tại trước khi có thể chuyển đổi bằng cách sử dụng dòng commmand.


Bạn có thể tham chiếu một bồn rửa theo chỉ mục HOẶC theo tên của nó pactl list short sinks> 4 bluez_sink.FC_A8_9A_2C_EB_0B module-bluez5-device.c s16le 1ch 8000Hz IDLEbây giờ chỉ cần tham chiếu tênpactl set-default-sink bluez_sink.FC_A8_9A_2C_EB_0B
Leif Liddy

@LeifLiddy: Cảm ơn bạn đã lưu ý. Trong các phiên bản gần đây hơn của Pulseaudio bạn thực sự có thể tham chiếu đến tên của một bồn rửa trên set-default-sinknhưng bạn vẫn sẽ cần số chỉ mục trên move-sink-input.
Takkat

Và nếu như 0 sink input(s) available.? Nhưng flash player shitty đó vẫn đang phát âm thanh?
Zhigalin

Và tôi thấy người chơi flash trong client(s) logged inphần củapacmd list
Zhigalin

@Zhigalin Flash đã chết từ lâu trên các hệ thống của tôi vì vậy tôi không thể nói ... nó có thể phát trực tiếp qua ALSA.
Takkat

27

Tôi đã viết một tập lệnh đơn giản để tự động di chuyển tất cả các đầu vào chìm.

Sử dụng: ./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
Tuyệt vời! Tôi đã mở rộng điều này hơn một chút để sử dụng cho riêng mình: Tôi muốn một biểu tượng trên thanh tác vụ của mình có thể chuyển đổi giữa hai thẻ âm thanh. Tôi đã viết một tập lệnh nhỏ trong Ruby để xác định mức chìm hiện tại và gọi ra tập lệnh shell này để thực hiện thay đổi ( pastebin.com/xb3i2ejW ). Sau đó, tôi đặt cả hai tập lệnh vào ~ / bin và tùy chỉnh biểu tượng KDE để chạy tập lệnh ruby. Điều này có thể được thực hiện thanh lịch hơn, hoặc hoàn toàn trong kịch bản shell, nhưng nó hoạt động với tôi.
Tác nhân gây bệnh

2
Cảm ơn vì điều đó. Đây là phiên bản chuyển sang đầu ra cuối cùng (? - Tôi chỉ có hai): pastebin.com/raw/sidH7QPb tức là nó bật đầu ra, phù hợp để ánh xạ tới phím nóng.
Julian

4

Phiên bản cải tiến của tập lệnh @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

bản sao thời gian chạy của tôi là trên github và nó cũng bao gồm tự động chuyển kênh Master chokmix



2

Tôi đã ghép các thứ từ một vài nơi khác nhau và đưa ra kịch bản này để thiết lập một JAMBOX bluetooth sau khi nó được ghép nối. MAC của bạn sẽ khác nhau tất nhiên. Vì tôi kiểm soát âm lượng JAMBOX thông qua ứng dụng Clementine, 130% âm lượng hoạt động tốt nhất trong trường hợp của tôi. Bạn có thể muốn thay đổi điều này, cùng với nhịpbox.png (đó là hình ảnh loa duy nhất tôi có thể tìm thấy trên máy tính của mình). Việc kiểm tra lỗi còn thô sơ, nhưng hoạt động khá đáng tin cậy. Tôi đặt cái này trong trình khởi chạy máy tính để bàn để thuận tiện trên 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

+1 để sử dụng pactl list short. Bạn có thể đơn giản hóa dòng sau bằng cách thực hiện cắt trực tiếp sau: pactl list short sink-inputs | cut -f1 | while read streamIdlàm việc cho tôi.
Bodo

1

MÙA XUÂN-TOGGLE.

Tập lệnh Gaco chỉ với một dòng nữa để chuyển vòng tròn qua các bồn có sẵn.

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

tuyệt vời, đơn giản và nhân rộng!
Paul Bastian

1

Và đây là một kịch bản sẽ chuyển đổi giữa các chìm:

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

Đây là kịch bản dưới đây:

#!/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
Chào mừng bạn đến hỏi Ubuntu! Trong khi về mặt lý thuyết có thể trả lời câu hỏi, tốt hơn là nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo.
ζ--

Xong, mặc dù không may, điều này có nghĩa là tập lệnh không được cập nhật ở đây trừ khi tôi nhớ rằng nó ở đây. Ví dụ, ruby ​​đã thay đổi cách xử lý .each cho chuỗi (trong phần backtick) vì vậy tôi cần cập nhật dòng 53 ở trên. Hoặc chỉ cần tải xuống tập lệnh để đảm bảo nó được cập nhật.
David Ljung Madison Stellar

1

Dựa trên câu trả lời của Gaco, tôi viết lại một chút cho mục đích sử dụng cá nhân của mình. Có lẽ ai đó thấy nó hữu ích. Đó là để chuyển đổi Loa USB và tai nghe USB Gaming của tôi.

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

Tôi nghĩ có một tùy chọn khác đáng được đề cập và nó có sẵn tại trang chính thức cho Câu hỏi thường gặp về PulseAudio tại freedesktop.org . Theo tiêu đề sau:

Làm cách nào để chuyển đổi card âm thanh mặc định, di chuyển tất cả các ứng dụng?

Họ cung cấp các kịch bản sau đây để làm như vậy:

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

Tôi đã điều chỉnh @mpapis thành một "chuyển đổi chìm0 hoặc chìm1" đơn giản khi chạy:

#!/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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.