发表于 2026年08月13日
MPC手机dlan推流音乐到mpd恢复到当前播放记录
现在先别重启
把下面 4 个命令的结果给我:
ps -o pid,ppid,lstart,cmd -p 804
systemctl list-units --type=service --all | grep -Ei 'mpd|autostart'
grep -R "mpd" /etc/systemd/system /etc/rc.local /usr/local/bin 2>/dev/null | head -100
mpc status
killall -9 mpd
sudo -u mpd /usr/bin/mpd /etc/mpd.conf
现在先恢复 MPD,执行这几条
不要重启机器。
systemctl stop mpd-dlna-resume.service 2>/dev/null
systemctl disable mpd-dlna-resume.service 2>/dev/null
kill 804
sleep 2
systemctl reset-failed mpd.service
systemctl start mpd.service
sleep 3
systemctl status mpd --no-pager
mpc status
systemctl restart upmpdcli
mpd.service
↓
MPD :6600
↓
upmpdcli
↓
BubbleUPnP
ss -lntp | grep ':6600'
lsof -nP -iTCP:6600 -sTCP:LISTEN
ps aux | grep '[m]pd'
systemctl status mpd-manager.service --no-pager
马上执行:
systemctl reset-failed mpd.service
systemctl start mpd.service
systemctl status mpd --no-pager
第一步:启动 MPD
执行:
systemctl reset-failed mpd.service
systemctl start mpd.service
sleep 3
systemctl status mpd --no-pager
然后:
mpc status
- 替换 mpd-autostart.sh
直接执行:
cat > /usr/local/bin/mpd-autostart.sh <<'EOF'
#!/bin/bash
# ============================================================
# MPD 开机自动播放本地音乐
# 只负责开机播放一次
# 不参与 DLNA
# 不修改 /etc/mpd.conf
# ============================================================
export MPD_HOST="127.0.0.1"
export MPD_PORT="6600"
LOG="/var/log/mpd-autostart.log"
log() {
echo "$(date '+%F %T') $1" >> "$LOG"
}
mkdir -p /var/log/mpd
mkdir -p /run/mpd
mkdir -p /var/lib/mpd/playlists
mkdir -p /var/lib/mpd/cache
mkdir -p /var/lib/mpd/tag_cache
mkdir -p /media/music
chown -R mpd:audio \
/var/log/mpd \
/run/mpd \
/var/lib/mpd \
/media/music
chmod -R 775 \
/var/log/mpd \
/run/mpd \
/var/lib/mpd \
/media/music
log "MPD 开机自动播放启动"
# MPD 由 systemd 管理,这里只等待它启动
systemctl start mpd
# 等待 MPD 可连接
for i in $(seq 1 20); do
if mpc status >/dev/null 2>&1; then
break
fi
sleep 1
done
if ! mpc status >/dev/null 2>&1; then
log "MPD 无法连接,退出"
exit 0
fi
# 更新本地音乐库
mpc update >/dev/null 2>&1 || true
# 给数据库一点时间
sleep 3
# 如果 MPD 已经有队列,就不重新建立
COUNT=$(mpc playlist 2>/dev/null | wc -l)
if [ "$COUNT" -gt 0 ]; then
log "已有队列 ${COUNT} 首,不重新建立"
else
# 没有队列才建立本地音乐队列
mpc listall 2>/dev/null | mpc add >/dev/null 2>&1 || true
COUNT=$(mpc playlist 2>/dev/null | wc -l)
log "建立本地队列 ${COUNT} 首"
fi
# 播放设置
mpc repeat on >/dev/null 2>&1 || true
mpc random off >/dev/null 2>&1 || true
# 保持你原来的音量
mpc volume 100 >/dev/null 2>&1 || true
# 声卡音量
amixer sset Master 100% unmute 2>/dev/null || true
amixer sset PCM 100% unmute 2>/dev/null || true
amixer sset Line 100% unmute 2>/dev/null || true
# 有队列并且当前没有播放才开始
STATUS=$(mpc status 2>/dev/null)
if echo "$STATUS" | grep -q '\[playing\]'; then
log "MPD 已经在播放,不干预"
elif [ "$COUNT" -gt 0 ]; then
mpc play >/dev/null 2>&1 || true
log "开始播放本地音乐"
fi
log "MPD 开机自动播放完成"
exit 0
EOF
chmod +x /usr/local/bin/mpd-autostart.sh
这一份是重点。
#!/bin/bash
# ============================================================
# MPD + DLNA + YouTube 网络流恢复系统
#
# 功能:
#
# 1. 本地播放每5秒保存队列和进度
# 2. DLNA开始时绝不覆盖本地队列
# 3. DLNA结束后直接播放下一首
# 4. 切换过程中临时静音,防止旧歌曲/第一首窜声
# 5. 下一首从0:00开始
# 6. 最后一首自动循环第一首
# 7. 网络流卡死自动检测
# 8. MPD无响应自动重启
# 9. 网络流卡死后自动恢复本地队列
# 10. 恢复过程中禁止保存状态
#
# ============================================================
# ============================================================
# 路径
# ============================================================
STATE="/var/lib/mpd-dlna-resume"
QUEUE="$STATE/queue.txt"
INFO="$STATE/info.txt"
LOG="/var/log/mpd-dlna-resume.log"
mkdir -p "$STATE"
touch "$LOG"
# ============================================================
# MPD
# ============================================================
export MPD_HOST="127.0.0.1"
export MPD_PORT="6600"
# ============================================================
# 全局状态
# ============================================================
DLNA=0
RESTORING=0
FAILCOUNT=0
# ============================================================
# 网络流卡死检测
#
# 连续多少次播放位置没有变化
#
# 主循环5秒一次
#
# 6次 = 30秒
# ============================================================
STREAM_STUCK_COUNT=0
STREAM_LAST_POSITION=""
STREAM_LAST_URI=""
STREAM_STUCK_LIMIT=6
# ============================================================
# 日志
# ============================================================
log() {
echo "$(date '+%F %T') $*" >> "$LOG"
}
# ============================================================
# MPD 是否正常
# ============================================================
mpc_ok() {
timeout 3 mpc status >/dev/null 2>&1
}
# ============================================================
# 获取当前URI
# ============================================================
get_uri() {
timeout 3 mpc -f "%file%" current 2>/dev/null
}
# ============================================================
# 获取当前歌曲序号
# ============================================================
get_current() {
timeout 3 mpc status 2>/dev/null |
grep -oE '#[0-9]+/' |
head -1 |
tr -dc '0-9'
}
# ============================================================
# 获取当前播放时间
# ============================================================
get_position() {
timeout 3 mpc status 2>/dev/null |
grep -oE '[0-9]+:[0-9]+/' |
head -1 |
cut -d/ -f1
}
# ============================================================
# 获取MPD播放状态
#
# 返回:
#
# playing
# paused
# stopped
# ============================================================
get_state() {
timeout 3 mpc status 2>/dev/null |
grep -oE '\[(playing|paused|stopped)\]' |
head -1 |
tr -d '[]'
}
# ============================================================
# 判断网络流 / DLNA
# ============================================================
is_network_stream() {
echo "$1" |
grep -qiE \
'^(http|https|rtsp|rtmp|mms|ffmpegpcmdecode|stream)'
}
# ============================================================
# 获取当前音量
# ============================================================
get_volume() {
timeout 3 mpc volume 2>/dev/null |
grep -oE '[0-9]+%' |
head -1 |
tr -dc '0-9'
}
# ============================================================
# 安全等待MPD
# ============================================================
wait_mpd() {
for i in $(seq 1 15)
do
if mpc_ok; then
return 0
fi
sleep 1
done
return 1
}
# ============================================================
# 保存本地状态
#
# 注意:
#
# DLNA:
# 不保存
#
# 恢复:
# 不保存
# ============================================================
save_local_state() {
# --------------------------------------------------------
# 恢复期间禁止保存
# --------------------------------------------------------
if [ "$RESTORING" = "1" ]; then
return 1
fi
# --------------------------------------------------------
# MPD必须正常
# --------------------------------------------------------
if ! mpc_ok; then
return 1
fi
# --------------------------------------------------------
# 获取当前URI
# --------------------------------------------------------
URI=$(get_uri)
# --------------------------------------------------------
# 网络流绝对不保存
# --------------------------------------------------------
if is_network_stream "$URI"; then
return 1
fi
# --------------------------------------------------------
# 队列数量
# --------------------------------------------------------
COUNT=$(timeout 5 mpc playlist 2>/dev/null | wc -l)
if [ "$COUNT" -lt 2 ]; then
return 1
fi
# --------------------------------------------------------
# 当前歌曲
# --------------------------------------------------------
CURRENT=$(get_current)
# --------------------------------------------------------
# 当前播放位置
# --------------------------------------------------------
POSITION=$(get_position)
FILE="$URI"
[ -z "$CURRENT" ] && CURRENT=1
[ -z "$POSITION" ] && POSITION="0:00"
# ========================================================
# 保存完整队列
# ========================================================
timeout 10 \
mpc -f "%file%" playlist \
> "$QUEUE.tmp" 2>/dev/null
if [ ! -s "$QUEUE.tmp" ]; then
rm -f "$QUEUE.tmp"
return 1
fi
# --------------------------------------------------------
# 第一首不能是网络流
# --------------------------------------------------------
FIRST=$(head -1 "$QUEUE.tmp")
if is_network_stream "$FIRST"; then
rm -f "$QUEUE.tmp"
return 1
fi
# --------------------------------------------------------
# 原子替换
# --------------------------------------------------------
mv "$QUEUE.tmp" "$QUEUE"
# ========================================================
# 保存信息
# ========================================================
cat > "$INFO.tmp" <<EOT
COUNT=$COUNT
CURRENT=$CURRENT
POSITION=$POSITION
FILE=$FILE
EOT
mv "$INFO.tmp" "$INFO"
log "保存本地队列:${COUNT}首 / 第${CURRENT}首 / ${POSITION}"
return 0
}
# ============================================================
# 恢复本地队列
#
# MODE:
#
# normal
# 开机恢复原来的歌曲和位置
#
# next
# DLNA结束
# 直接下一首
#
# ============================================================
restore_local_state() {
MODE="$1"
# ========================================================
# 开启恢复保护
# ========================================================
RESTORING=1
log "开始进入恢复保护模式"
# ========================================================
# 检查队列
# ========================================================
if [ ! -s "$QUEUE" ]; then
log "没有保存的本地队列"
RESTORING=0
return 1
fi
if [ ! -s "$INFO" ]; then
log "没有保存的播放状态"
RESTORING=0
return 1
fi
# ========================================================
# 读取状态
# ========================================================
source "$INFO"
log "准备恢复:${COUNT}首 / 第${CURRENT}首 / ${POSITION}"
# ========================================================
# 等待MPD
# ========================================================
if ! wait_mpd; then
log "MPD等待失败"
RESTORING=0
return 1
fi
# ========================================================
# 保存当前音量
# ========================================================
OLD_VOLUME=$(get_volume)
if [ -z "$OLD_VOLUME" ]; then
OLD_VOLUME=100
fi
log "保存当前音量:${OLD_VOLUME}%"
# ========================================================
# ★★★ 恢复期间静音 ★★★
#
# 防止mpc play瞬间播放第一首
# ========================================================
timeout 5 mpc volume 0 >/dev/null 2>&1 || true
# ========================================================
# 停止当前播放
# ========================================================
timeout 5 mpc stop >/dev/null 2>&1 || true
sleep 0.1
# ========================================================
# 清除当前DLNA队列
# ========================================================
timeout 5 mpc clear >/dev/null 2>&1 || true
sleep 0.1
# ========================================================
# 重新加入本地队列
# ========================================================
ADDED=0
while IFS= read -r FILE
do
[ -z "$FILE" ] && continue
timeout 5 \
mpc add "$FILE" \
>/dev/null 2>&1
if [ $? -eq 0 ]; then
ADDED=$((ADDED + 1))
fi
done < "$QUEUE"
log "重新加入队列:${ADDED}/${COUNT}首"
# ========================================================
# 恢复失败
# ========================================================
if [ "$ADDED" -lt 1 ]; then
log "恢复队列失败"
timeout 5 \
mpc volume "$OLD_VOLUME" \
>/dev/null 2>&1 || true
RESTORING=0
return 1
fi
# ========================================================
# 修正CURRENT
# ========================================================
if [ -z "$CURRENT" ]; then
CURRENT=1
fi
if [ "$CURRENT" -lt 1 ]; then
CURRENT=1
fi
if [ "$CURRENT" -gt "$ADDED" ]; then
CURRENT=1
POSITION="0:00"
log "原歌曲序号超出当前队列,改为第1首"
fi
# ========================================================
# ★★★ DLNA结束 → 下一首 ★★★
# ========================================================
if [ "$MODE" = "next" ]; then
NEXT=$((CURRENT + 1))
# ----------------------------------------------------
# 最后一首 → 第一首
# ----------------------------------------------------
if [ "$NEXT" -gt "$ADDED" ]; then
NEXT=1
log "DLNA结束:原来是最后一首,循环到第1首"
else
log "DLNA结束:从第${CURRENT}首切换到下一首第${NEXT}首"
fi
CURRENT="$NEXT"
POSITION="0:00"
# ====================================================
# ★★★ 静音状态下选择歌曲
# ====================================================
timeout 5 \
mpc play "$CURRENT" \
>/dev/null 2>&1 || true
sleep 0.05
# ----------------------------------------------------
# 暂停
# ----------------------------------------------------
timeout 5 \
mpc pause \
>/dev/null 2>&1 || true
sleep 0.05
# ----------------------------------------------------
# 定位0秒
# ----------------------------------------------------
timeout 5 \
mpc seek 0 \
>/dev/null 2>&1 || true
sleep 0.05
# ====================================================
# 确认当前歌曲
# ====================================================
CHECK_CURRENT=$(get_current)
if [ "$CHECK_CURRENT" != "$CURRENT" ]; then
log "警告:当前第${CHECK_CURRENT}首,期望第${CURRENT}首"
else
log "已锁定下一首:第${CURRENT}首 / 0:00"
fi
# ====================================================
# 恢复音量
# ====================================================
timeout 5 \
mpc volume "$OLD_VOLUME" \
>/dev/null 2>&1 || true
sleep 0.05
# ====================================================
# 最后开始播放
# ====================================================
timeout 5 \
mpc play \
>/dev/null 2>&1 || true
log "DLNA恢复完成:${ADDED}首 / 第${CURRENT}首 / 0:00 / 音量${OLD_VOLUME}%"
RESTORING=0
return 0
fi
# ========================================================
# ★★★ 普通开机恢复 ★★★
# ========================================================
log "普通恢复:第${CURRENT}首 / ${POSITION}"
# --------------------------------------------------------
# 选择歌曲
# --------------------------------------------------------
timeout 5 \
mpc play "$CURRENT" \
>/dev/null 2>&1 || true
sleep 0.05
# --------------------------------------------------------
# 暂停
# --------------------------------------------------------
timeout 5 \
mpc pause \
>/dev/null 2>&1 || true
sleep 0.05
# --------------------------------------------------------
# 恢复进度
# --------------------------------------------------------
if [ -n "$POSITION" ] && [ "$POSITION" != "0:00" ]; then
timeout 5 \
mpc seek "$POSITION" \
>/dev/null 2>&1 || true
log "定位到第${CURRENT}首 / ${POSITION}"
else
timeout 5 \
mpc seek 0 \
>/dev/null 2>&1 || true
log "从第${CURRENT}首 / 0:00开始"
fi
sleep 0.05
# --------------------------------------------------------
# 恢复音量
# --------------------------------------------------------
timeout 5 \
mpc volume "$OLD_VOLUME" \
>/dev/null 2>&1 || true
sleep 0.05
# --------------------------------------------------------
# 开始播放
# --------------------------------------------------------
timeout 5 \
mpc play \
>/dev/null 2>&1 || true
log "普通恢复完成:${ADDED}首 / 第${CURRENT}首 / ${POSITION} / 音量${OLD_VOLUME}%"
RESTORING=0
return 0
}
# ============================================================
# MPD进程健康检查
# ============================================================
check_mpd() {
if mpc_ok; then
FAILCOUNT=0
return 0
fi
FAILCOUNT=$((FAILCOUNT + 1))
log "MPD无响应 ${FAILCOUNT}/3"
if [ "$FAILCOUNT" -ge 3 ]; then
log "MPD确认无响应,尝试重启"
systemctl restart mpd
sleep 3
FAILCOUNT=0
if mpc_ok; then
log "MPD已恢复"
else
log "MPD恢复失败"
fi
fi
}
# ============================================================
# 网络流卡死检测
#
# 只检测:
#
# 网络流
# +
# playing
# +
# 播放位置长时间不变化
#
# 不检测:
#
# 本地音乐
# pause
# stopped
# DLNA切换
# 恢复过程
# ============================================================
check_network_stream_stuck() {
# --------------------------------------------------------
# 恢复过程中不检测
# --------------------------------------------------------
if [ "$RESTORING" = "1" ]; then
STREAM_STUCK_COUNT=0
STREAM_LAST_POSITION=""
STREAM_LAST_URI=""
return 0
fi
# --------------------------------------------------------
# MPD无响应
# --------------------------------------------------------
if ! mpc_ok; then
return 0
fi
URI=$(get_uri)
# --------------------------------------------------------
# 当前不是网络流
# --------------------------------------------------------
if ! is_network_stream "$URI"; then
STREAM_STUCK_COUNT=0
STREAM_LAST_POSITION=""
STREAM_LAST_URI=""
return 0
fi
# --------------------------------------------------------
# 当前播放状态
# --------------------------------------------------------
STATE_NOW=$(get_state)
# --------------------------------------------------------
# 暂停/停止不算卡死
# --------------------------------------------------------
if [ "$STATE_NOW" != "playing" ]; then
STREAM_STUCK_COUNT=0
STREAM_LAST_POSITION=""
STREAM_LAST_URI="$URI"
return 0
fi
POSITION_NOW=$(get_position)
# --------------------------------------------------------
# 没拿到播放时间
# --------------------------------------------------------
if [ -z "$POSITION_NOW" ]; then
return 0
fi
# ========================================================
# 第一次检测
# ========================================================
if [ -z "$STREAM_LAST_URI" ]; then
STREAM_LAST_URI="$URI"
STREAM_LAST_POSITION="$POSITION_NOW"
STREAM_STUCK_COUNT=0
return 0
fi
# ========================================================
# 网络流换了
# ========================================================
if [ "$URI" != "$STREAM_LAST_URI" ]; then
STREAM_LAST_URI="$URI"
STREAM_LAST_POSITION="$POSITION_NOW"
STREAM_STUCK_COUNT=0
return 0
fi
# ========================================================
# 播放时间有变化
# ========================================================
if [ "$POSITION_NOW" != "$STREAM_LAST_POSITION" ]; then
STREAM_LAST_POSITION="$POSITION_NOW"
STREAM_STUCK_COUNT=0
return 0
fi
# ========================================================
# 播放时间没有变化
# ========================================================
STREAM_STUCK_COUNT=$((STREAM_STUCK_COUNT + 1))
log "网络流播放位置未变化:${POSITION_NOW} / ${STREAM_STUCK_COUNT}/${STREAM_STUCK_LIMIT}"
# ========================================================
# 超过30秒
# ========================================================
if [ "$STREAM_STUCK_COUNT" -ge "$STREAM_STUCK_LIMIT" ]; then
log "检测到网络流卡死:${URI}"
# ----------------------------------------------------
# 防止重复触发
# ----------------------------------------------------
RESTORING=1
# ----------------------------------------------------
# 记住当前是DLNA
# ----------------------------------------------------
DLNA=1
# ----------------------------------------------------
# 重置监控
# ----------------------------------------------------
STREAM_STUCK_COUNT=0
STREAM_LAST_POSITION=""
STREAM_LAST_URI=""
# ====================================================
# 重启MPD
# ====================================================
log "网络流卡死,开始重启MPD"
systemctl restart mpd
sleep 3
# ----------------------------------------------------
# 等MPD
# ----------------------------------------------------
if ! wait_mpd; then
log "MPD重启后仍然无响应"
RESTORING=0
return 1
fi
log "MPD重启成功"
# ====================================================
# 网络流卡死等同于DLNA结束
#
# 直接进入下一首
# ====================================================
RESTORING=0
restore_local_state "next"
DLNA=0
return 0
fi
return 0
}
# ============================================================
# 主程序
# ============================================================
log "MPD DLNA Resume + Network Watchdog 启动"
DLNA=0
RESTORING=0
FAILCOUNT=0
# ============================================================
# 等待MPD
# ============================================================
while ! mpc_ok
do
sleep 2
done
# ============================================================
# 启动后保存当前本地队列
# ============================================================
save_local_state
# ============================================================
# 主循环
# ============================================================
while true
do
# ========================================================
# MPD进程健康检查
# ========================================================
check_mpd
if ! mpc_ok; then
sleep 2
continue
fi
# ========================================================
# 网络流卡死检查
# ========================================================
check_network_stream_stuck
# ========================================================
# 恢复过程中跳过下面状态判断
# ========================================================
if [ "$RESTORING" = "1" ]; then
sleep 5
continue
fi
# ========================================================
# 获取当前URI
# ========================================================
URI=$(get_uri)
# ========================================================
# 当前是DLNA / 网络流
# ========================================================
if is_network_stream "$URI"; then
if [ "$DLNA" = "0" ]; then
DLNA=1
# ------------------------------------------------
# 重置网络流监控
# ------------------------------------------------
STREAM_STUCK_COUNT=0
STREAM_LAST_POSITION=""
STREAM_LAST_URI="$URI"
log "检测到DLNA流"
# ------------------------------------------------
# ★★★ 绝对不保存DLNA队列 ★★★
# ------------------------------------------------
if [ -s "$QUEUE" ] && [ -s "$INFO" ]; then
source "$INFO"
log "使用DLNA前保存的本地队列:${COUNT}首 / 第${CURRENT}首 / ${POSITION}"
else
log "没有找到DLNA前的本地队列"
fi
fi
else
# ====================================================
# 当前不是DLNA
# ====================================================
if [ "$DLNA" = "1" ]; then
log "检测到DLNA结束"
# ------------------------------------------------
# 给upmpdcli一点释放时间
# ------------------------------------------------
sleep 2
URI2=$(get_uri)
# ------------------------------------------------
# 手机又重新推送
# ------------------------------------------------
if is_network_stream "$URI2" then
log "DLNA重新连接,取消本次恢复"
else
log "确认DLNA结束"
# ------------------------------------------------
# ★★★ 直接下一首 ★★★
# ------------------------------------------------
restore_local_state "next"
fi
DLNA=0
# ------------------------------------------------
# 重置网络流监控
# ------------------------------------------------
STREAM_STUCK_COUNT=0
STREAM_LAST_POSITION=""
STREAM_LAST_URI=""
else
# =================================================
# 本地正常播放
#
# 每5秒保存
# =================================================
save_local_state
fi
fi
sleep 5
done
你的 mpd-autostart.service 也建议确认一下。
cat > /etc/systemd/system/mpd-autostart.service <<'EOF'
[Unit]
Description=MPD Auto Start Play
After=mpd.service
Requires=mpd.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/mpd-autostart.sh
RemainAfterExit=yes
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable mpd-autostart.service
systemctl restart mpd-autostart.service
systemctl status mpd-autostart.service --no-pager
先确保以前错误的服务内容全部替换:
cat > /etc/systemd/system/mpd-dlna-resume.service <<'EOF'
[Unit]
Description=MPD DLNA Resume and Network Watchdog
After=mpd.service upmpdcli.service
Requires=mpd.service
[Service]
Type=simple
ExecStart=/usr/local/bin/mpd-dlna-resume.sh
Restart=always
RestartSec=5
User=root
# 防止缓冲输出
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable mpd-dlna-resume.service
systemctl restart mpd-dlna-resume.service
systemctl status mpd-dlna-resume.service --no-pager
这个很重要,因为你之前已经产生过:
207 首 101 首 4811 首 1770 首
这些旧快照不能继续使用。
执行:
systemctl stop mpd-dlna-resume.service
rm -f /var/lib/mpd-dlna-resume/dlna_queue.txt
rm -f /var/lib/mpd-dlna-resume/dlna_info.txt
rm -f /var/lib/mpd-dlna-resume/dlna_queue.tmp
rm -f /var/lib/mpd-dlna-resume/dlna_info.tmp
systemctl daemon-reload
systemctl start mpd-dlna-resume.service
systemctl status mpd-dlna-resume.service --no-pager
systemctl list-units --type=service --all | grep -Ei 'mpd|autostart'
tail -f /var/log/mpd-dlna-resume.log
平时本地播放:
保存本地队列:101首 / 第37首 / 2:18
保存本地队列:101首 / 第37首 / 2:23
保存本地队列:101首 / 第37首 / 2:28
这个看要不要改 先改 mpd-manager.py
你现在执行
cp /usr/local/bin/mpd-manager.py /usr/local/bin/mpd-manager.py.bak
sed -i 's|START="/usr/local/bin/mpd-autostart.sh"|START="systemctl restart mpd"|g' /usr/local/bin/mpd-manager.py
执行:
python3 - <<'PY'
p="/usr/local/bin/mpd-manager.py"
s=open(p).read()
s=s.replace(
'''subprocess.Popen(
START
)''',
'''subprocess.Popen(
["systemctl", "restart", "mpd"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)'''
)
open(p,"w").write(s)
PY
grep -n -C 4 'systemctl\|START' /usr/local/bin/mpd-manager.py
["systemctl", "restart", "mpd"]
systemctl restart mpd-manager.service
#!/usr/bin/env python3
from flask import Flask,request,redirect,render_template_string
import subprocess
import re
import shutil
import os
app=Flask(__name__)
MPD_CONF="/etc/mpd.conf"
START="systemctl restart mpd"
HTML="""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>MPD DAC管理</title>
<style>
body{
background:#111;
color:#fff;
font-family:Arial;
padding:20px;
}
.box{
background:#222;
padding:20px;
border-radius:12px;
margin-bottom:20px;
}
button,select{
font-size:18px;
padding:10px;
width:100%;
}
</style>
</head>
<body>
<h2>CM101H MPD DAC管理</h2>
<div class="box">
<h3>当前配置</h3>
<pre>
{{current}}
</pre>
</div>
<div class="box">
<h3>检测到DAC</h3>
<form method="post" action="/set">
<select name="dac">
{% for d in dacs %}
<option value="{{d.hw}}">
{{d.hw}} {{d.name}}
</option>
{% endfor %}
</select>
<br><br>
<button>
切换DAC
</button>
</form>
</div>
<div class="box">
<a href="/restart">
<button>
重启MPD
</button>
</a>
</div>
</body>
</html>
"""
def run(cmd):
try:
return subprocess.check_output(
cmd,
shell=True,
stderr=subprocess.STDOUT
).decode()
except:
return ""
def scan_dac():
out=run("aplay -l")
result=[]
for line in out.splitlines():
m=re.search(
r"card (\d+): (.*?) \[.*?\], device (\d+):",
line
)
if m:
result.append(
{
"hw":
"hw:%s,%s"%(m.group(1),m.group(3)),
"name":
m.group(2)
}
)
return result
def change_dac(hw,name):
text=open(MPD_CONF).read()
if not os.path.exists(
"/etc/mpd.conf.backup"
):
shutil.copy(
MPD_CONF,
"/etc/mpd.conf.backup"
)
start=text.find("audio_output {")
if start<0:
return
count=0
end=start
for i in range(start,len(text)):
if text[i]=="{":
count+=1
elif text[i]=="}":
count-=1
if count==0:
end=i+1
break
new=f'''
audio_output {{
type "alsa"
name "{name}"
device "{hw}"
mixer_type "none"
auto_resample "no"
auto_channels "no"
auto_format "no"
}}
'''
text=text[:start]+new+text[end:]
open(
MPD_CONF,
"w"
).write(text)
@app.route("/")
def index():
return render_template_string(
HTML,
dacs=scan_dac(),
current=run(
"grep -A12 audio_output /etc/mpd.conf"
)
)
@app.route("/set",methods=["POST"])
def setdac():
hw=request.form["dac"]
name="USB DAC"
for d in scan_dac():
if d["hw"]==hw:
name=d["name"]
change_dac(hw,name)
subprocess.Popen(
["systemctl", "restart", "mpd"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
return redirect("/")
@app.route("/restart")
def restart():
subprocess.Popen(
["systemctl", "restart", "mpd"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
return redirect("/")
app.run(
host="0.0.0.0",
port=8090
)