WirePlumber bluetooth codec config

I updated to Fedora 35 yesterday. Before I cannot connect to my Bluetooth headset, but after the upgrade I can with the default WirePlumber+pipewire+bluez setup, which is great. However, the sound quality is really awful. I think it is because the mSBC codec is used instead of AAC, so I want to change it, but the three sources [1] [2] [3] I found all relate to the config file in /usr/share/pipewire/media-session.d, which is not present in the Fedora 35 installation since the old simple media session manager is replaced by WirePlumber. So where is the location of WirePlumber’s configuration file and how can I set the default Bluetooth codec for it? I’m sure that the headset can run AAC codec on other devices.

Update: I use the KDE spin and found that I can change the codec in the audio setting icon shown below, but the headset is identified as only HSP/HFP and does not support codec other than CVSD (which is worse) and mSBC. How can I make pipewire recognize more advanced audio profile of the headset?

In addition, previously in Fedora 34 I switched from pulseaudio to pipewire by manually removing pulseaudio and installing pipewire-pulseaudio instead of using dnf swap, which seem to also remove some packages that depends on pluseaudio, such as the bluedevil package for KDE bluetooth plugin. Can I found what other packages have been removed and get them back?

Update: from this post this seems to be a problem of bluez. Could anyone confirm it?

/usr/share/wireplumber if you want to change copy it to /etc/…

Take in consideration that when you check on Arch Forum that there are might differences in path names of config files ?!

Hello @ytliu ,
https://pipewire.pages.freedesktop.org/wireplumber/ is the place to read about WirePlumber, and https://docs.pipewire.org/ are the PipeWire docs. Happy reading!

Thanks for the reply! I’ve copied and tried to modify part of the config file (/etc/bluetooth/main.conf and /etc/wireplumber/bluetooth.lua.d/50-bluez-config.lua) according to this guide on ArchWiki, but pactl list still only list three HFP/HSP profiles, as shown below:

Card #67
	Name: bluez_card.D8_55_75_12_5F_EF
	Driver: module-bluez5-device.c
	Owner Module: n/a
	Properties:
		api.bluez5.address = "D8:55:75:12:5F:EF"
		api.bluez5.class = "0x240404"
		api.bluez5.connection = "disconnected"
		api.bluez5.device = ""
		api.bluez5.icon = "audio-headset"
		api.bluez5.path = "/org/bluez/hci0/dev_D8_55_75_12_5F_EF"
		bluez5.a2dp.aac.bitratemode = "2"
		bluez5.auto-connect = "[ hfp_hf hsp_hs a2dp_sink ]"
		device.alias = "Galaxy Buds (5FEF)"
		device.api = "bluez5"
		device.bus = "bluetooth"
		device.description = "Galaxy Buds (5FEF)"
		device.form_factor = "headset"
		device.name = "bluez_card.D8_55_75_12_5F_EF"
		device.product.id = "0xa011"
		device.profile = "a2dp-sink"
		device.string = "D8:55:75:12:5F:EF"
		device.vendor.id = "bluetooth:0075"
		media.class = "Audio/Device"
		factory.id = "14"
		client.id = "79"
		object.id = "67"
	Profiles:
		off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
		headset-head-unit: Headset Head Unit (HSP/HFP) (sinks: 1, sources: 1, priority: 0, available: yes)
		headset-head-unit-cvsd: Headset Head Unit (HSP/HFP, codec CVSD) (sinks: 1, sources: 1, priority: 0, available: yes)
		headset-head-unit-msbc: Headset Head Unit (HSP/HFP, codec mSBC) (sinks: 1, sources: 1, priority: 0, available: yes)
	Active Profile: headset-head-unit-msbc
	Ports:
		headset-input: Headset (type: Headset, priority: 0, latency offset: 0 usec, available)
			Properties:
				port.type = "headset"
			Part of profile(s): headset-head-unit, headset-head-unit-cvsd, headset-head-unit-msbc
		headset-output: Headset (type: Headset, priority: 0, latency offset: 0 usec, available)
			Properties:
				port.type = "headset"
			Part of profile(s): headset-head-unit, headset-head-unit-cvsd, headset-head-unit-msbc

Could you give more advice on which part of the configuration could be wrong and how I can fix it?

Wireplumber is the session manager for Pipewire. Wouldn’t you use bluetoothctl for your bluetooth devices?

Sure, but I think the settings for wireplumber contains the setting for bluez in terms of Bluetooth audio device related settings. My guess is that since this is related to the audio backend the settings cannot be directly applied to bluez. Can I set these audio settings otherwise by directly modifying bluez’s config file, and how can I do that?

I guess what I was getting at was that the physical device Pipewire uses, and hence WirePlumber manages, gets determined by the bluetooth driver? does it not? So as to what you would do WRT how you handled that device (ie how it becomes a source for a corresponding sink in pipewire) is done by wireplumber I would think so yes. The how is very likely in the documentation I pointed to in my previous comment. I don’t have any bluetooth audio devices to test with otherwise I would do so for you.

Update: I’ve tried the method in this GitHub issue of bluez and it works! I think the problem then is that the previous cache profile of my bluetooth headsets are from an older bluez install which is incorrect, and removing the cache and connecting again fix it. I tried deleting the device in GUI without deleting the /var/lib/bluetooth folder and that didn’t work out.

