Skip to content

holefrog/RPI-MediaPlayer

Repository files navigation

Logo

🎵 RPI MediaPlayer

将 Raspberry Pi 打造为专业级多音源媒体播放器,支持 Logitech Media Server (LMS)AirPlay 2蓝牙音频,配备 OLED 实时显示屏


✨ 核心特性

🎼 三音源无缝切换

  • 🎹 Squeezelite - 连接 Logitech Media Server,播放本地音乐库
  • 📱 AirPlay 2 - 从 iPhone/iPad/Mac 推送音频
  • 🔵 蓝牙音箱 - 接收任何蓝牙设备的音频流

🖥️ 智能 OLED 显示

  • 📊 实时显示当前音源(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+)

⚠️ 重要提示:


💽 操作系统

推荐: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-inputscorked 状态
  • 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 分钟

🔧 配置说明

核心配置(config.ini)

📖 点击展开完整配置示例
# ============================================
# 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

🎮 使用指南

🎵 播放音乐

方式 1:Logitech Media Server (LMS)

  1. 在 LMS 服务器上找到播放器 RPI-Squeeze
  2. 选择音乐并播放
  3. OLED 显示屏会自动显示曲目信息

方式 2:AirPlay

  1. 打开 iPhone/iPad 控制中心
  2. 点击 AirPlay 图标
  3. 选择 RPI-AirPlay
  4. 播放音乐,树莓派自动接收

方式 3:蓝牙

  1. 打开手机蓝牙设置
  2. 搜索并连接 RPI-Bluetooth
  3. 无需 PIN 码,自动配对
  4. 播放音乐

🔊 音量控制

手动调节:

volume.sh up      # 提高音量
volume.sh down    # 降低音量
volume.sh set 75  # 设置固定音量
volume.sh mute    # 静音切换
volume.sh status  # 查看当前状态

自动音量:

  • AirPlay:通过 iOS 设备侧边按键调节
  • 蓝牙:通过播放设备音量键调节
  • Squeezelite:通过 LMS 界面调节

🖥️ OLED 显示说明

显示内容:

┌────────────────────────┐
│ SQ: 周杰伦              │  ← 顶部:音源 + 艺术家
│ 晴天 ►►►               │  ← 中部:曲目(自动滚动)
│ 🔊━━━━━━━━━━━━ 75%    │  ← 底部:音量条(2.5秒弹窗)
└────────────────────────┘

音源标识:

  • SQ: - Squeezelite (LMS)
  • AP: - AirPlay
  • BT: - 蓝牙

屏保功能:

  • 5秒无操作 → 亮度降低(8/255)
  • 15分钟无操作 → 屏幕关闭
  • 有新活动 → 自动唤醒

🛠️ 故障排查

遇到问题?请查阅详细的故障排查指南:

常见问题快速索引:

问题类型 参考章节
🔌 SSH 连接失败 部署和连接问题
🔊 声卡未检测到 硬件检测问题
🖥️ OLED 无显示 OLED 显示问题
🎵 服务启动失败 音频服务问题
🔵 蓝牙无法配对 蓝牙配对问题
🔇 音量过小/过大 音量控制问题

🤝 贡献

欢迎提交 Issue 和 Pull Request!

开发指南

  • 📏 代码风格遵循 ShellCheck 规范
  • 📦 新增模块放在 modules/ 目录
  • 📝 模板文件使用 {{VARIABLE}} 占位符
  • ✅ 提交前测试完整安装流程

📄 许可证

MIT License - 自由使用和修改


🙏 致谢


📮 联系方式


🎉 享受您的多功能媒体播放器!

Made with ❤️ by the RPI MediaPlayer Team