Як змінити раковину pulseaudio на "pacmd set-default-sink" під час відтворення?


55

Мені потрібно переключити імпульсний сервер поточного аудіо потоку.

Сервер 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 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Наведені тут то , що нам потрібно для адресація мийки з допомогою командного рядка. Нинішня раковина за замовчуванням позначена зірочкою (тут 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

Недоліком цього методу є те, що індекс вхідного потоку змінюється кожного разу, коли ми зупиняємось і перезапускаємо музичний плеєр. Таким чином, ми завжди повинні з'ясувати поточний індекс потоку, перш ніж ми зможемо переключитися за допомогою командної лінії.


Ви можете посилатися на раковину за її індексом АБО за її назвою 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
Лейф Лідді

@LeifLiddy: Дякую за замітку. В останніх версіях Pulseaudio ви дійсно можете посилатися на ім’я мийки, set-default-sinkале вам все одно знадобиться номер індексу move-sink-input.
Таккат

А що якщо 0 sink input(s) available.? Але той лайно-флеш плеєр все ще відтворює аудіо?
Жигалін

І я бачу флеш плеєр у client(s) logged inрозділіpacmd list
Жигалін

@Zhigalin Flash давно мертвий у моїх системах, тому я не можу сказати, що він може грати безпосередньо через ALSA.
Таккат

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 для запуску сценарію ruby. Це можна зробити більш елегантно або повністю в сценарії оболонки, але це працює для мене.
Збудник

2
Дякую за це Ось версія, яка перемикається на останній (? - у мене є лише два) невикористаного виводу: pastebin.com/raw/sidH7QPb, тобто він перемикає вихід, придатний для відображення на гарячу клавішу.
Джуліан

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

Я спільно зібрав речі з декількох різних місць і придумав цей сценарій, щоб створити Bluetooth JAMBOX після того, як він був сполучений. Звичайно, ваш MAC буде іншим. Оскільки я контролюю гучність JAMBOX за допомогою програми Clementine, в моєму випадку найкраще працює 130% об'єм. Ви можете змінити це разом із ritbox.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працює для мене.
Бодо

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

чудово, просто і масштабування!
Пол Бастіан

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! Хоча це теоретично може відповісти на питання, бажано було б сюди включити істотні частини відповіді та надати посилання для довідки.
ζ--

Зроблено, хоча, на жаль, це означає, що сценарій не оновлюється тут, якщо я не пам’ятаю, що він знаходиться тут. Як приклад, ruby ​​змінив спосіб обробки .each для рядків (у частині backtick), тому мені потрібно було оновити рядок 53 вище. Або просто скачайте сценарій, щоб переконатися, що він актуальний.
Девід Люнг Медісон Зоряний

1

На основі відповіді Гако я трохи переписав це для особистого використання. Можливо, хтось вважає це корисним. Це для перемикання моїх динаміків 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 or 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.