当前位置: 首页 > news >正文

【Agent】在基于WSL2的Linux的ALSA输出音频

Linux使用ALSA作为音频驱动。作为Agent的音频输出,我计划在WSL(Ubuntu 22.04.5 LTS)上播放音频。

起因

WSL默认没有安装alsa工具包,需要通过如下命令安装:

sudo apt install alsa-utils

安装成功后,尝试执行如下命令打印音频设备:

bluebonnet27@bluebonnet27:~$ aplay -l
aplay: device_list:274: no soundcards found...

怎么会没有音频设备呢?

为WSL2添加音频驱动

WSL2使用的是微软定制的Linux内核,为了保持轻量级,默认不包含许多硬件驱动,包括音频驱动。
网上使用socket共享的方式适用于旧版的WSL,新版的WSLg使用了更简单的方式映射音频设备。

执行wsl --version查询wsl版本:

WSL 版本: 2.6.1.0
内核版本: 6.6.87.2-1
WSLg 版本: 1.0.66
MSRDC 版本: 1.2.6353
Direct3D 版本: 1.611.1-81528511
DXCore 版本: 10.0.26100.1-240331-1435.ge-release
Windows: 10.0.26100.6584

执行以下命令,以配置PulseAudio使用WSLg的音频服务:

# 创建或编辑PulseAudio配置文件
mkdir -p ~/.config/pulse
echo "default-server = unix:/mnt/wslg/PulseServer" > ~/.config/pulse/client.conf

此时/mnt/wslg/下会多出一个链接:

total 56
srwxrwxrwx  1 bluebonnet27 bluebonnet27     0 Sep 27 18:47 PulseAudioRDPSink
srwxrwxrwx  1 bluebonnet27 bluebonnet27     0 Sep 27 18:47 PulseAudioRDPSource
srwxrwxrwx  1 bluebonnet27 bluebonnet27     0 Sep 27 18:47 PulseServer
drwxr-xr-x 19 root         root          4096 Sep 27 18:46 distro
drwxr-xr-x 65 root         root          4096 Sep 13  2024 doc
-rw-------  1 bluebonnet27 bluebonnet27  1371 Sep 27 18:47 pulseaudio.log
drwxr-xr-x  3 root         root            60 Sep 27 18:46 run
drwxrwxrwx  3 bluebonnet27 bluebonnet27   100 Sep 27 18:47 runtime-dir
-r--r--r--  1 root         root           893 Sep 27 18:47 stderr.log
-rw-r--r--  1 root         root           329 Sep 13  2024 versions.txt
-rw-rw-rw-  1 bluebonnet27 bluebonnet27 32091 Sep 27 19:45 weston.log
-rw-rw-rw-  1 bluebonnet27 bluebonnet27  1679 Sep 27 18:47 wlog.log

接下来,默认的ALSA 直接访问硬件设备(通过 /dev/snd/ 设备节点),而 WSLg 中默认不创建这些节点(因为音频是通过 PulseAudio 桥接到 Windows,而非直接暴露硬件),所以会显示 “无设备”。因此,需要添加全局配置:

sudo tee /etc/asound.conf <<EOF
pcm.!default {type pulse
}
ctl.!default {type pulse
}
pcm.pulse {type pulse
}
ctl.pulse {type pulse
}
EOF

最后,需要安装一个语音相关的库:

sudo apt install libasound2-plugins

重启WSL,此时使用aplay -L就能打印设备了:

nullDiscard all samples (playback) or generate zero samples (capture)
samplerateRate Converter Plugin Using Samplerate Library
speexrateRate Converter Plugin Using Speex Resampler
jackJACK Audio Connection Kit
ossOpen Sound System
pulsePulseAudio Sound Server
upmixPlugin for channel upmix (4,6,8)
vdownmixPlugin for channel downmix (stereo) with a simple spacialization
default

ubuntu有默认的测试音频,可以播放试试:

aplay /usr/share/sounds/alsa/Front_Center.wav

或者使用alsamixer打开声音面板:
alsamixer
因为是pulseaudio转的音频设备,因此只有默认这一种设备。

使用pyaudio播放

安装pyaudio之前,需要安装如下依赖:

sudo apt install python3-pyaudio portaudio19-dev libpulse-dev

然后安装即可:

pip install pyaudio

如下python代码可以打印当前pyaudio能读取到的音频设备,我们只是确认有即可,由于之前的原因,这里应该只有一个设备。

import pyaudiop = pyaudio.PyAudio()
for i in range(p.get_device_count()):dev = p.get_device_info_by_index(i)print(f"设备 {i}: {dev}")
p.terminate()

