跳转到内容
~/tosaki
返回

闲置路由 + 小米音箱:硬核打造低成本局域网 AirPlay 2 音频桥接指南

编辑页面

作为一名重度依赖米家生态的打工人,在房间配置一个支持红外的中枢网关是刚需。出于生态融合和性价比的考量,我购入了小米智能音箱 Pro 作为终端输出设备。但如果只把它当作智能家居中枢,其音响硬件未免有些性能过剩。由于这款音箱原生并不支持我重度依赖的 AirPlay,为了满足高品质流媒体音频的播放需求,就有了这次的硬核改造计划。

经过一番硬件选型和底层折腾,我最终用闲置的 Cudy TR3000 (MT7981) 路由器,通过 OpenWrt / ImmortalWrt 成功实现了一套零成本、低延迟的 AirPlay 2 接收端。这篇文章记录了整个架构的选型思考、以及在 Linux ALSA 音频层和网络组播层踩过的各种深坑。

效果图

一、 动机:为什么非得是 AirPlay?

很多人会问,直接连蓝牙不香吗?在深度使用后,蓝牙音频的体验缺陷非常明显:

  1. 通知音混流的灾难:蓝牙本质上是系统全局音频输出。当你正在享受沉浸式音乐时,手机突然来一条微信提示音,或者你在刷 TikTok / Reels,声音会直接粗暴地打断音乐并从音箱外放,体验极差。
  2. 设备切换繁琐:在 MacBook、iPhone、iPad 之间切换蓝牙音箱的配对,永远是一个不够优雅的痛点。
  3. 音频压缩:常规蓝牙协议(SBC/AAC)在重采样过程中有不可忽视的音质损耗。

AirPlay 的优势在于它是基于网络层的流媒体投射协议(TCP/UDP)。它能做到媒体流与系统通知音彻底分离(音乐在音箱放,微信提示音只在手机响),且只要设备在同一个局域网(mDNS 发现),任何 Apple 设备都可以做到一键无缝切换投流,同时原生支持 ALAC 无损传输。

二、 硬件选型:为什么是小米智能音箱 Pro?

市面上有大把的无源/有源音箱,但我最终选择用这台小米音箱作为物理输出终端,主要基于以下作为“Smart Home Hub”的考量:

它是一个完美的智能家居 Node,唯一的缺点就是原生不支持 AirPlay。我们需要一个“外挂大脑”来帮它接收并解码 AirPlay 音频流。

三、 方案调研:外挂大脑怎么选?

在选型初期,我原本打算采用社区非常经典的 AirConnect 方案。其原理是在局域网中发现 DLNA 音箱,然后将其封装并广播为一个 AirPlay 设备。但我买来后才发现,新款的小米智能音箱已经彻底阉割了 DLNA 协议。此路不通,直接接收 AirPlay 协议并通过 USB Audio 数字输出给音箱,成了唯一的突围路径。

为了实现这个目标,我考察了目前主流的几种廉价硬件方案:

  1. 旧 Android 手机 + AeroPlay App
    • 优点:零门槛,App 生态成熟(部分支持 UAPP 绕过安卓 SRC)。
    • 缺点:长期插电作为 Server 运行,电池有严重的鼓包/起火风险;即使 Root 后锁电也显得不够优雅。
  2. Raspberry Pi Zero 2 W + Shairport Sync
    • 优点:Linux 音频圈的“标准答案”,文档极多。
    • 缺点:需要额外购买,且目前供应链有时不稳定,增加了系统冗余。
  3. ESP32-S3 DIY 魔改
    • 优点:极客最爱,成本极低,S3 原生支持 USB Host。
    • 缺点:过于硬核。社区的 AirPlay 接收库大多只支持 AirPlay 1,且利用 TinyUSB 驱动特定 USB-C 音箱的 UAC 兼容性极差,需要大量底层的 C 语言 Debug。
  4. 闲置 OpenWrt 路由器(最终胜出)
    • 硬件:手头闲置的 Cudy TR3000(搭载 MT7981 神 U,性能严重过剩)。
    • 优势:原本就要插电运行,多跑一个后台 daemon 毫无压力;Linux (ImmortalWrt) 系统自带完整的 ALSA 架构和 USB 驱动,网络处理能力吊打 ESP32。

四、 踩坑实录:ImmortalWrt 的音频打通之旅

本以为在路由器上 make menuconfig 勾选几个包就能搞定,没想到一路遭遇了从底层驱动到网络架构的连环坑。

坑一:包名与依赖的“幻觉”

在编译 ImmortalWrt 时,寻找 USB 音频驱动耗费了一些时间。

开源产物:整个项目的源码及编译配置已开源至我的 GitHub:t0saki/openwrt-personal。如果你刚好也持有 Cudy TR3000 (v1),可以直接下载我编译好的 AirPlay 2 专版 Release 固件 免去编译折腾。

坑二:进程 Crash,TCP 7000 端口冲突

固件刷入,硬件通过 aplay -l 完美识别。但手动拉起 shairport-sync 时直接 Panic 退出。

坑三:OpenWrt 的 UID/GID 幽灵 Bug (Avahi Daemon Crash)

端口让出后,iPhone 依然搜不到设备。查日志发现 shairport-sync 找不到 mDNS backend,而底层的 avahi-daemon 在疯狂 Crash Loop。

坑四:有进度条没声音,ALSA 的直通与重采样悖论

手机终于搜到了设备并成功连接,进度条在走,但音箱死活没声音。

坑五:L3 NAT 导致的 mDNS 与组播黑洞

我在 TR3000 自己的子网下测试一切完美,但在主路由(父网)下,设备再次“失联”,或者点击后一直转圈。

五、 总结

这套方案最终达到了我的全部预期:

  1. 0 额外硬件成本:完全榨干了闲置路由器的剩余价值。
  2. 极高的稳定性:MT7981 的算力和 Linux 的网络栈处理 AirPlay 2 的 Jitter Buffer 游刃有余。
  3. 完美的生态融合:音箱依然是米家/红外中心,但同时拥有了 Apple 原生的流媒体投射体验。

作为工程师,折腾过程中的乐趣往往大过结果。从内核驱动、ALSA 架构,再到网络层的 mDNS 与组播抓包,解决这一连串问题的获得感,是直接买一个 HomePod 无法替代的。如果你手头刚好也有吃灰的 OpenWrt 路由和支持 USB 音频的音箱,强烈建议尝试这个方案。

当然,如果你手里有树莓派之类的开发板,那么上述 OpenWrt 的很多特有深坑(如防火墙、NAT 隔离、包管理器 Bug)都能轻松避免,但在 ALSA 音频层和网络层的软件栈配置上,依然可以参考本文的踩坑经验。


编辑页面
分享到:

下一篇
AI副屏(下):利用LLM构建多源新闻的个性化推荐流