2 Likes

I did this:

  1. sudo rm -Rf /var/lib/bluetooth/*
  2. systemctl reboot
  3. After reboot, I paired again all my devices.

It seems to be working. But the same as before. The logs from journalctl -u bluetooth.service -b say:

-- Journal begins at Wed 2021-12-08 11:14:51 WET, ends at Thu 2021-12-23 07:59:13 WET. --
dic 23 07:57:57 yajolap systemd[1]: Starting Bluetooth service...
dic 23 07:57:57 yajolap bluetoothd[1054]: Bluetooth daemon 5.62
dic 23 07:57:57 yajolap bluetoothd[1054]: Starting SDP server
dic 23 07:57:57 yajolap systemd[1]: Started Bluetooth service.
dic 23 07:57:57 yajolap bluetoothd[1054]: Bluetooth management interface 1.21 initialized
dic 23 07:58:09 yajolap bluetoothd[1054]: Player registered: sender=:1.49 path=/media_player0
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSource/ldac
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSource/aac
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSink/sbc
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSource/sbc
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSink/sbc_xq
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSource/sbc_xq
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSource/faststream
dic 23 07:58:09 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.49 path=/MediaEndpoint/A2DPSource/faststream_duplex
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSource/ldac
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSource/aac
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSink/sbc
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSource/sbc
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSink/sbc_xq
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSource/sbc_xq
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSource/faststream
dic 23 07:58:13 yajolap bluetoothd[1054]: Endpoint unregistered: sender=:1.49 path=/MediaEndpoint/A2DPSource/faststream_duplex
dic 23 07:58:13 yajolap bluetoothd[1054]: Player unregistered: sender=:1.49 path=/media_player0
dic 23 07:58:15 yajolap bluetoothd[1054]: Player registered: sender=:1.84 path=/media_player0
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSource/ldac
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSource/aac
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSink/sbc
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSource/sbc
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSink/sbc_xq
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSource/sbc_xq
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSource/faststream
dic 23 07:58:15 yajolap bluetoothd[1054]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSource/faststream_duplex
dic 23 07:58:30 yajolap bluetoothd[1054]: src/device.c:load_gatt_db() No cache for EB:D0:F5:C1:43:90
dic 23 07:58:32 yajolap bluetoothd[1054]: profiles/input/hog-lib.c:report_value_cb() bt_uhid_send: Invalid argument (22)
dic 23 07:58:32 yajolap bluetoothd[1054]: profiles/input/hog-lib.c:report_value_cb() bt_uhid_send: Invalid argument (22)
dic 23 07:58:32 yajolap bluetoothd[1054]: profiles/input/hog-lib.c:report_value_cb() bt_uhid_send: Invalid argument (22)
dic 23 07:58:40 yajolap bluetoothd[1054]: src/device.c:load_gatt_db() No cache for E4:D5:20:0C:91:07
dic 23 07:58:47 yajolap bluetoothd[1054]: profiles/input/hog-lib.c:report_value_cb() bt_uhid_send: Invalid argument (22)
dic 23 07:58:47 yajolap bluetoothd[1054]: profiles/input/hog-lib.c:report_value_cb() bt_uhid_send: Invalid argument (22)
dic 23 07:58:47 yajolap bluetoothd[1054]: profiles/input/hog-lib.c:report_value_cb() bt_uhid_send: Invalid argument (22)
dic 23 07:59:02 yajolap bluetoothd[1054]: profiles/audio/avdtp.c:cancel_request() Open: Operation canceled (125)
dic 23 07:59:02 yajolap bluetoothd[1054]: profiles/audio/avdtp.c:session_cb() Transaction label doesn't match

So, that makes me think that my headset (Jabra Elite 45h) supports AAC, but still I cannot choose it. Maybe I’m missing some codec or other stuff? Or maybe AAC is just not supported by the headset?

Right now I only have SBC and SBC-XQ modes when in A2DP. Fedora 35 Silverblue here, fresh install.

AAC available on RPMFussion Non-free. If you already installed RPMFussion, from Gnome Software on the bottom window, there’re codec catagery that have GStreamer Multimedia Codecs - Non Free packages (Multimedia playback for Bluray, DTS, MMS, MP3, MPEG-2 AAC, MPEG-4, Mimic and Siren).

It seems like those plugins are no longer available in rpmfusion :confused:

Well, nevermind. I activated UnitedRPMs and installed all possible gstreamer1-plugin packages, including bad-nonfree which should contain the AAC stuff.

Then I just repeated previous steps and the headphones still display the same profiles. So, it seems that after all they don’t support AAC… :man_shrugging:

Just to make sure. You also need to run sudo dnf group update core (on the very bottom of the docs) to make RPM Fussion list apps available in Gnome Software.

Please don’t activate unitrpms it’s a botched project. You will only broke your system

1 Like

AAC codec is provided by RPM Fusion, but wireplumber cannot make use of it.

You need to install a special package dedicated for pipewire.
dnf install pipewire-codec-aptx

I tested with pipewire-codec-aptx, both from rpmfusion and from unitedrpms. Still no luck :confused:

I find it confusing. Are we talking about AAC or APTX? Or are these the same thing? What’s the package name for AAC from RPMFusion?