打印信息如下(略去ALSA的打印):

设备 0: {'index': 0, 'structVersion': 2, 'name': 'pulse', 'hostApi': 0, 'maxInputChannels': 32, 'maxOutputChannels': 32, 'defaultLowInputLatency': 0.008684807256235827, 'defaultLowOutputLatency': 0.008684807256235827, 'defaultHighInputLatency': 0.034807256235827665, 'defaultHighOutputLatency': 0.034807256235827665, 'defaultSampleRate': 44100.0}
设备 1: {'index': 1, 'structVersion': 2, 'name': 'default', 'hostApi': 0, 'maxInputChannels': 32, 'maxOutputChannels': 32, 'defaultLowInputLatency': 0.008684807256235827, 'defaultLowOutputLatency': 0.008684807256235827, 'defaultHighInputLatency': 0.034807256235827665, 'defaultHighOutputLatency': 0.034807256235827665, 'defaultSampleRate': 44100.0}

接下来就可以编写代码,使用pyaudio播放音频了。我这里给一个示例代码:

import pyaudio
import wave
import sysdef list_audio_devices():"""列出所有可用的音频输出设备"""p = pyaudio.PyAudio()print("可用音频输出设备:")for i in range(p.get_device_count()):device_info = p.get_device_info_by_index(i)if device_info.get('max_output_channels', 0) > 0:default = "(默认设备)" if device_info['default_output'] else ""print(f"  设备 {i}: {device_info['name']} {default}")p.terminate()def play_wav(file_path, device_index=None):"""播放WAV文件:param file_path: WAV文件路径:param device_index: 输出设备索引,None表示使用默认设备"""# 打开WAV文件try:wf = wave.open(file_path, 'rb')except FileNotFoundError:print(f"错误:找不到文件 {file_path}")return# 初始化PyAudiop = pyaudio.PyAudio()# 打开音频流stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),channels=wf.getnchannels(),rate=wf.getframerate(),output=True,output_device_index=device_index  # 指定输出设备,None则使用默认)# 读取并播放音频数据print(f"开始播放 {file_path}...")chunk = 1024data = wf.readframes(chunk)while data:stream.write(data)data = wf.readframes(chunk)# 清理资源print("播放结束")stream.stop_stream()stream.close()wf.close()p.terminate()if __name__ == "__main__":# 默认播放的WAV文件路径wav_file = "/usr/share/sounds/alsa/Front_Center.wav"# 列出可用设备list_audio_devices()# 询问用户是否使用默认设备use_default = input("\n是否使用默认输出设备?(y/n): ").strip().lower()if use_default == 'n':try:device_idx = int(input("请输入要使用的设备索引:").strip())play_wav(wav_file, device_idx)except ValueError:print("无效的设备索引,使用默认设备播放")play_wav(wav_file)else:play_wav(wav_file)
http://www.dtcms.com/a/414296.html

相关文章:

  • LeetCode:68.寻找两个正序数组的中位数
  • 在 Unity 中使用 SoundTouch 插件控制音频倍速播放
  • 通过keepalived搭建MySQL双主模式的MySQL集群
  • MySQL压缩表创建指南
  • 简述网站的建站流程做一个旅游团网站怎么做
  • ApplicationContext接口实现(三)
  • 英文版网站建设的意义网站怎么做友链
  • 第5章:前后端编码规范
  • Java实现文件下载
  • Python api示例
  • StarRocks:Connect Data Analytics with the World
  • deepseek Kotlin Channel 详细学习指南
  • 网站市场推广东莞 网站制作
  • 面试题回顾
  • Visual Studio 2026 IDE发布了
  • 在MCUXpresso IDE中建立使用静态库的工程
  • 【人工智能通识专栏】第二十八讲:IDE集成Deepseek
  • 电子商务网站建设参考书软文时光发稿平台
  • Flask与Django:Python Web框架的哲学对决
  • Android 消息循环机制
  • 若依前后端分离版集成到企业微信自建应用
  • 电商网站建设心得ps做网站首页怎么运用起来
  • 免费建一级域名网站精品网站设计
  • windows电脑如何执行openssl rand命令
  • 【MySQL✨】MySQL 入门之旅 · 第十一篇:常见错误排查与解决方案
  • Word表格数据提取工具
  • 【Rust GUI开发入门】编写一个本地音乐播放器(1. 主要技术选型架构设计)
  • Rust 中的 static 和 const
  • Linux操作系统-进程(一)
  • 零基础学AI大模型之LangChain六大核心模块与大模型IO交互链路