ubuntu18.04 PulseAudio蓝牙耳机开启mic的解决办法
Posted samxfb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ubuntu18.04 PulseAudio蓝牙耳机开启mic的解决办法相关的知识,希望对你有一定的参考价值。
一、背景
- 基于Linux音频服务子系统PulseAudio(Linux默认声音服务器)进行音频开发,包括采集(record)和播放(playback);
- 测试中发现笔记本(ubuntu 18.04)连接蓝牙后无法读取record设备,只能识别到playback设备,经过一番折腾,发现native PulseAudio不支持HSP/HFP, 连接蓝牙耳机后,输入指令
pactl list cards
查看声卡信息:
查看蓝牙耳机声卡Profiles:
Profiles:
off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
a2dp-sink: High Fidelity Playback (A2DP Sink) (sinks: 1, sources: 0, priority: 0, available: yes)
headset-head-unit: Headset Head Unit (HSP/HFP) (sinks: 1, sources: 1, priority: 0, available: no)
可以看出此时默认只支持A2DP协议,不支持HSP/HFP,解释如下:
a2dp-sink: High Fidelity Playback (A2DP Sink) (sinks: 1, sources: 0, priority: 0, available: yes)
A2DP是单向的,只支持播放(sink),不支持录制(source);headset-head-unit: Headset Head Unit (HSP/HFP) (sinks: 1, sources: 1, priority: 0, available: no)
HSP/HFP是双向的,同时支持播放(sink)和录制(source);
结论:当前系统环境下无法支持蓝牙耳机录制,就算从PulseAudio Volume Control工具下切换Configuration也是毫无意义的。
二、解决方案
查阅资料发现,可以通过安装pipewire(参考
PipeWire: The Linux audio/video bus)让PulseAudio工作在pipewire上。
详细操作可以参考How to Enable PipeWire Audio Service to Replace PulseAudio in Ubuntu 21.10 & 21.04
步骤如下:
1. 通过ppa安装pipewire
sudo add-apt-repository ppa:pipewire-debian/pipewire-upstream
sudo apt install pipewire
sudo apt install libspa-0.2-bluetooth
2. 重启系统
3. 验证pipewire是否正常安装
pactl info
sam@sam-ThinkPad-Edge-E440:~$ pactl info
Server String: /run/user/1000/pulse/native
Library Protocol Version: 32
Server Protocol Version: 35
Is Local: yes
Client Index: 74
Tile Size: 65472
User Name: sam
Host Name: sam-ThinkPad-Edge-E440
Server Name: PulseAudio (on PipeWire 0.3.39)
Server Version: 15.0.0
Default Sample Specification: float32le 2ch 48000Hz
Default Channel Map: front-left,front-right
Default Sink: alsa_output.pci-0000_00_1b.0.analog-stereo
Default Source: alsa_input.pci-0000_00_1b.0.analog-stereo
Cookie: 2c95:ace7
查看Server Name出现PipeWire说明安装完成
Server Name: PulseAudio (on PipeWire 0.3.39)
4. 查看声卡Profiles
pactl list cards
Profiles:
off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
a2dp-sink: High Fidelity Playback (A2DP Sink) (sinks: 1, sources: 0, priority: 0, available: yes)
headset-head-unit: Headset Head Unit (HSP/HFP) (sinks: 1, sources: 1, priority: 0, available: yes)
a2dp-sink-sbc: High Fidelity Playback (A2DP Sink, codec SBC) (sinks: 1, sources: 0, priority: 0, available: yes)
headset-head-unit-cvsd: Headset Head Unit (HSP/HFP, codec CVSD) (sinks: 1, sources: 1, priority: 0, available: yes)
现在看到A2DP和HSP/HFP都支持了,现在移步到系统Settings或使用PulseAudio Volume Control工具去配置蓝牙耳机的profile为HSP/HFP,即可使用蓝牙耳机的mic功能。
蓝牙连接失败,使用 bluetoothctl 命令
【中文标题】蓝牙连接失败,使用 bluetoothctl 命令【英文标题】:bluetooth connection fail with bluetoothctl command 【发布时间】:2018-11-27 01:38:43 【问题描述】:我在Vmware环境下的Ubuntu下尝试了蓝牙连接测试。 Ubuntu 是 14.04 lts,蓝牙是 USB-dongle,BT 堆栈是 Bluez 5.35。 我不使用pulseaudio。
我使用 bluetoothctl 命令进行扫描、配对和连接。 但是连接失败。下面是bluetoothctl的日志
$ sudo bluetoothctl
[bluetooth]# power on
[bluetooth]# show
Controller 00:1A:7D:DA:xx:xx (public)
Name: ubuntu
Alias: ubuntu-0
Class: 0x00000000
Powered: yes
Discoverable: no
Pairable: yes
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
Modalias: usb:v1D6Bp0246d0532
Discovering: no
[bluetooth]# scan on // Wait until found BT headset
[bluetooth]# scan off
[bluetooth]# devices
Device 11:11:22:xx:xx:xx Test
Device 0C:E0:E4:xx:xx:xx PLT_Legend
[bluetooth]# pair 0C:E0:E4:xx:xx:xx // try pairing with 0C:E0:E4:xx:xx:xx
Attempting to pair with 0C:E0:E4:xx:xx:xx
[CHG] Device 0C:E0:E4:xx:xx:xx Connected: yes
[PLT_Legend]# interfaces_added
[CHG] Device 0C:E0:E4:xx:xx:xx Modalias: bluetooth:v0055p0113d0067
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 00001108-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 82972387-294e-4d62-97b5-2668aa35f618
[CHG] Device 0C:E0:E4:xx:xx:xx ServicesResolved: yes
[CHG] Device 0C:E0:E4:xx:xx:xx Paired: yes
Pairing successful
[CHG] Device 0C:E0:E4:xx:xx:xx ServicesResolved: no
[CHG] Device 0C:E0:E4:xx:xx:xx Connected: no
[PLT_Legend]# connect 0C:E0:E4:xx:xx:xx
Attempting to connect to 0C:E0:E4:xx:xx:xx
[CHG] Device 0C:E0:E4:xx:xx:xxConnected: yes
Failed to connect: org.bluez.Error.Failed
我发现上面的 bluez 没有 a2dp 配置文件。 实际上,bluez5.x 和pulseaudio 是紧密结合的。如果不使用 pulseaudio,用户必须添加额外的配置文件(a2dp 或 hspag)。
以下代码是添加 a2dpsink 、 a2dpsource 和 haspag 的示例。
#define A2DP_SOURCE_ENDPOINT "/MediaEndpoint/A2DPSource"
#define A2DP_SINK_ENDPOINT "/MediaEndpoint/A2DPSink"
#define HSP_AG_PROFILE "/Profile/HSPAGProfile"
#define PA_BLUETOOTH_UUID_HSP_AG "00001112-0000-1000-8000-00805f9b34fb"
#define PA_BLUETOOTH_UUID_A2DP_SOURCE "0000110a-0000-1000-8000-00805f9b34fb"
#define PA_BLUETOOTH_UUID_A2DP_SINK "0000110b-0000-1000-8000-00805f9b34fb"
static void register_profile_reply(DBusPendingCall *call, void *user_data)
//struct bluetooth_profile *profile = user_data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusError derr;
dbus_error_init(&derr);
if (!dbus_set_error_from_message(&derr, reply))
printf("Profile %s registered", (char *)user_data);
goto done;
//unregister_profile(profile);
printf("bluetooth: RequestProfile error: %s, %s", derr.name,
derr.message);
dbus_error_free(&derr);
done:
dbus_message_unref(reply);
static DBusConnection *connection;
void btd_profile_add_hspag(const char *profile, const char *uuid)
DBusMessage *msg;
DBusMessageIter iter, opt;
DBusPendingCall *call;
connection = btd_get_dbus_connection();
msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
"org.bluez.ProfileManager1",
"RegisterProfile");
if( msg == NULL )
printf("%s : msg is null \n", __func__);
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &profile);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uuid);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
DBUS_TYPE_STRING_AS_STRING
DBUS_TYPE_VARIANT_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
&opt);
dbus_message_iter_close_container(&iter, &opt);
if (!g_dbus_send_message_with_reply(connection, msg, &call, -1))
printf("%s:%s - fail g_dbus_send_message_with_reply() \n", __FILE__, __func__);
//unregister_profile(profile);
goto failed;
dbus_pending_call_set_notify(call, register_profile_reply, &profile,
NULL);
dbus_pending_call_unref(call);
failed:
dbus_message_unref(msg);
return;
void btd_profile_add(void)
btd_profile_add_hspag(HSP_AG_PROFILE, PA_BLUETOOTH_UUID_HSP_AG);
btd_profile_add_hspag(A2DP_SOURCE_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SOURCE);
btd_profile_add_hspag(A2DP_SINK_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SINK);
在那之后,bluez 有了 a2dp、hspag 配置文件,没有 pulseaudio。 我可以用 bluetoothctl 的“show”命令查看。
[bluetooth]# show
Controller 00:1A:7D:xx:xx:xx
Name: ubuntu
Alias: ubuntu-0
Class: 0x000000
Powered: yes
Discoverable: no
Pairable: yes
UUID: Headset AG (00001112-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb)
UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
Modalias: usb:v1D6Bp0246d0523
Discovering: no
即使添加了 a2dp 配置文件,蓝牙连接仍然失败。 通过btmon trace,断开了rfcomm的连接,接下来,l2cap的连接也断开了。 我不知道我错过了什么。 在没有pulseaudio的情况下运行bluez 5.35我还需要什么?
【问题讨论】:
【参考方案1】:日志显示您的“PLT_Legend”设备支持 A2DP SINK 角色,因此您的 Ubuntu 应充当 A2DP SOURCE 角色。要使其工作,您需要一个工作配置文件实现。
您可能不需要完全实现 A2DP 源配置文件来获取音频数据,但至少您需要注册基本功能才能让 bluetoothd 满意。
下图直接复制自here。
在上面的序列中,您可以看到蓝牙在连接具有 A2DP 功能的新设备时调用“SelectConfiguration”和“SetConfiguration”。
正如您所观察到的,连接状态最初移动到已连接,然后回退到“否”。这是因为,bluetoothd 在获得低级连接后会尝试与配置文件(SDP 服务发现协议)进行连接。低级连接成功后,设备被标记为已连接,SDP 继续进行。
在 SDP 期间,bluetoothd 尝试获取您的设备(在本例中为 ubuntu)的功能,并使用“SelectConfiguration”与终端设备 (PLT_Legend) 就编解码器支持进行协商,并使用“SetConfiguration”选择一个。握手成功后,蓝牙标记 A2DP 配置文件已连接。
因此,使用您的配置文件的虚拟注册,由于它找不到方法并且正确的编解码器返回,它标志着连接失败并终止 Ubuntu 和设备之间的连接。
如果您不想使用 pulseaudio,可以尝试使用 bluez-alsa https://github.com/Arkq/bluez-alsa 并开始收听 A2DP 配置文件。我认为这个包已经在 ubuntu repo 中可用了,你可以试试
sudo apt-get install bluez-alsa
AFAIK,pulseaudio 没有与蓝牙紧密绑定,你仍然可以以蓝牙理解的方式实现自己的 A2DP 实现。
注意,bluez-alsa 使用开源 fdk-aac 进行 AAC 编码和解码。
【讨论】:
以上是关于ubuntu18.04 PulseAudio蓝牙耳机开启mic的解决办法的主要内容,如果未能解决你的问题,请参考以下文章