自动在内置扬声器和 HDMI 扬声器之间切换

UTF*_*F-8 20 sound pulseaudio hdmi alsa 16.04

您知道如何将耳机插入笔记本电脑的辅助插孔时,内置扬声器会自动静音并且声音从耳机中传出吗?我想要的正是 HDMI。

有时,我将带有内置扬声器的显示器连接到我的笔记本电脑以观看视频。当视频在显示器上(距离我的桌子 3 m 远)但声音从我的笔记本电脑的内置扬声器(笔记本电脑放在桌子上)上时,这很奇怪。

当然,我可以直接进入声音设置,将输出通道切换到HDMI。但是,后来,当我几个小时前移除 HDMI 电缆并且甚至可能在一个完全不同的位置时,声音将无法播放,因为声音服务器仍然尝试通过 HDMI 播放它,但没有任何连接到它.

在没有通过 HDMI 连接设备时自动切换回内置扬声器更为重要,但在连接设备时切换到通过 HDMI 输出的声音仍然非常好。

这显然适用于 11.10,但不适用于 16.04。

Win*_*nix 9

背景

当声音从 HDMI 电视切换到笔记本电脑扬声器时,我在暂停/恢复期间遇到了类似的问题。恢复后声音会留在笔记本电脑扬声器上,我必须手动将输出设备重置为 TV in System Settings-> Sound

这是我从Ubuntu 14.04升级到16.04 的第一个烦人的经历之一,根是升级到16.04 LTS附带的 PulseAudio 8

经过大量搜索,我创建了一个名为TV-sound. 虽然我不像你自己那样插拔电视,但我做了一些谷歌搜索并创建了脚本的变体来适应你的情况。我已经测试过它并且有效。

第 1 步:创建脚本以在连接的设备之间切换音频

我们将创建一个名为hotplugtvwhich udev 调用的脚本。但是,可以在许多地方调用相同的脚本。例如,在测试期间,我lock-screen-timer在屏幕锁定期间声音恢复到笔记本电脑的情况下使用它。

cd /usr/local/bin
sudo touch hotplugtv
sudo chmod +x hotplugtv
gksu gedit hotplugtv
Run Code Online (Sandbox Code Playgroud)

当编辑器以空白屏幕打开时,将以下内容复制并粘贴到其中:

#! /bin/bash

# NAME: hotplugtv
# PATH: /usr/local/bin
# DESC: Update pulseaudio output device when HDMI TV plugged / unplugged
# CALL: called from /etc/udev/rules.d/99-monitor-hotplug.rules
# DATE: Created Nov 26, 2016.
# NOTE: logs output using log-file
# UPDT: Dec 14, 2016 - Sometimes /sys/class/drm/card0 & sometimes /sys/class/drm/card1
#       so use /sys/class/dmcard* instead.

if [[ $(cat /sys/class/drm/card*-HDMI-A-1/status | grep -Ec "^connected") -eq 1 ]]; then
#        log-file "HDMI TV connected" ~/bin/log-hotplugtv;
        /bin/sleep 2;
        export PULSE_RUNTIME_PATH="/run/user/1000/pulse/";
        sudo -u rick -E pacmd set-card-profile 0 output:hdmi-stereo;
else
#        log-file "HDMI TV disconnected" ~/bin/log-hotplugtv;
        export PULSE_RUNTIME_PATH="/run/user/1000/pulse/";
        sudo -u rick -E pacmd set-card-profile 0 output:analog-stereo;
fi

exit 0
Run Code Online (Sandbox Code Playgroud)

您将需要rick用您自己的用户 ID替换两次出现的, ieUTF-8等。

