将 Raspberry Pi 打造为专业级多音源媒体播放器,支持 Logitech Media Server (LMS)、AirPlay 2 和 蓝牙音频,配备 OLED 实时显示屏。
- 🎹 Squeezelite - 连接 Logitech Media Server,播放本地音乐库
- 📱 AirPlay 2 - 从 iPhone/iPad/Mac 推送音频
- 🔵 蓝牙音箱 - 接收任何蓝牙设备的音频流
- 📊 实时显示当前音源(SQ/AP/BT)
- 🎨 艺术家、曲目信息自动滚动
- 🔊 音量调节时弹窗显示
- 💤 智能屏保(5秒暗屏,15分钟关闭)
- PipeWire - 现代音频服务器
- WM8960 声卡 - 高保真输出
- 🎚️ 音源优先级自动管理
- 🎛️ 独立音量控制
- ⚡ 一键安装脚本
- 🔄 智能两阶段部署
- 🔌 硬件驱动自动加载
- ✅ 服务自动启动和验证
| 组件 | 推荐型号 | 必需 |
|---|---|---|
| 主板 | Raspberry Pi 4B (4GB) | ✅ |
| 声卡 | Waveshare WM8960 Audio Board | ✅ |
| 显示屏 | SSD1306 OLED (128x64, I2C) | ⭕ |
| 电源 | 5V 3A USB-C | ✅ |
| 存储 | microSD 卡 (16GB+) | ✅ |
⚠️ 重要提示:
- WM8960 是 Sound Board,不是 Audio HAT,接线方式不同
- OLED 使用 GPIO 模拟 I2C(I2C-3),不占用标准 I2C 总线
- 详细接线图请参见
documents/HW_WM8960.md和documents/HW_SSD1306.md
推荐:Raspberry Pi OS Trixie (64-bit) 或 Bookworm (64-bit)
⚠️ 重要: Trixie/Bookworm 不再支持wpa_supplicant.conf配置 WiFi
必须使用 Raspberry Pi Imager 的预配置功能
📖 详细无头安装步骤:documents/RPI_HEADLESS_SETUP.md
RPI-MediaPlayer/
├── 📄 config.ini # 主配置文件(SSH、音源、硬件参数)
├── 🚀 setup.sh # 本地部署脚本(入口)
├── 🔧 stage_1.sh # 阶段1:系统和硬件驱动
├── 🔧 stage_2.sh # 阶段2:服务安装
│
├── 📚 lib/ # 核心库
│ ├── env.sh # 环境初始化和路径管理
│ ├── utils.sh # 工具函数(日志、配置、服务管理)
│ ├── local_utils.sh # 本地脚本工具库
│ └── monitor.sh # 远程服务监控脚本
│
├── 🧩 modules/ # 安装模块(按顺序执行)
│ ├── 01-system.sh # 系统配置(时区、locale、硬件驱动)
│ ├── 02-pipewire.sh # PipeWire 音频服务器
│ ├── 03-volume.sh # 音量控制
│ ├── 04-squeezelite.sh # LMS 播放器
│ ├── 05-oled.sh # OLED 显示屏
│ ├── 06-airplay.sh # AirPlay 接收器
│ └── 07-bluetooth.sh # 蓝牙音频
│
├── 📋 templates/ # 配置和脚本模板
│ ├── configs/ # 服务配置文件
│ │ ├── bluetooth-main.conf.template
│ │ ├── oled.ini.template
│ │ ├── shairport-sync.conf.template
│ │ └── wireplumber-bluetooth.conf.template
│ ├── scripts/ # 启动脚本
│ │ ├── bluetooth-a2dp-autopair.sh.template
│ │ ├── check_services.sh.template
│ │ ├── oled_test.py.template
│ │ ├── squeezelite.sh.template
│ │ └── volume.sh.template
│ └── services/ # Systemd 服务单元
│ ├── bluetooth-a2dp-autopair.service.template
│ ├── oled.service.template
│ ├── shairport-sync.service.template
│ ├── squeezelite.service.template
│ └── volume.service.template
│
├── 🎨 resources/ # 应用资源
│ └── oled/ # OLED Python 应用
│ ├── main.py # 主循环
│ ├── config.py # 配置读取
│ ├── display.py # 显示控制
│ ├── query.py # 音源状态查询
│ ├── screensaver.py # 屏保管理
│ ├── state_handlers.py # 状态处理器
│ └── msyh.ttf # 中文字体
│
└── 📖 documents/ # 文档
├── TROUBLESHOOTING.md # 故障排查指南
├── BLUETOOTH_TIPS.md # 蓝牙配对策略
├── HW_WM8960.md # WM8960 接线和验证
├── HW_SSD1306.md # OLED 接线和配置
├── RPI_HEADLESS_SETUP.md # 无头安装教程
└── RPI_SSH_KEY_GEN.md # SSH 密钥配置
┌─────────────────────────────────────────────────────────┐
│ 本地电脑 (setup.sh) │
│ 1. ✅ 验证本地文件 │
│ 2. 📤 上传文件到树莓派 │
│ 3. 🚀 执行远程安装脚本 │
│ 4. 🔄 管理两次重启 │
│ 5. ✔️ 验证服务状态 │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 树莓派 - 阶段 1 (stage_1.sh) │
│ • ⏰ 配置时区和 locale │
│ • ⚙️ 修改 /boot/firmware/config.txt │
│ - 启用 I2C (WM8960, OLED) │
│ - 加载 WM8960 驱动 (dtoverlay=wm8960-soundcard) │
│ - 启用 GPIO 模拟 I2C (dtoverlay=i2c-gpio) │
│ • 🔄 自动重启(加载内核模块) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 树莓派 - 阶段 2 (stage_2.sh) │
│ 1. 🔍 验证硬件(WM8960 声卡、OLED I2C 设备) │
│ 2. 🎵 安装 PipeWire 音频服务器 │
│ 3. 🔊 配置音量控制(WM8960 硬件 + PipeWire 软件) │
│ 4. 🎹 安装 Squeezelite(生成虚拟 MAC 地址) │
│ 5. 🖥️ 部署 OLED 显示应用(Python 虚拟环境) │
│ 6. 📱 配置 AirPlay (Shairport-Sync + metadata 管道) │
│ 7. 🔵 设置蓝牙自动配对(NoInputNoOutput 代理) │
│ • 🔄 最终重启(确保所有服务完全就绪) │
└─────────────────────────────────────────────────────────┘
- 第一次重启:加载硬件驱动(dtoverlay 需要内核重新初始化)
- 第二次重启:确保所有用户服务在正确的运行时环境中启动
- 硬件层(WM8960):固定 95%,防止失真
- 软件层(PipeWire):100% 默认,用户可调
- 应用层(AirPlay/蓝牙):各自独立的音量控制
- 检查 PipeWire
sink-inputs的corked状态 corked: no= 正在播放,corked: yes= 已暂停- 优先级:AirPlay > 蓝牙 > Squeezelite
- SSH 密钥权限强制验证(600)
- 蓝牙 PIN 文件权限保护(600)
- AirPlay metadata 管道权限限制(664)
- ✅ 已安装 Raspberry Pi OS (Trixie/Bookworm 64-bit)
- ✅ 已配置 SSH 并可通过
rpi.local访问 - ✅ 已设置 SSH 密钥无密码登录(推荐)
在 本地电脑(非树莓派)执行以下命令:
# 1️⃣ 克隆仓库
git clone https://github.com/yourusername/RPI-MediaPlayer.git
cd RPI-MediaPlayer
# 2️⃣ 创建 SSH 密钥(如果没有)
mkdir -p rpi_keys
ssh-keygen -t ed25519 -f ./rpi_keys/id_rpi -C "player@rpi"
# 按 Enter 跳过密码(用于无密码登录)
# 3️⃣ 将公钥复制到树莓派
ssh-copy-id -i ./rpi_keys/id_rpi.pub [email protected]
# 4️⃣ 编辑配置文件
nano config.ini[ssh]
host = rpi.local # 树莓派主机名或 IP
user = player # SSH 用户名
key = ./rpi_keys/id_rpi # 私钥路径
[squeezelite]
name = RPI-Squeeze # LMS 播放器名称
server = 192.168.50.210 # LMS 服务器 IP
[airplay]
name = RPI-AirPlay # AirPlay 名称
port = 5000 # 监听端口
[bluetooth]
name = RPI-Bluetooth # 蓝牙设备名称
[oled]
bus = 3 # I2C 总线编号
address = 0x3C # I2C 地址# 5️⃣ 运行自动化安装
./setup.sh| 阶段 | 时间 |
|---|---|
| 📤 上传文件 | ~10 秒 |
| 🔧 阶段 1(系统配置) | ~2 分钟 + 重启(~1 分钟) |
| 🔧 阶段 2(服务安装) | ~5 分钟 + 重启(~1 分钟) |
| ⏱️ 总计 | 约 10-12 分钟 |
📖 点击展开完整配置示例
# ============================================
# SSH 连接
# ============================================
[ssh]
host = rpi.local # 树莓派主机名或 IP
user = player # SSH 用户名
port = 22 # SSH 端口
key = ./rpi_keys/id_rpi # 私钥路径
# ============================================
# 系统配置
# ============================================
[system]
timezone = America/Vancouver # 时区
auto_update = yes # 是否自动更新系统
# ============================================
# Squeezelite (LMS 播放器)
# ============================================
[squeezelite]
name = RPI-Squeeze # 播放器名称(显示在 LMS 中)
server = 192.168.50.210 # LMS 服务器 IP
device = default # ALSA 设备(通常用 default)
args = -a 40:4:32:0 -b 500:5000 # 可选参数(缓冲、日志等)
# ============================================
# AirPlay
# ============================================
[airplay]
name = RPI-AirPlay # AirPlay 名称(显示在 iOS 中)
port = 5000 # 监听端口
device = default # ALSA 设备
initial_volume = 60 # 初始音量(0-100)
# ============================================
# 蓝牙
# ============================================
[bluetooth]
name = RPI-Bluetooth # 蓝牙设备名称
check_interval = 20 # 自动配对检查间隔(秒)
# ============================================
# WM8960 声卡
# ============================================
[wm8960]
bus = 1 # I2C 总线编号(通常是 1)
# ============================================
# OLED 显示屏
# ============================================
[oled]
width = 128 # 屏幕宽度
height = 64 # 屏幕高度
bus = 3 # I2C 总线编号(通常是 3)
sda_pin = 4 # GPIO 数据引脚
scl_pin = 5 # GPIO 时钟引脚
address = 0x3C # I2C 地址(0x3C 或 0x3D)
# ============================================
# 路径配置
# ============================================
[paths]
# 远程安装目录名
remote_install_dir = installer
# 应用根目录名
app_base_dir = rpi-mediaplayer
# OLED 虚拟环境路径
oled_venv_dir = .venv/oled
# AirPlay metadata 管道路径
metadata_pipe = /tmp/shairport-sync-metadata
# ============================================
# 超时配置(秒)
# ============================================
[timeouts]
# APT 锁等待超时
apt_lock = 60
# PipeWire 就绪超时
pipewire_ready = 30
# SSH 连接超时
ssh_connect = 10
# 重启等待超时
reboot_wait = 180
# 重启轮询间隔
reboot_poll_interval = 5
# ============================================
# 音频配置
# ============================================
[audio]
# ALSA 硬件音量(0-100)
default_hw_volume = 95
# PipeWire Sink 默认音量(0-100)
default_sink_volume = 100
⚠️ 永远不要将私钥提交到 Git!
.gitignore已配置忽略rpi_keys/目录- 私钥仅保存在本地电脑
- 如需多台电脑部署,手动复制私钥文件
安装完成后,以下服务将自动运行:
| 服务名称 | 类型 | 功能 | 启动命令 |
|---|---|---|---|
pipewire |
👤 用户 | 音频服务器 | systemctl --user status pipewire |
squeezelite |
👤 用户 | LMS 播放器 | systemctl --user status squeezelite |
shairport-sync |
👤 用户 | AirPlay 接收 | systemctl --user status shairport-sync |
oled |
👤 用户 | OLED 显示 | systemctl --user status oled |
volume |
👤 用户 | 音量控制 | systemctl --user status volume |
bluetooth |
🔧 系统 | 蓝牙服务 | systemctl status bluetooth |
bluetooth-a2dp-autopair |
🔧 系统 | 蓝牙自动配对 | systemctl status bluetooth-a2dp-autopair |
# 用户服务
journalctl --user -u squeezelite -f
# 系统服务
journalctl -u bluetooth-a2dp-autopair -f# 使用内置的监控脚本
./check_status.sh- 在 LMS 服务器上找到播放器
RPI-Squeeze - 选择音乐并播放
- OLED 显示屏会自动显示曲目信息
- 打开 iPhone/iPad 控制中心
- 点击 AirPlay 图标
- 选择
RPI-AirPlay - 播放音乐,树莓派自动接收
- 打开手机蓝牙设置
- 搜索并连接
RPI-Bluetooth - 无需 PIN 码,自动配对
- 播放音乐
手动调节:
volume.sh up # 提高音量
volume.sh down # 降低音量
volume.sh set 75 # 设置固定音量
volume.sh mute # 静音切换
volume.sh status # 查看当前状态自动音量:
- AirPlay:通过 iOS 设备侧边按键调节
- 蓝牙:通过播放设备音量键调节
- Squeezelite:通过 LMS 界面调节
显示内容:
┌────────────────────────┐
│ SQ: 周杰伦 │ ← 顶部:音源 + 艺术家
│ 晴天 ►►► │ ← 中部:曲目(自动滚动)
│ 🔊━━━━━━━━━━━━ 75% │ ← 底部:音量条(2.5秒弹窗)
└────────────────────────┘
音源标识:
SQ:- Squeezelite (LMS)AP:- AirPlayBT:- 蓝牙
屏保功能:
- 5秒无操作 → 亮度降低(8/255)
- 15分钟无操作 → 屏幕关闭
- 有新活动 → 自动唤醒
遇到问题?请查阅详细的故障排查指南:
常见问题快速索引:
| 问题类型 | 参考章节 |
|---|---|
| 🔌 SSH 连接失败 | 部署和连接问题 |
| 🔊 声卡未检测到 | 硬件检测问题 |
| 🖥️ OLED 无显示 | OLED 显示问题 |
| 🎵 服务启动失败 | 音频服务问题 |
| 🔵 蓝牙无法配对 | 蓝牙配对问题 |
| 🔇 音量过小/过大 | 音量控制问题 |
欢迎提交 Issue 和 Pull Request!
- 📏 代码风格遵循 ShellCheck 规范
- 📦 新增模块放在
modules/目录 - 📝 模板文件使用
{{VARIABLE}}占位符 - ✅ 提交前测试完整安装流程
MIT License - 自由使用和修改
- Logitech Media Server - 开源音乐服务器
- Squeezelite - 轻量级音频播放器
- Shairport-Sync - AirPlay 音频接收器
- PipeWire - 现代音频服务器
- Luma.OLED - Python OLED 驱动库
- 问题反馈:GitHub Issues
- 讨论交流:GitHub Discussions
🎉 享受您的多功能媒体播放器!
Made with ❤️ by the RPI MediaPlayer Team
