재생 중에 "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 미디어 플레이어가 노래를 재생하고 있습니다.

소스 측에 펄스 오디오가있는 새로운 터널 싱크를 만들었습니다.

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

그러나 오디오를 재생하는 동안 서버를 즉시 변경할 수 없었습니다. 플레이어를 멈추고 다시 재생 한 후에 만 ​​괜찮습니다.

출력 장치의 "gnome-volume-control"또는 "gnome-control-center sound"전환에서 즉시 적용됩니다.

사운드 파일을 재생하는 동안 명령 줄에서 즉시 출력 싱크 전환을 적용하려면 어떻게해야합니까?

답변:


83

PulseAudio pacmd는 싱크 입력으로 스트림을 재생하는 동안 기본 싱크를 전환 할 수 없습니다. 그러나 여전히 이것을 달성 할 수있는 방법이 있습니다.

명령 줄에서 기본 싱크 변경

먼저 전환하려는 싱크의 색인 번호를 결정해야합니다. 다음을 호출하여 수행 할 수 있습니다.

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에 필요한 것입니다. 현재 기본 싱크에는 별표 (여기 0) 가 표시되어 있습니다 .

명령 줄에서 기본 싱크를 전환하려면 다음과 같이 해당 라인을 편집하여 스트림 대상 장치 복원비활성화 해야 /etc/pulse/default.pa합니다.

load-module module-stream-restore restore_device=false

싱크로 기본 출력 싱크를 변경하려면 1다음을 실행하십시오.

pacmd set-default-sink 1

소리 설정 메뉴를 열어 성공을 시각화 할 수 있습니다 .

스트림을 다른 싱크로 이동

지정된 싱크로 재생중인 활성 입력 스트림이있는 동안 기본 싱크를 변경해 도 아무런 영향이 없습니다 . 이 입력을 다른 싱크로 이동하여 수행해야합니다.

pacmd list-sink-inputs

입력 스트림의 인덱스를 알려줍니다

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

이제 우리는 호출 하여 입력 스트림 5을 싱크로 옮기고 싶다는 것을 알고 있습니다.1

pacmd move-sink-input 5 1

0원한다면 다시 싱크대로 재생을 중단 할 필요없이 바로 수행됩니다.

재생 중 기본 싱크 변경

물론이 두 명령을 결합하여 재생 중에 기본 싱크를 즉시 전환 할 수 있습니다.

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

이 방법의 단점은 음악 플레이어를 중지했다가 다시 시작할 때마다 입력 스트림 색인이 변경 된다는 것 입니다. 따라서 commmand 행을 사용하여 전환하기 전에 항상 현재 스트림 색인을 찾아야합니다.


색인 또는 이름으로 싱크를 참조 할 수 있습니다. 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에서 작은 스크립트를 작성 하고이 쉘 스크립트를 호출하여 변경을 수행합니다 ( pastebin.com/xb3i2ejW ). 그런 다음 두 스크립트를 ~ / bin에 넣고 KDE 아이콘을 사용자 정의하여 루비 스크립트를 실행했습니다. 이것은 더 우아하거나 완전히 쉘 스크립트로 수행 할 수는 있지만 나에게 효과적입니다.
병원체

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은 물론 다릅니다. Clementine 앱을 통해 JAMBOX 볼륨을 제어하므로 필자의 경우 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

사용하는 일 pactl list short. 바로 다음 컷을 수행하여 다음 줄을 단순화 할 수 있습니다 pactl list short sink-inputs | cut -f1 | while read streamId.
bodo

1

순환 토글 싱크.

가용 싱크를 통해 전환 할 수있는 라인이 하나 더있는 Gaco 스크립트.

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

위대하고 간단하며 스케일링!
Paul Bastian

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
Ask Ubuntu에 오신 것을 환영합니다! 이 이론적으로 질문에 대답 할 수 있습니다 동안, 바람직 할 것이다 여기에 대한 대답의 본질적인 부분을 포함하고 참조 할 수 있도록 링크를 제공합니다.
ζ--

안타깝게도 스크립트가 여기에 있다는 것을 기억하지 않으면 여기에 스크립트가 업데이트되지 않습니다. 예를 들어, 루비는 (백틱 부분의) 문자열에 대해 .each를 처리하는 방식을 변경 했으므로 위의 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

언급 할 가치가있는 옵션이 하나 더 있다고 생각 하며 freedesktop.org의 PulseAudio 에 대한 FAQ를 공식 페이지에서 사용할 수 있습니다 . 다음 제목에서 :

모든 응용 프로그램을 이동하여 기본 사운드 카드를 전환하려면 어떻게합니까?

이를 위해 다음 스크립트를 제공합니다.

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