我知道这可以更专业,将用户名自动设置为 bash 变量,但我还不是那么熟练:(无论如何,保存文件并退出gedit

第二步:创建udev规则

当您插入和拔出 HDMI 显示器时,udev 会监控热插拔事件。键入以下内容以创建新规则。

cd /etc/udev/rules.d
sudo cp 70-persistent-net.rules 99-hotplugtv.rules
gksu gedit 99-hotplugtv.rules
Run Code Online (Sandbox Code Playgroud)

注意:如果70-persistent-net.rules您的目录中不存在该文件,请复制其中的任何其他文件。我们不需要文件内容,只需要文件权限以确保我们的内容相同。

编辑器会显示一堆不相关的文本,突出显示并删除它。然后突出显示下面的代码并将其粘贴到编辑器中:

# NAME: 99-hotplugtv.rules
# PATH: /etc/udev/rules.d
# DESC: Update pulseaudio output device when HDMI TV plugged / unplugged
# CALL: automatically called on system events
# DATE: Created Nov 26, 2016.
# NOTE: in future may requre systemd service hooks

ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/usr/local/bin/hotplugtv"
Run Code Online (Sandbox Code Playgroud)

保存文件并退出。

要启用规则(无需重启),我们需要重新加载 udev:

sudo udevadm control --reload-rules
Run Code Online (Sandbox Code Playgroud)

现在您可以插拔您的 HDMI 显示器/电视,声音会相应地切换。

警告

在我的系统上,当拔下 HDMI 时,声音会自动恢复到笔记本电脑扬声器。在你的系统上它没有。如果在拔下 HDMI 时声音没有传到您的笔记本电脑扬声器,则可能需要进一步增强代码。请通过下面的评论回复事情如何运作/不运作。

CLI 中的快速测试

您可以使用以下命令在终端快速测试代码:

    export PULSE_RUNTIME_PATH="/run/user/1000/pulse/";
Run Code Online (Sandbox Code Playgroud)
  • 切换到 HDMI/电视:

        sudo -u rick -E pacmd set-card-profile 0 output:hdmi-stereo;
    
    Run Code Online (Sandbox Code Playgroud)
  • 切换回内置扬声器:

        sudo -u rick -E pacmd set-card-profile 0 output:analog-stereo;
    
    Run Code Online (Sandbox Code Playgroud)
  • 记得rick用你的用户名替换。

  • 最初的export行可能不是必需的,但为了安全起见,我将其包含在内。
  • 如果您有多个声卡,或者hdmi-stereo在编写脚本之前显然需要进行调整以找出正确的参数。

在 PulseAudio 中解密您的设备名称

下面的代码两次使用相同的命令。一旦声音设置为外部 HDMI 电视。第二次将声音设置为笔记本电脑的内置扬声器。每次您看到 PulseAudio 使用的名称时:

$ pacmd list-sinks | grep -e 'name:' -e 'index'
  * index: 28
    name: <alsa_output.pci-0000_00_1b.0.hdmi-stereo>
???????????????????????????????????????????????????????????????????????????????
$ pacmd list-sinks | grep -e 'name:' -e 'index'
  * index: 30
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
Run Code Online (Sandbox Code Playgroud)

当您有多个声卡时

使用该命令aplay -l查看是否有大于 0 的卡。如果是,则需要在脚本中使用适当的卡号。例如:

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: 92HD91BXX Analog [92HD91BXX Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 3: HDMI 0 [HDMI 0]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,所有卡号均为 0,具有不同的输出源。如果您有 USB 扬声器,它们的卡号可以与 0 不同。

编辑 2016 年 12 月 2 日

由于某种未知的原因,脚本今天被破坏了。上面的代码以前是这样写的:“$(cat /sys/class/drm/card0-HDMI-A-1/status”但是我不得不改成card0这样card1,上面的代码已经修改了。我无法解释发生了什么变化自 2016 年 11 月 26 日以来,在我的系统上,除了常规的 Ubuntu 更新。

编辑 2016 年 12 月 14 日

上面的代码需要再次切换回:“$(cat /sys/class/drm/card0-HDMI-A-1/status”。而不是修改代码之间card0card1依赖于引导,修改程序引用card*以捕获两种情况.