For many users, the issue is simply that Bluetooth audio devices have a software and hardware volume. Turning up the software volume makes the sound quality worse. Linux doesn't support changing Bluetooth hardware volume*.
Workarounds
As @BassGod and others also mentioned there are two workarounds to this:
- Have a physical method for adjusting the hardware volume on your Bluetooth audio device.
- Adjust the hardware volume while the device is connected to Android/iOS/Windows/macOS. Then connect the device to your Linux.
Solutions
Just update
The best option is probably to update your OS (or more specifically pulseaudio), since according to some people this issue got resolved in pulseaudio version 15.
Control it via dbus
(Modified from @LiamDennehy and @Sean Normandy)
- Find the DBus object that allows control of the headset's internal volume:
$ dbus-send --system --print-reply --dest=org.bluez / org.freedesktop.DBus.ObjectManager.GetManagedObjects | less
- While it is piped to less, search for the interface
org.bluez.MediaTransport1
(press slash /, type MediaControl1
, press Enter) and record the value of the object path
of the parent of the search result:
dict entry(
object path "/org/bluez/hci0/dev_C8_B2_58_35_64_6F"
array [
dict entry(
string "org.freedesktop.DBus.Introspectable"
array [
]
)
- Send volume up or volume down requests to it with these commands:
dbus-send --print-reply --system --dest=org.bluez /org/bluez/hci0/dev_C8_B2_58_35_64_6F org.bluez.Control.VolumeUp
dbus-send --print-reply --system --dest=org.bluez /org/bluez/hci0/dev_C8_B2_58_35_64_6F org.bluez.Control.VolumeDown
- Now you can map these commands to hotkeys via your desktop environment or make them accessible some other way.
Use some script
(Modified from @Sam Mason)
It works for any connected Bluetooth audio device - you don't need to manually find the mac address like in the previous example.
#!/usr/bin/python3
from pulsectl import Pulse
import subprocess
import sys
# Prerequisite tasks on ubuntu machine:
# sudo apt install python3-pip
# pip install pulsectl
method = 'org.bluez.MediaControl1.Volume{}'.format(
'Down' if sys.argv[1] == 'down' else 'Up')
with Pulse() as pulse:
for sink in pulse.sink_list():
bluez_path = sink.proplist.get('bluez.path')
if bluez_path:
args = [
'dbus-send', '--system', '--print-reply',
'--dest=org.bluez', bluez_path, method,
]
subprocess.run(args, check=True)
Then I made the file executable and mapped some hotkeys to run this script:
/home/me/scripts/bt_volume.py up
/home/me/scripts/bt_volume.py down