Raspberry Pi4下Pydub通过subprocess调用时蓝牙音箱无声音问题
树莓派4 subprocess调用Pydub播放蓝牙音频无输出解决方案
故障根因
单独执行脚本时运行在你当前登录的普通用户会话下,PulseAudio音频服务默认将蓝牙音箱设为当前用户的默认输出设备;通过subprocess调用时,子进程如果没有继承当前用户的PulseAudio会话环境变量,会默认使用HDMI/3.5mm接口作为输出,音频没有路由到蓝牙音箱,因此不会报错但没有声音。
修复方案
方案1:subprocess调用时传入PulseAudio环境变量
调用子进程时主动复制当前用户的环境变量,补充PulseAudio运行路径配置:
import subprocess import os # 复制当前进程的环境变量 run_env = os.environ.copy() # 1000是树莓派默认普通用户pi的uid,如果你用其他用户,替换为对应用户的uid即可 run_env["PULSE_RUNTIME_PATH"] = "/run/user/1000/pulse/" run_env["XDG_RUNTIME_DIR"] = "/run/user/1000/" # 调用播放脚本 subprocess.run(["python3", "/path/to/your/play_script.py"], env=run_env)
方案2:修改播放逻辑,直接指定蓝牙音频输出设备
先执行aplay -L命令,找到蓝牙音箱对应的ALSA设备标识,格式一般为bluealsa:DEV=蓝牙MAC地址,PROFILE=a2dp,之后修改播放脚本,替换默认的play方法:
from pydub import AudioSegment import subprocess sound = AudioSegment.from_wav('mywavfile.wav') # 调用aplay直接指定蓝牙设备输出音频 p = subprocess.Popen( ["aplay", "-D", "你查到的蓝牙设备标识", "-f", "S16_LE", "-r", str(sound.frame_rate), "-c", str(sound.channels)], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) p.communicate(sound.raw_data)
方案3:父进程为systemd服务的额外配置
如果调用subprocess的父进程是systemd托管的服务,需要在service配置文件中增加用户和环境变量配置:
[Service] User=pi Group=pi Environment="PULSE_RUNTIME_PATH=/run/user/1000/pulse/" Environment="XDG_RUNTIME_DIR=/run/user/1000/" ExecStart=/usr/bin/python3 /path/to/your/parent_script.py
注意事项
- 不要使用root权限运行父进程,root默认无权限访问普通用户的PulseAudio会话
- 可以在播放脚本中临时增加
print(os.environ)的代码,对比直接运行和subprocess调用时的环境变量差异,定位缺失的配置项 - 如果Pydub默认用ffplay作为播放后端,也可以修改play方法的调用参数,给ffplay加上
-audio_device pulse的参数指定用PulseAudio输出
内容的提问来源于stack exchange,提问作者k3nz3n
相关产品推荐
相关产品推荐

