将选定应用程序的声音与语音结合到虚拟麦克风(Linux)

将选定应用程序的声音与语音结合到虚拟麦克风(Linux)

有时我想通过 Skype、Discord 等与朋友分享音乐。

我不想共享声卡的全部输出(我可以通过将相应的显示器设置为麦克风来实现),因为这样我的朋友就可以听到自己的声音(这很烦人),而且除了音乐之外可能还有其他声音在播放(例如通知),我也不想让他们听到。此外,当我这样做时,我无法再在通话中说话(因为我的麦克风设置为其他设置)。

我如何混合输出声音一些应用程序使用麦克风的声音,并通过语音聊天发送该信号?

我正在使用 Linux Mint。

答案1

(下面我假设使用类似 Ubuntu 的 Linux 发行版 --- 在我的情况下我使用的是 Linux Mint 20.1 Cinnamon --- 并且安装了脉冲音频音量控制;您可以使用它进行安装sudo apt install pavucontrol。如果您没有做一些太奇怪的事情,这应该适用于任何 Linux 发行版,但我不保证。我在进行过程中也弄清楚了以下内容,因此对于任何不准确之处,请谅解。)

首先,让我介绍一下与 Pulse Audio 相关的概念,这样可以更容易理解下面的解释:

  • A下沉是“消耗”音频信号(可能将该信号转换为实际声音之类的东西)的东西。这意味着您的扬声器等就是接收器。您也可以将它们称为输出设备。

  • A来源是相反的概念;它是产生信号的东西,比如麦克风。您也可以将它们称为输入设备。

  • A监视器是为计算机上的每个输出设备(接收器)创建的虚构(虚拟)输入设备(源)。它只是重现相应源上输出的声音,就像它进入计算机一样。

你还应该知道,使用 Pulse Audio 时,有三个主要工具:GUIPulse Audio Volume Control界面(你可以从终端启动)pavucontrolpactl命令,以及pacmd命令。

该命令的大多数功能(我们感兴趣的)pactl都是通过内置“模块”实现的。你可以使用以下命令调用这些模块

pactl load-module <module name> <parameters>

并解除它们/逆转它们的效果

pactl unload-module <module name>

由此所做的更改不是永久性的;如果感到恐慌,只需注销并重新登录,就可以重新开始。

pactl的反馈也相当差 --- 每当你的命令出现问题时,它都会半默默地失败,并显示“失败:模块初始化失败” --- 但你可以找到一个相当不错的文档参考这里

好的,那么,以下是我们可用的原料和游戏计划:

  1. 我们可以创建所谓的“零接收器”。这些是虚拟接收器设备,能够像扬声器一样接收信号,但不播放声音。这些是通过module-null-sink模块

  2. 我们可以将声音从源“回送”到接收器。例如,可以将其视为将麦克风传来的声音直接转发到扬声器中。这是通过module-loopback模块

  3. 我们可以通过界面选择将每个应用程序的声音播放到哪个接收器中pavucontrol;每当有多个接收器时,您可以在“播放”选项卡中选择每个应用程序要使用的接收器。

该计划如下:

  1. 找出我们声卡的源(内置麦克风)和接收器(扬声器/耳机)

  2. 创建一个空接收设备(transmit),用于接收我们想要广播的应用程序的声音

  3. 将声音从transmit声卡回送,这样我们也可以听到我们正在广播的内容(因为请记住,空接收器只会丢弃它们接收到的内容)

  4. 创建另一个空接收器设备(combined)来接收transmit 麦克风的声音——这是我们想要广播的信号,但不是我们想听到的,因为我们不想听到自己说话

  5. 在 Skype 通话中使用显示器combined作为虚拟麦克风

为了将计划付诸实施:

0. 找出我们内置的接收器/源

pactl让我们轻松枚举我们的接收器/源:

pactl list sinks

告诉我们有关单个水槽的信息

Sink #0
    State: IDLE
    Name: alsa_output.pci-0000_00_1f.3.analog-stereo
    Description: Built-in Audio Analog Stereo
    
    (... more information ...)

这是我的声卡的输出,即笔记本电脑的扬声器或耳机,我们可以找到源

pactl list sources

得出

Source #0
    State: RUNNING
    Name: alsa_output.pci-0000_00_1f.3.analog-stereo.monitor
    Description: Monitor of Built-in Audio Analog Stereo
    
    (... more information ...)
    
    Properties:
        device.description = "Monitor of Built-in Audio Analog Stereo"
        device.class = "monitor"
        alsa.card = "0"
        alsa.card_name = "HDA Intel PCH"

    (... more information ...)

Source #1
    State: RUNNING
    Name: alsa_input.pci-0000_00_1f.3.analog-stereo
    Description: Built-in Audio Analog Stereo
        
    (... more information ...)

