Linux で AirPods を使うと音量を最大にしても音が小さすぎます。
これは AirPods などの比較的新しい Bluetooth ヘッドセットの音量は AVRCP の Absolute Volume
という仕組みを使って調節しなければならないのが、Linux 側のサウンドサーバーがそれに対応していないことによるものです。
コマンドラインから AVRCP で音量を調節するスクリプト
bluetoothd
のオプションに --noplugin=avrcp
を指定して AVRCP を無効にしてしまうという手 (bluetooth - Extremely low volume with AirPods (Ubuntu 19.10) - Ask Ubuntu) もありますが、 AirPods の場合バッテリーが減ってきた際の通知音がめちゃくちゃでかい音で鳴ったり、ダブルタップが効かなくなったりして不便です。
そこで AVRCP を使って音量を調節する簡単な Python スクリプトを作りました。
AirPods 以外の Bluetooth ヘッドセットでも使用できます。
#!/usr/bin/env python3
import dbus
import sys
DBUS_OM_IFACE = 'org.freedesktop.DBus.ObjectManager'
DBUS_PROP_IFACE = 'org.freedesktop.DBus.Properties'
BLUEZ_SERVICE_NAME = 'org.bluez'
BLUEZ_MT_IFACE = 'org.bluez.MediaTransport1'
VOL_STEP = 5
def usage():
print("""Usage:
{0} Show volume
{0} <value> Set volume to <value> (0-127)
{0} inc Increase volume
{0} dec Decrease volume""".format(sys.argv[0]), file=sys.stderr)
sys.exit(1)
def main():
if len(sys.argv) > 2:
usage()
bus = dbus.SystemBus()
om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'), DBUS_OM_IFACE)
objects = om.GetManagedObjects()
path = None
for obj, props in objects.items():
if BLUEZ_MT_IFACE in props.keys():
path = obj
break
if path is None:
print('No device exists', file=sys.stderr)
sys.exit(1)
vol_now = props[BLUEZ_MT_IFACE]['Volume']
if len(sys.argv) == 2:
if sys.argv[1] == 'inc':
vol = vol_now + VOL_STEP
elif sys.argv[1] == 'dec':
vol = vol_now - VOL_STEP
elif sys.argv[1].isdecimal():
vol = sys.argv[1]
else:
usage()
print('{} -> {}'.format(vol_now, vol))
obj = bus.get_object(BLUEZ_SERVICE_NAME, path)
props = dbus.Interface(obj, DBUS_PROP_IFACE)
props.Set(BLUEZ_MT_IFACE, 'Volume', dbus.types.UInt16(vol))
else:
print(vol_now)
if __name__ == '__main__':
main()
使い方
Bluetooth ヘッドセットを繋いだあと、予めシステムの音量を最大にしておきます。(音量はヘッドセット側で調節されるため)
現在の音量を表示する
$ ./vol.py
20
音量を設定する
0 から 127 までの値を指定できます。
$ ./vol.py 30
20 -> 30
音量を上げる
$ ./vol.py inc
30 -> 35
音量を下げる
$ ./vol.py dec
35 -> 30