结合 DeepSeek 生成的脚本,自己做了一些改动和错误修正:
#!/bin/bash
# 蓝牙音频优化脚本 v2025.6
# 功能:自动切换蓝牙设备到高质量音频模式(A2DP Sink),按配置文件给出的优先级来激活
# 初始化设置
DEBUG_MODE=false
LOG_FILE="/tmp/bluetooth_audio_optimizer.log"
export LC_ALL=C
# 设置正确的环境变量
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
# 等待 PulseAudio/Pipewire 服务启动
MAX_ATTEMPTS=10
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
if pactl info &>/dev/null; then
break
fi
sleep 1
ATTEMPT=$((ATTEMPT+1))
done
if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then
echo "$(date) - 错误:无法连接到 PulseAudio/Pipewire 服务" >&2
exit 1
fi
# 记录日志函数
log() {
local msg="$1"
if $DEBUG_MODE; then
echo -e "$(date +'%F %T'): $msg" | tee -a "$LOG_FILE"
else
echo -e "$msg"
fi
}
# === 核心功能:语言无关的设备识别 ===
# 获取蓝牙MAC地址(完全语言无关)
get_bt_mac() {
pactl list sinks | grep -m1 -oP 'api\.bluez5\.address\s*=\s*"\K([0-9A-F:]{17})'
}
# 获取蓝牙卡路径(兼容所有语言环境)
get_bt_card_path() {
local mac
mac=$(pactl list sinks | grep -m1 -oP 'api\.bluez5\.address\s*=\s*"\K([0-9A-F:]{17})')
[ -n "$mac" ] && echo "bluez_card.${mac//:/_}"
}
# === A2DP/LDAC状态检测 ===
# 检测当前配置文件
get_active_profile() {
local card_path="$1"
pactl list cards | awk -v card="$card_path" '
$0 ~ " " card {
active = 0
while (getline) {
if (/Active Profile:/) {
print $3
exit
}
if (/^$/ || /^Card/) break
}
}
'
}
# 检测当前编码器
get_active_codec() {
pactl list sinks | awk '
/api\.bluez5\.codec = "/ {
match($0, /"([^"]+)"/, a);
if (a[1] != "") print a[1]
}' | head -1
}
# 检测支持的编码列表
get_supported_codecs() {
local card_path="$1"
pactl list cards | grep -A50 " $card_path" |
grep -oP 'bluez5\.codecs = \[\K[^\]]+' |
tr -d '"' | tr ',' '\n' | sed 's/^ //'
}
# === A2DP模式切换(兼容多Profile)===
switch_to_a2dp() {
local card_path="$1"
declare -a profile_entries
local profile_name="" priority=""
declare -i -x retval=1
log "检测可用的A2DP配置并准备按优先级排序..."
# 解析所有可用A2DP配置
pactl list cards | awk -v card="$card_path" '
$0 ~ " " card {
in_card = 1
next
}
in_card && /Profiles:/ {
in_profiles = 1
next
}
in_profiles && /^$/ {
exit # 遇到空行结束解析
}
in_profiles && /available:[[:space:]]*yes/ && /a2dp-sink/ {
# 提取配置名
profile_name = $0
sub(/:.*/, "", profile_name)
gsub(/^[[:space:]]+/, "", profile_name)
# 提取优先级
match($0, /priority:[[:space:]]*([0-9]+)/, m)
priority = m[1]
if (priority == "") priority = 0 # 缺省值
printf "%d:%s\n", priority, profile_name
}
' | sort -t: -k1,1nr | while IFS=: read -r priority profile; do
# 记录发现的配置
# profile_entries+=("$priority:$profile")
if [[ "$retval" == "1" ]]; then
log "发现高优先级配置 [优先级:${priority}]: ${profile}"
if pactl set-card-profile "$card_path" "$profile" 2>/dev/null; then
sleep 0.5 # 等待协议生效
log "✓ 成功激活配置: ${profile}"
# 验证配置激活
local active_profile
active_profile=$(get_active_profile "$card_path")
if [[ "$active_profile" == "$profile" ]]; then
log "✓ 配置状态已确认"
retval=0
else
log "⚠️ 配置激活但状态不匹配,实际配置: ${active_profile}"
fi
else
log "⚠️ 配置激活失败: ${profile}"
fi
fi
done
# 所有配置尝试失败
current_profile=$(get_active_profile "$card_path")
if [[ ! "$current_profile" == *"a2dp-sink"* ]]; then
log "${RED}错误:所有可用A2DP配置尝试均失败${NC}"
log "请检查设备兼容性:pactl list cards | grep -A30 ' $card_path'"
return 1
fi
return 0
}
# === 设备重连辅助函数 ===
reconnect_bluetooth_device() {
local mac="$1"
log "重置蓝牙连接..."
(
echo "disconnect $mac"
sleep 3
echo "connect $mac"
sleep 5
echo "quit"
) | bluetoothctl > /dev/null 2>&1
log "设备重连完成"
}
# === 主控制流程 ===
main() {
log "${BLUE}=== $(date -Iseconds) 蓝牙音频优化开始 ==="
# 获取设备信息
local bt_mac
bt_mac=$(get_bt_mac)
if [ -z "$bt_mac" ]; then
log "${RED}错误:未检测到已连接的蓝牙耳机"
return 1
fi
log "设备MAC地址: $bt_mac"
local card_path
card_path=$(get_bt_card_path "$bt_mac")
if [ -z "$card_path" ]; then
log "${RED}错误:无法识别蓝牙设备路径"
return 1
fi
log "设备路径: $card_path"
# 检查当前配置
local current_profile
current_profile=$(get_active_profile "$card_path")
local current_codec
current_codec=$(get_active_codec "$card_path")
log "当前配置: ${current_profile:-未知} | 编码: ${current_codec:-未知}"
# 自动切换到高质量模式
if [[ ! "$current_profile" == *"a2dp-sink"* ]]; then
log "正在切换到高质量音频模式..."
if ! switch_to_a2dp "$card_path"; then
log "${YELLOW}配置切换失败,尝试设备重连..."
reconnect_bluetooth_device "$bt_mac"
sleep 3
switch_to_a2dp "$card_path" || {
log "${RED}错误:无法切换到A2DP模式"
return 1
}
fi
sleep 2 # 等待配置稳定
log "${GREEN}✓ 已启用高质量音频配置"
else
log "${GREEN}✓ 已在高质量音频模式"
fi
log "${BLUE}=== 优化完成 ==="
}
# === 颜色定义 ===
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 执行主函数
if [ "$1" = "--debug" ]; then
DEBUG_MODE=true
fi
main
后续步骤:
- 保存脚本,然后就是加执行权限和目录的写入权限。
- 执行 crontab -e 将脚本写入到计划任务里,每分钟检查一次。
* * * * * /opt/ldac/ldac.sh > /opt/ldac/ldac.log 2>&1
