Ubuntu实时读取音乐软件的音频流

文章目录

  • [一. 前言](#一. 前言)
  • [二. 开发环境](#二. 开发环境)
  • [三. 具体操作](#三. 具体操作)
  • [四. 实际效果](#四. 实际效果)

一. 前言

起因是这样的,我需要在Ubuntu中,实时读取正在播放音乐的音频流,然后对音频进行相关的处理。本来打算使用的**Pipewire+Helvum** 的方式实现,好处是可以直接利用Helvum图形化工具对软件输出的音频进行重定向,但是由于使用的是**Ubuntu20.04** ,默认的音频服务器使用的是PulseAudio,替换为Pipewire后,播放的音频会出现卡顿不流畅,最终还是使用原生的**PulseAudio+pavucontrol**来实现实时播放的音频的处理。

二. 开发环境

Ubuntu: Ubuntu 20.04.6 LTS

虚拟机: VMware Workstation 17 Pro

音频服务器: PluseAudio

音频IO库: Portaudio

音频驱动: Alsa

开发语言: C/C++

三. 具体操作

举个例子,我们需要在Ubuntu中实时获取QQ音乐目前正在播放的音频流,我们需要按如下步骤进行操作:

1. 创建虚拟设备:

bash 复制代码
pactl load-module module-null-sink sink_name=music sink_properties=device.description="Virtual_Music_Sink"  

终端输入指令,通过加载**module-null-sink**模块,PulseAudio 创建了一个虚拟的音频输出设备,其名称为 "music"。该虚拟设备不会直接输出声音,但它会自动生成一个监控源,记录所有发送到该虚拟设备的音频数据。

指令部分 作用
pactl PulseAudio 控制工具(PulseAudio Control)
load-module 加载一个 PulseAudio 模块
module-null-sink 加载 Null Sink 模块,创建一个虚拟音频输出设备
sink_name=music 指定新创建的虚拟设备名称为 music
sink_properties=device.description="Virtual_Music_Sink" 设置设备的描述信息,在pavucontrol中显示为 "Virtual_Music_Sink"

2. 设置 QQ 音乐的音频输出:

bash 复制代码
pavucontrol

终端输入指令,**pavucontrol**打开(PulseAudio 音量控制工具),在 "Playback" 选项卡中将 QQ 音乐的输出设备改为你刚创建的 "music" 虚拟设备。

3. 将虚拟设备输出到扬声器中:

为了保证你能听到音频,还需要把虚拟设备"music" 的音频输出送到物理扬声器。这可以通过加载**module-loopback**环回模块实现:

bash 复制代码
pactl load-module module-loopback source=music.monitor sink=alsa_output.pci-0000_02_02.0.analog-stereo
部分 作用
pactl PulseAudio 控制工具(PulseAudio Control)
load-module 加载一个 PulseAudio 模块
module-loopback 加载 Loopback 模块,用于将音频流从一个设备转发到另一个设备
source=music.monitor 指定 音频来源 为 music.monitor(虚拟设备 music 的监控源)
sink=alsa_output.pci-0000_02_02.0.analog-stereo 指定音频目标为 alsa_output.pci-0000_02_02.0.analog-stereo(物理扬声器)

需要注意的是:sink后面的物理扬声器信息需要根据自己的电脑来定。

4. 在 PortAudio 中捕捉音频:

cpp 复制代码
// PortAudio回调函数
static int paCallback(const void* inputBuffer, void* outputBuffer,
                      unsigned long framesPerBuffer,
                      const PaStreamCallbackTimeInfo* timeInfo,
                      PaStreamCallbackFlags statusFlags,
                      void* userData)
{
    return paContinue;
}

int main()
{
    PaStreamParameters inputParameters;
    inputParameters.device = Pa_GetDefaultInputDevice();

    inputParameters.channelCount = 1;            
    inputParameters.sampleFormat = paFloat32;    
    const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(inputParameters.device);
    inputParameters.suggestedLatency = deviceInfo->defaultLowInputLatency;
    inputParameters.hostApiSpecificStreamInfo = nullptr;

    PaStream* stream = nullptr;
    Pa_OpenStream(&stream,
                        &inputParameters,
                        nullptr,              // 不使用输出流
                        SAMPLE_RATE,
                        FRAMES_PER_BUFFER,
                        paNoFlag,
                        paCallback,
                        nullptr);

    Pa_StartStream(stream);

	while(1)
	{}
}

5. pavucontrol修改程序音频入口:

打开pavucontrol后,在Recording中,把启动的应用程序的输入入口修改为Virtual_Music_Sink,这样就把程序的录音入口修改为我们的虚拟设备,由于前面我们使用load-module环回模块,已将QQ音乐中的输出重定向至Virtual_Music_Sink虚拟设备中,那么此时,Portaudio收到的input设备获得的音频流便是QQ音乐输出的音频流。

四. 实际效果

通过上述操作,我们可以采集到的QQ音乐中播放的音频,我们实时去捕捉音频中的节奏点,再通过Implot画出实时的歌曲的音频曲线和节奏信息,效果如下:

相关推荐
小猫挖掘机(绝版)1 分钟前
kalibr进行相机内参以及相机imu的融合标定
ubuntu·无人机·slam·标定·vinsfusion
Siren_dream5 分钟前
在VMware上运行Linux(我选择的是Ubuntu)
linux·运维·ubuntu
张晓~183399481218 分钟前
碰一碰发视频 系统源码 /PHP 语言开发方案
开发语言·线性代数·矩阵·aigc·php·音视频·文心一言
Cabbage_acmer17 分钟前
MySQL期中考试突击!
数据库·mysql
Lu Yao_22 分钟前
Redis 缓存
数据库·redis·缓存
迷路爸爸18042 分钟前
源码编译安装最新 tmux 教程(含 Debian/Ubuntu/CentOS/Arch/macOS 等系统)
linux·ubuntu·macos·centos·debian·tmux·archlinux
小桥流水人家哇1 小时前
性能测试单场景测试时,是设置并发读多个文件,还是设置不同的用户读不同的文件?
数据库·性能测试技巧
表示这么伤脑筋的题我不会1 小时前
Oracle 21C 部署ogg踩过的坑
数据库·oracle
你不是我我1 小时前
【Java 开发日记】MySQL 与 Redis 如何保证双写一致性?
数据库·redis·缓存
望获linux1 小时前
【实时Linux实战系列】实时 Linux 在边缘计算网关中的应用
java·linux·服务器·前端·数据库·操作系统