侧边栏壁纸
博主头像
半生瓜のblog

THERE IS NO END.

  • 累计撰写 284 篇文章
  • 累计创建 30 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

【ALSA】播放器声卡设备打开失败问题,音频流播放问题分析

xuanxuan
2025-08-17 / 0 评论 / 0 点赞 / 1 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

播放器声卡设备绑定问题

背景: TTS引擎合成的PCM音频流,送给播放器,到指定声卡完成音频播放;

原本使用GStreamer + alsasink插件,输出到alsa的指定声卡设备中

const std::string pipeline_desc =
    "appsrc name=mysrc ! "        // 从应用层推送音频数据的源
    "audioconvert ! "             // 转换音频格式(采样位宽、通道数等)
    "audioresample ! "            // 重采样(调整采样率)
    "alsasink device=my_audio_device ";  // 用 ALSA 输出到指定设备

最开始,这里指定的device是default,导致输出到了hw:0,0,0号声卡的第0个设备,对应UI上多媒体的音量控制。

问题: 绑定的音频设备有问题,导致多媒体播放 + 唤醒卡顿,唤醒&交互音量忽大忽小,还有在连接蓝牙的情况下,TTS播报会非常卡顿

推测是由于多路音频输入同一个设备,造成的音频竞争。

解决过程: 查看设备->研究GStreamer问题->转换到直接调ALSA API 重构播放器

检查设备绑定问题

  • 使用命令行测试,UI上的语音服务音量调节按钮,具体控制的是哪个声卡设备,以此确定了到底应该将音频流输出到哪个声卡设备。
# hw0,5 或者 my_audio_device 这个自定义的音频设备
aplay -D hw:0,5 test.wav
# 以及检测Mixer空间状态变化
alsactl monitor

同时,并没有发现自定义声卡名字的配置,可能客户给出的设备名,是定义在系统底层硬件上的。

/etc/asound.conf
or
~/.asoundrc

并且检查混音器 TTS_MIXER 的相关信息。

sh-4.4# amixer -c 0 scontents | grep -A 5 TTS_MIXER Simple mixer control 'TTS_MIXER',0 Capabilities: volume volume-joined Playback channels: Mono Capture channels: Mono Limits: 0 - 131072 Mono: 58894 [45%]
  • Mixer(混音器)是 ALSA 中负责 音量控制信号路由管理 的一部分。

简单来说,ALSA Mixer 就是管理和控制音频设备音量、静音、声道平衡等参数的组件。

检查音频设备的权限

# p->playback播放
# c->capture捕获
xuan@xuan:~$ ls -l /proc/asound/card0/

发现权限是够得,并没有问题。

检查SDS服务,在尝试播音频的时候,操作的声卡设备文件

lsof -p <pid> | grep pcm

发现,打开的是pcm0p,并不是pcm5p,所以还是得看,为什么代码中GStreamer打开的不对。

提高GStreamer日志等级,命令行启动服务,检查初始化日志

LOG                     alsa gstalsasink.c:1326:gst_alsasink_open:<alsasink0> Opened device plughw:0,5

DEBUG                   alsa gstalsa.c:470:gst_alsa_open_iec958_pcm:<alsasink0> Generated device string "plughw:0,5:{AES0 0x02 AES1 0x82 AES2 0x00 AES3 0x02}"
WARN                    alsa conf.c:5453:parse_args: alsalib error: Parameter DEV must be an integer
WARN                    alsa conf.c:5560:snd_config_expand: alsalib error: Parse arguments error: Invalid argument
WARN                    alsa pcm.c:2660:snd_pcm_open_noupdate: alsalib error: Unknown PCM plughw:0,5{xxx}
DEBUG                   alsa gstalsa.c:476:gst_alsa_open_iec958_pcm:<alsasink0> failed opening IEC958 device: Invalid argument

LOG                     alsa gstalsasink.c:1326:gst_alsasink_open:<alsasink0> Opened device multimedia_device

发现它尝试打开我们所指定的0,5设备了,然后尝试使用iec958解析,但是失败了,不过这里似乎并不影响后续流程,接着尝试打开multimedia_device设备,成功了,所以走了多媒体设备输出音频。

检查GStreamer1.12.4源码发现

gst_alsasink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
{
  GstAlsaSink *alsa;
  gint err;

  alsa = GST_ALSA_SINK (asink);

  if (alsa->iec958) {
    snd_pcm_close (alsa->handle);
    alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa), alsa->device);
    if (G_UNLIKELY (!alsa->handle)) {
      goto no_iec958;
    }
  }

  if (!alsasink_parse_spec (alsa, spec))
    goto spec_parse;
------
  if(alsa->channels > 2) {
	gst_alsasink_set_device(MULTIMEDIA2_DEVICE, alsa);
  }else {
	gst_alsasink_set_device(MULTIMEDIA_DEVICE, alsa);
  }
------

像是尝试IEC958打开失败后,走了fallback,一定会走到 gst_alsasink_set_device(MULTIMEDIA_DEVICE, alsa); ,打开multimedia设备。

解决方案

  • 尝试自定义设备名称——不可以,系统中不好添加新配置文件,而且这个方案似乎也会走到上述逻辑;
  • 修改GStreamer源码——不可以,同样改动很大;
  • 使用原生ALSA API重构播放器——可以,可控。
0

评论区