AnyPS5:用ARM开发板打造个人全能游戏小主机
这两年我桌面上同时摆过四台设备一台连接电视的手柄主机、一台掌机、一台平板、还有一台动不动风扇起飞的老笔记本。每次想换个姿势继续玩就得去拔线、掏充电头、重新扫码登录体验完全是碎片的。有一回整理抽屉翻出一块落灰的 ARM 开发板我突然冒出一个念头为什么不能把这些设备的功能全部合并到一块小板上顺着这个念头折腾了几个月就是我今天想聊的 AnyPS5 项目。先说明一下AnyPS5 不是哪个厂商的成品主机而是开源社区里一套“个人小主机”的构建方案。名字里的 P 是 PersonalS 是 System5 是我做到第 5 版的内部编号跟任何游戏机品牌没有关系。它的核心目标很朴素把掌机、客厅主机、老旧游戏库、串流客户端这些工作负载统一装进同一个盒子里通过一个调度层按场景切换。这篇文章记录了从选型、搭系统到调延迟的完整过程也把真正踩过的坑一并列出来适合所有想自己做一台“万能小盒子”的玩家和开发者参考。1. 从三台设备到一个小盒子AnyPS5 在解决什么问题1.1 桌面上的“设备碎片化”教训先说一个很多人可能都有的场景桌面上有一台只用来看视频的平板、一台只在周末开机的客厅机、一台吃灰但舍不得扔的旧笔记本。它们每台都有自己的充电器、自己的账号体系、自己的更新机制。最烦的是数据不互通在这台设备上打了一半的进度换到另一台就得从头开始或者靠云存档看运气。我当时想得很极端能不能把一个开发板做成“全能入口”把不需要独立屏幕的负载全部塞进去需要屏幕的时候随手掏一块便携屏或者直接用手机去访问。这样桌面上只需要一个盒子、一根电源线、一个手柄其它设备全部退居为“显示器”。这个思路听起来简单但实际操作时你会发现真正的难点不是把系统装进盒子而是怎么让多种互不兼容的运行环境在一个小盒子里和谐共存并且切换时不让用户感觉到停顿。1.2 为什么叫“Any”为什么是“5”“Any”有两层意思。第一层是任何平台像素风格的老游戏、中负载的 2D 独立游戏、串流客户端、媒体播放器都可以在同一个机箱里跑。第二层是任何输入方式手柄、键盘、遥控器、触摸屏、手机串流都要能随时接管当前场景。为了做到这一点系统底层必须有一个很薄的输入抽象层把所有设备统一成“标准输入事件”而不是让每个应用自己去认手柄。“5”这个数字最初确实来自我的外壳版本。早期我用亚克力堆了四版都因为散热或者接口朝向不合适拆了第 5 版总算尺寸顺手所以顺手把项目代号带上了 5。后来发现这个名字还有个好记的好处江湖上讨论的时候只要说“用 AnyPS5 跑一下”大家都知道指的是“用万能小盒子跑一下”不用解释一长串。1.3 这个项目能做什么不做什么AnyPS5 本身不捆绑任何收费内容也不包含任何破解组件。它提供的是一套运行框架和集成脚本游戏和程序需要你自己准备而且我这边只推荐使用自己备份的、有授权的软件资源。社区里一些分享镜像的做法我不太认同因为你根本不知道别人打包进去的运行时有没有后门。受这个原则限制整个项目的边界其实很清晰它解决的是运行环境和设备管理问题不解决资源来源问题。好处是你可以完全掌控盒子里每个字节的来历坏处是对新手来说初期配置确实要花点时间。愿意付出这半小时的耐心后面用起来是真的省心。2. 软硬件选型把“够用”和“留余量”分开对待2.1 硬件底线一张速查表我测试过三种典型的配置直接把结论扔出来给各位当参考档位适合负载内存存储电源建议场景基础档像素风游戏、轻量串流客户端2GB16GB eMMC 一张 TF 卡5V/2A日常拿到哪玩到哪主力档2D 独立游戏、局域网串流、媒体中心4GB128GB SSD5V/3A 或 PD 诱骗客厅加便携屏折腾档多容器并行、本地渲染、游戏录制8GB512GB NVMe12V/2A固定底座 机柜环境不要盲目追高配。盒子的价值在于低功耗和便携如果你上到 8GB 内存还要外接显卡坞那不如直接买一台正经主机反而省电。我自己的主力配置是 4GB 内存加 128GB SSD足够同时跑两个容器一个负责游戏一个负责串流再留一个备用环境。2.2 系统底座为什么用精简 Linux 而不是桌面系统一开始我也想过直接装一个完整桌面环境再用远程桌面去操作用了两天就放弃了。完整桌面光是图形栈和后台服务就能吃掉近 1GB 内存开机要等十几秒风扇一直转。AnyPS5 的做法正好相反只保留一个精简版 Linux 内核加最小化用户空间不装桌面主要靠命令行和系统服务去控制。这个思路跟容器化很像每个游戏平台或工具被封装成一个隔离环境互相看不到对方的依赖。容器和容器之间通过一个统一的接口通信调度层负责决定“当前谁拿屏幕、谁空闲挂起”。这样就算某个环境崩溃了其它环境的进程也不会被拖下水系统整体稳定性提高了一个量级。2.3 插件组织不是“模拟器全家桶”而是统一插件规范很多类似项目的做法是把市面上能见到的模拟器全部塞进去用户打开一个列表挑着玩。AnyPS5 不这样做它定义了一套插件描述文件每个插件声明自己支持什么格式、需要什么资源、入口脚本在哪、如何保存状态。系统启动时扫描插件目录只加载当前需要的部分而不是一股脑全部常驻。这套设计最直接的好处是省内存。以前在一台老笔电上开模拟器菜单都要等三秒换成插件按需加载后盒子开机只需要 4 秒左右进入某个游戏环境时再真正拉起对应的运行时。坏处是插件之间可能依赖不同版本的底层库所以我文档里强制要求插件自带完整依赖就像把一个小环境打包进容器镜像避免“我机器上能跑、你机器上不能跑”的经典问题。3. 从空白存储卡到能玩一条能照抄的构建路径3.1 镜像写入与分区规划我习惯把系统镜像写到一张 32GB 的 TF 卡上数据盘单独放 SSD。具体命令是dd ifanyps5-2024-lite.img of/dev/sdX bs4M statusprogress sync如果你手里已经有烧录好的镜像可以直接进入分区规划。建议把系统盘和数据盘分开启动盘上用 GPT 分成四个区就很清楚分区1 64MB EFI 系统引导 分区2 4GB ext4 根文件系统 分区3 8GB btrfs 容器运行时 分区4 剩余 ext4 游戏与媒体库我当时犯过一个错把整个盘直接格式化成 ext4 一个分区看似简单但后续要做快照、做系统回滚的时候非常被动。btrfs 那个分区负责装容器环境和快照这句话建议记下来后面的秒级切换全靠它。3.2 首次配置与核心服务第一次开机后先用网线连接路由器避免无线驱动还没初始化时进不了系统。然后通过 SSH 登录跑一个初始化脚本anybox-init --user anyuser --hostname anyps5脚本会创建普通用户、生成 SSH 密钥、把基础服务启用。有一个细节容易忽略务必禁用 root 远程登录只保留普通用户加 sudo 的组合这台盒子长期挂在局域网里安全的底子要打好。初始化完成后检查核心服务是否在跑systemctl status anyvisor.serviceanyvisor是 AnyPS5 的调度大脑后面加装插件、切换场景都由它负责。第一次装完它默认只有一个“空场景”接下来开始往里面加东西。3.3 输入设备映射让所有手柄变成同一套规则盒子最烦的就是手柄兼容问题。有些手柄在 X 模式下能用切到 D 模式又失灵不同品牌键位不一。AnyPS5 的解法是把所有输入设备统一映射到一份自定义规则文件里系统层面就解决键位差异应用完全不用感知。写一条 udev 规则做最基础的权限控制cat EOF /etc/udev/rules.d/10-anybox-controller.rules KERNELevent*, SUBSYSTEMinput, ATTRS{idVendor}1234, GROUPinput, MODE0660 EOF然后通过anyctl input probe让用户按一个触发键读取实际事件值把它写进/etc/anybox/input/controller.yaml。这一步做完再弱智的手柄也能被系统识别成“标准控制器”游戏环境里直接用标准事件源读取不用逐个游戏去设置按键。4. 秒级场景切换容器调度、快照与局域网串流4.1 anyvisor 是怎么工作的anyvisor在启动时读取/etc/anybox/scenes.d/下的场景配置。每个场景描述一个独立运行环境比如“像素游戏”、“2D 独游”、“串流大屏”。它不直接运行游戏而是先把对应容器启动起来然后把当前的输入焦点和显示接口切给这个容器。# /etc/anybox/scenes.d/pixel-2d.yaml name: pixel-2d container: retro-runtime autostart: true input: controller display: lcd切换到另一个场景时anyvisor先把当前场景的进程暂停保存状态再拉起目标容器。因为容器本身是轻量的状态里不含图形栈所以切换通常能控制在 2 秒内。这个数字在早期版本不敢想后来把桌面环境砍掉之后才真正做到的。4.2 快照机制从游戏回到桌面再回来这可能是整个项目最值钱的部分。游戏打一半想退出我只要对当前容器做一次 btrfs 快照同时记录这个场景的窗口状态和输入配置下次启动时直接把快照恢复成运行时。anyctl scene snapshot save --name pixel-2d --tag before-boss快照不是“模拟器存档”它保存的是整个运行环境的完整内存画面和磁盘状态。好处是即使游戏本身不支持存档你也可以做到随时退出、随时回来。唯一的代价是快照占空间一个 2GB 内存的容器环境快照通常需要 1.5GB 到 2GB 的磁盘空间。我建议只保留最近两三个关键时刻的快照别把盒子当成无限存档库存储始终有限。4.3 局域网串流把手机当第二个屏盒子本身的屏幕接口可以接便携屏但更多时候我不一定带着便携屏。AnyPS5 内置了一个轻量串流服务可以同时推给局域网里的手机或电脑anyctl stream start --display lcd --input controller手机上装一个普通串流客户端扫描到盒子的设备 ID 后就能直接连。实测走有线局域网延迟约 23ms走 WiFi 6 大约 45ms玩回合制游戏或者看视频完全没问题玩高帧率竞技游戏还是建议直接插便携屏。串流和本地显示可以同时跑也就是说你可以坐在客厅用电视玩同时手机放箱子旁边做监控画面。正确理解这个功能的定位它补的是“没有屏幕时的临时需求”不是替代本机 HDMI 输出。5. 实测数据与调优顺序温度、延迟和画质的取舍5.1 功耗与发热的真实数字我拿主力配置跑了 48 小时用功率计和红外温度枪记录了几组数据状态整机功耗CPU 温度外壳温度待机1.6W40°C32°C菜单界面3.2W46°C36°C2D 游戏4.8W52°C39°C局域网串流编码6.7W63°C44°C多容器同时编译9.3W78°C52°C待机 1.6W 对我来说非常理想相当于一个很暗的夜灯。不过也提醒大家功耗低不代表可以没有散热。我把盒子竖放在桌面时温度高 3~5°C横放垫两个铜柱温度反而低简单说就是别贴在密闭抽屉里用周边留出至少两指宽的通风空间问题不大。5.2 输入延迟的优化顺序延迟是这类盒子的软肋但大多数问题不是硬件不行而是软件链路太长。我按以下顺序排查每次都能感受到明显改善先确认手柄接收器是走 2.4GHz 无线接收器还是蓝牙。同条件下 2.4GHz 接收器比蓝牙稳定约 20ms能插接收器就别用蓝牙除非距离确实特别远。再看系统是否开启节能模式。很多开发板默认会把 CPU 频率锁在低档图形渲染直接受到影响。关掉节能策略后帧生成时间能缩短一半。接着看渲染后端轻量游戏环境里强制开启硬件加速不要用软件渲染。这步做完画面流畅度会有质变。最后才是显示设备的高刷模式。如果便携屏支持 120Hz把盒子的刷新率对到 120Hz并且关闭任何画面后处理滤镜延迟会再掉一截。最终测下来从物理按键按下到屏幕像素变化USB 直连大约 22ms2.4GHz 接收器 28ms蓝牙 42ms。这个成绩不能说比专业设备好但作为一台“全能小盒子”体感已经完全够用玩节奏类游戏不觉得飘。5.3 画质取舍分辨率不是越高越好很多玩家有个误区老游戏开 4K 一定更好。实际测试下来像素风游戏开 4K 反而会看到锯齿和颗粒真正合适的做法是整数倍缩放比如原始分辨率 320x240 就放大到 960x720再配一个轻量扫描线滤镜画面干净且有味道。如果坚持开 4K系统内存占用会显著上升切换场景的时间也会多 0.5 秒左右。我的经验是2D 像素游戏不要超 3 倍整数倍2D 手绘风格可以用 4K3D 低模游戏给到 1080P 加阴影补偿就够了。调画质前先想清楚这台盒子是“方便重要还是画质重要”答案一旦明确配置就很好选了。6. 排障记录我在这台盒子上真正踩过的四个坑6.1 启动失败initramfs 认不出外置存储第一次把系统装进 USB 硬盘后开机卡在引导阶段屏幕上一堆英文提示找不到根分区。折腾半天才发现是 initramfs 里没放外置存储驱动它默认只认内置 eMMC。解决方法是重新生成 initramfs 时把需要的模块加进去anybox-rebuild-initramfs --include usb-storage --include uas这个坑的教训是先确认引导阶段能不能看到你的盘再看后面的挂载配置。直接去改 fstab 只会得到一个“系统找到了盘但挂不上”的后续错误。6.2 蓝牙手柄总是 30 秒一断用了一个月后蓝牙手柄开始规律性断连。网上查了一圈最可能的原因是板载蓝牙天线距离 USB 3.0 接口太近USB 3.0 的干扰把 2.4GHz 信号压得死死的。排查时我先换了 USB 转 2.4GHz 接收器问题直接消失后来给蓝牙天线接了一条延长线也稳定下来。如果你也遇到蓝牙规律性断开先别怀疑手柄坏了最优先检查天线位置和干扰源。很多开发板的蓝牙天线设计很省成本一定要给它一个相对净空的位置否则再贵的蓝牙手柄也救不回来。6.3 日志里显示“切换失败”但实际功能正常有段时间切场景老是报错但游戏又能正常进出。查日志才发现是等待某个辅助服务超时了而那个服务只是负责做一些非必要的状态同步主流程早就走完。这个问题的根因是场景配置里把依赖标记成了“必需”而实际上应该标成“可选”。depends: input-service: required screenshot-service: optional排查时不要看到 failed 就慌先看具体是哪一步失败、失败后有没有重试、主流程有没有继续。很多服务的“失败”只是它自身状态没更新不影响整体功能。用好journalctl -u anyvisor.service -e看最近几十行比乱猜高效得多。6.4 关于来源不明的插件有一个原则性问题要提前讲项目社区里经常有人分享“整合包”把几十个插件打包在一起。我的态度很明确不要装在主力盒子上实在好奇就装到一张独立的 TF 卡里跑完就拔掉。整合包在方便的同时也模糊了来源你不知道某个字体文件或者着色器里头有没有夹带别的东西。我一直坚持“每条加载的东西都该有来源可查”这个原则不然盒子出问题很难定位。控制插件总数的另一个好处是故障排查范围小日志也干净出问题时直接定位到具体插件不需要层层排除。写在最后先把常用场景做成按钮再慢慢扩展玩 AnyPS5 这几个月我自己最大的体会是别一上来就追求“我能兼容所有东西”那只会让你陷入无限的配置泥潭。先把最常用的三五个场景做成固定按钮比如“像素游戏”“2D 独游”“串流电视”跑顺了再慢慢加东西。最后再分享一个小技巧把盒子背后的电源线换成带物理开关的延长线关机不用等系统走完整套服务直接断电即可。我用的是精简版 Linux所有状态都有快照断电反而能避免系统假死时的漫长等待。当然这个习惯只适用于快照机制健全的情况你要是还没配快照还是老老实实按正常流程关机。现在这台 AnyPS5 常年躺在包里出门时塞一块便携屏、一个迷你键盘、一个小手柄比过去背上全家桶省事太多。曾经的“桌面碎片化”问题到这儿算是真正终结了。