借助 PulseAudio 在 Telegram 进行音乐广播
Telegram 更新了语音聊天功能,然而中文 TG 用户大多是不会真的用 TG 语音聊天的。那就用它来做音乐/广播串流吧。
(注:码率只有不到 50kbps,全损音质可能)
Telegram 的语音聊天功能只是个引子,本文实际上描述了一个更大的需求面:即使用输出作为输入。除了语音聊天之外,像是通过 Zoom 或其它会议服务进行的动画视频鉴赏会之类。主要的需求是:
- 以设备的音频输出作为这些软件的音频输入
- 不使用物理输入设备(例如麦克风)
- Extra: 不影响自己使用物理音频输出
开始
在本文中可能会用到的软件:
- PulseAudio,本文的主角 (
pulseaudio
) - PulseAudio Volume Control(下称 pavucontrol),图形化控制 PulseAudio 的软件。PulseAudio 的命令行
pacmd
可以替代它,但是这个界面要方便得多。 (pavucontrol
) - VLC 播放器 (
vlc
) - Telegram,或任何你需要用来进行音频串流的工具
一些术语解释
输入和输出
关于音频的传输主要分为两部分,输入和输出。这里的输入和输出是对于设备而言的,也就是说:
- 输入 (input):从(物理或虚拟)设备获取音频到系统软件,也就是「录制」的方向。
- 输入设备 (source):输入的源(物理或虚拟)设备。在 PulseAudio 中一般被称为 source。例如麦克风、有麦克风功能的耳机、还有下文会提到的 monitor 等。
- 输出 (output):从系统软件传递音频至(物理或虚拟)设备,也就是「播放」的方向。
- 输出设备 (sink):输出的目标(物理或虚拟)设备。在 PulseAudio 中一般被称为 sink。例如扬声器、耳机等。
图解的话,大概就是这样:
Source Client Sink
+----------+
--> | Telegram | ---
| +----------+ |
| |
+----------+ | +----------+ | +----------+
| Micphone | --> | Recorder | ----> | Earphone |
+----------+ | +----------+ | +----------+
| |
| +----------+ |
--> | Zoom | ---
+----------+
Monitor
在 PulseAudio 中,每一个输出一般都有一个 Monitor,用于将此输出用作输入。通过命令 pacmd list-sources
可以看到有一些 name 结尾为 .monitor
的输入源,它们就是对应输出的 Monitor。在想把输出作为输入的时候,可以直接使用它们。在本文提到的解决方案中,我们就利用了 Monitor 将输出转化为输入。也就是说,所有的 monitor 都是 source,可以向软件提供音频信息。
Client、Source 与 Sink
PulseAudio clients can send audio to "sinks" and receive audio from "sources".
每一个从 PulseAudio 获取声音的程序都是一个 "client"。通过 pacmd list-clients
可以查看 client 的列表。Client 可以从 source 中获取音频,也可以将音频输入至 sink。
简单方案
如果自己不需要物理音频输出来做其它事情的话,直接使用物理输出作为输入即可。一般是 "Mirror of [你的设备]"。
或者,更复杂但更优雅的方案
创建新的输出设备
我们可以创建一个新输出,直接让播放器(例如 VLC)把音乐这个输出,然后使用这个输出的 Monitor 作为输入,将这个输入传输到其它应用中。用图表示就是大概这样:
Source Client Sink
-----------------------------------------------
| |
| |
| +------------------+ +----------+
| | Player (eg. VLC) | --> | Loopback |
| +------------------+ +----------+
v
+------------+ +---------------------+
| LB Monitor | --> | Telegram, Zoom etc. |
+------------+ +---------------------+
在 Linux 上,我们可以使用 PulseAudio 方便地达到这个目的。
Windows 也有类似的虚拟音频输出端口工具: VB-CABLE。
我们只需要创建一个 null sink。记得设置好它的名字。
pacmd load-module module-null-sink sink_name=SinkOne
我们可以给它一个 description 方便后续查看。
pacmd update-sink-proplist SinkOne device.description=MySink
你可能会注意到,当 description 中出现空格的时候,pacmd
不愿意接收参数。这种时候请这么做:
pacmd 'update-sink-proplist SinkOne device.description="A description sentence"'
(ref)
这样就有了一个新的输出。
我们可以把任何需要通过音频输入串流的音频内容输出到这个输出。例如,在 VLC 中是这样设置:
切换音频输入
之后,我们就可以用这个输出的 Monitor 作为输入,将播放的内容进行串流。选择名字类似 "Monitor of Null Output" 的输入(如果你没有更改它的名字的话)即可。
你也可以使用 pacmd update-source-proplist
来修改这个输入的 description。只要在 pacmd list-sources
找到它的 ID,pacmd update-source-proplist <ID> device.description="Name"
即可。
...或者使用 PulseAudio 指定音频输入
有些软件内部可以切换音频输入源,例如 Telegram:
然而,在它们的输入源列表中,可能看不到特殊输入源(例如本文需要的 Monitor)。比较好的方法是,在这些软件内选择默认的音频输入源,而在 PulseAudio 端切换输入源。在 pavucontrol
中的 "Recording" 标签下找到对应的软件,使用右侧的下拉列表切换输入即可。
注意 Telegram 可能需要先使用其它输入录音(开麦)一次之后才能在 pavucontrol
中看到。
最后
找点好音乐,开始你的 Telegram DJ 之旅吧!
另见
- https://endless.ersoft.org/pulseaudio-loopback/ - 描述了一个更复杂的客制化 PulseAudio 用例。