我的计算机上设置了两个源:alsa_input.pci-0000_00_1f.3.analog-stereo,这是我的内置麦克风(来自声卡),alsa_output.pci-0000_00_1f.3.analog-stereo.monitor这是接收器的监视器alsa_output.pci-0000_00_1f.3.analog-stereo,即从我的扬声器或耳机发出的声音,就像进入 PC 一样。

1. 创建transmit水槽

这很简单,只需执行以下操作module-null-sink

pactl load-module module-null-sink sink_name=transmit

请注意,我们将这个新接收器命名为transmit,但如果你查看pavucontrol,在“输出设备”选项卡下,你会发现确实有一个新设备,但它被称为“空输出”。这是因为pavucontrol显示设备的描述作为显示名称;如果我们再次枚举我们的接收器......

$ pactl list sinks

(... other sinks ...)

Sink #6
    State: IDLE
    Name: transmit
    Description: Null Output
    
    (... more information ...)

    Properties:
        device.description = "Null Output"
        device.class = "abstract"
        device.icon_name = "audio-card"
    Formats:
        pcm

我们可以看到接收器确实名为transmit,但其device.description属性显示为“Null Output”。我们可以用 来修复该问题pacmd

pacmd 'update-sink-proplist transmit device.description="Signals to Transmit"'

(如果你收到“无法解析 proplist。”的提示,注意单引号

当我们创建空接收器时,也会创建transmit相应的监视源。(您可以通过再次调用来检查这一点。)我们还应该修复它的名称,我们可以再次使用:transmit.monitorpactl list sourcespacmd

pacmd 'update-source-proplist transmit.monitor device.description="Monitor of Signals to Transmit"'

现在,如果您播放一些音乐,您将能够将该信号转发到播放标签 下的新接收器pavucontrol。但是,由于该信号正在播放到空接收器,因此该信号不再可听见;让我们修复这个问题。

2. 回送来自transmit

回想一下,当发送到(在我的情况下)接收器 0 时,声音会从扬声器/耳机中播放出来alsa_output.pci-0000_00_1f.3.analog-stereo。然后,如果我们将进入接收器的声音回transmit送到这个接收器,我们应该能够再次听到它。当然,我们不能回送来自下沉,信号必须来自一个源。幸运的是,監視器正是进入接收器的信号,以源的形式呈现。

然后让我们回transmit.monitor送到我们的声卡,使用module-loopback

pactl load-module module-loopback source=transmit.monitor sink=alsa_output.pci-0000_00_1f.3.analog-stereo

现在您应该能够再次听到发送到“要传输的信号”接收器的声音。

3. 结合transmit麦克风

现在的过程与第 1 点和第 2 点非常相似;我们将创建另一个接收信号transmit.monitor和麦克风输入的零接收器。该信号的监视器将用作虚拟麦克风。

我们首先创建空接收器combined...

pactl load-module module-null-sink sink_name=combined

...并修复出现的默认名称pavucontrol...

pacmd 'update-sink-proplist combined device.description="Transmit+Microphone Sink"'
pacmd 'update-source-proplist combined.monitor device.description="Transmit+Microphone"'

...最后将我们的麦克风和transmit监视器环回到组合通道:

pactl load-module module-loopback source=alsa_input.pci-0000_00_1f.3.analog-stereo sink=combined
pactl load-module module-loopback source=transmit.monitor sink=combined

4.利润

现在,在设置通话时,应该有一个名为“Transmit+Microphone”的麦克风可用 --- 这是您选择的声音和您的声音的组合信号。

请注意,所有这些环回等操作都可能导致 CPU 开销,但我的笔记本电脑性能并不强大,除了一些延迟外,我没有遇到任何问题。要撤消上述所有操作,请调用

pactl unload-module module-loopback
pactl unload-module module-null-sink

或注销并重新登录。

总结

pactl load-module module-null-sink sink_name=transmit
pacmd 'update-sink-proplist transmit device.description="Signals to Transmit"'
pacmd 'update-source-proplist transmit.monitor device.description="Monitor of Signals to Transmit"'
pactl load-module module-null-sink sink_name=combined
pacmd 'update-sink-proplist combined device.description="Transmit+Microphone Sink"'
pacmd 'update-source-proplist combined.monitor device.description="Transmit+Microphone"'
pactl load-module module-loopback source=alsa_input.pci-0000_00_1f.3.analog-stereo sink=combined
pactl load-module module-loopback source=transmit.monitor sink=combined
pactl load-module module-loopback source=transmit.monitor sink=alsa_output.pci-0000_00_1f.3.analog-stereo

如果这对您不起作用,请阅读该帖子,但alsa_input.pci-0000_00_1f.3.analog-stereo对您来说可能会有所不同。

相关内容