
开发者用本地服务器恢复 Stadia 手柄 Wi-Fi 模式
来源标题:Show HN: I brought the Stadia Controller's Wi-Fi mode back with a local server
开发者推出 Stadiacast 本地服务器,让 Stadia 手柄在谷歌 2023 年 1 月关停云服务后仍能通过 Wi-Fi 连接自用 PC。该服务器无需修改手柄固件,可同时支持多个手柄,传输按键、震动和耳机音频,在 Windows 上被识别为 Xbox 360 手柄。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
Google 于 2023 年 1 月关停 Stadia,Stadia Controller 的 Wi-Fi 模式所依赖的云端端点也随之消失。Stadiacast 是一个运行在你自家网络上的小型服务器,用来替代那些端点,让你手上的手柄继续配合自己的 PC 使用:它接入你的 Wi-Fi、建立连接并保持在线,上报每一个按键、摇杆和扳机,按请求振动,并通过耳机插孔播放声音。
状态:已端到端跑通,支持运行 Wi-Fi 固件的手柄(用 ota.282115 测试过),可同时连接多个。预计会有粗糙之处。问题请发到 Discussions,bug 请发到 issues;非常欢迎 pull request。
把手柄切换到了蓝牙模式?可以恢复,见「要求」一节。
🛠️ 不修改固件。接收端按手柄的原厂协议原样通信,绝不刷写任何东西。
🔒 无账号、无云服务。输入、振动和耳机音频都只在本机与手柄之间传输。
📜 无需自行获取任何东西。接收端自带手柄接受的证书:解压、运行、唤醒手柄即可。
🎮 Windows 上的 PC 游戏手柄。每个手柄都会变成游戏可识别的 Xbox 360 手柄,游戏的振动也能传到手柄上。
🍎 macOS 上的游戏手柄。通过 OpenJoystickDriver 应用,每个手柄都会变成 Mac 游戏可识别的 Xbox 手柄,同样支持振动。
🎧 耳机音频。PC 播放的声音或任意文件都能串流到插在手柄上的耳机。
👥 支持多个手柄同时连接,各自是独立的玩家。
pip install 'stadiacast[ble,audio,gamepad]' # 或从 releases 页面解压可执行文件 stadiacast --preset live --dns-upstream 192.168.1.1 # 你的路由器:DNS sink 会把其余请求转发到那里
网络。把手柄和接收端放在同一网络,并让接收端所在机器成为手柄的 DNS 服务器;最简单的做法是在该机器上开一个热点(见 docs/setup.md)。
仅首次启动。全新开箱或已重置的手柄会停留在蓝牙设置模式,等待 Wi-Fi 凭据:
stadiacast-provision scan stadiacast-provision provision --address <ADDR> --ssid <your SSID>
用上面的命令启动接收端;如需虚拟游戏手柄,在 Windows 上加 --gamepad vigem,在 macOS 上加 --gamepad ojd。若从源码检出运行,tools/start_receiver.sh 会在后台完成同样的事,并使用 .env 文件中的设置(参见 .env.example)。
按下 Stadia 按钮约 1 秒,在第一次振动时松开,即可唤醒手柄。两次短振动加常亮灯表示已找到接收端;灯闪烁且无振动则是短暂的「上报唤醒」,再按一次即可。
观察输入。控制台会为每条上报打印一行,GET http://<receiver>/_status 显示会话状态、电量以及是否插了耳机;如果是从 PyPI 或源码安装,stadiacast-show-input captures/<stamp> 可对一次运行生成摘要。
振动。先用 --start-game 启动,因为游戏会话是通往马达的唯一路径,然后发送 0 到 65535 的强度:
curl -d '{"left":40000,"right":40000,"ms":1500}' http://<receiver>/_rumble # 脉冲 curl -d '{"left":65535,"right":20000}' http://<receiver>/_rumble # 持续 curl -d '{"left":0,"right":0}' http://<receiver>/_rumble # 停止
更多手柄各有自己的会话,在日志和 /_status 中显示为 c0、c1……;可用 ?controller=c1 或 JSON 体中的 "controller" 字段指定控制请求的目标。
用 Ctrl-C 停止;若接收端是由启动脚本拉起的,可用 tools/stop_receiver.sh。
--preset live 是经过端到端验证的参数组合;显式指定的参数会覆盖它,stadiacast --help 列出了所有可调项。
DNS。手柄必须把接收端所在机器作为 DNS 服务器。接收端会启动一个小型 DNS 服务器,把它需要的 Google 域名指向自己,其余请求转发到上游。
HTTPS。固件会用内置的 Google Trust Services 根证书验证服务器证书,但不校验主机名、有效期和吊销状态,因此接收端自带的一条 GTS 证书链就能应答所有 Google 域名。
WebRTC。手柄在其 DiscoverDisplay 请求中发起一个 WebRTC 会话;接收端通过 GMsg 推送通道应答,终止 STUN 和 DTLS,并扮演 DTLS 之后 RPC 握手中的显示端,直到手柄进入 READY 状态并开始上报输入。
游戏会话。收到 StartGame 时,手柄会为游戏串流打开第二个会话。该会话同样承载输入,并且是通往手柄振动马达的唯一路径。
docs/protocol.md 详细描述了协议,docs/architecture.md 说明了代码结构。
要求 运行 Wi-Fi 固件的 Stadia Controller(用 ota.282115 测试过)。已切换到蓝牙模式的手柄可用社区工具刷回;Stadiacast 本身绝不刷写任何东西。
一台 Windows、macOS 或 Linux 电脑,位于手柄所在网络,并充当其 DNS 服务器。参考配置是 macOS 的互联网共享热点。在 Linux 上,绑定 53、80、123 和 443 端口需要 root 或 CAP_NET_BIND_SERVICE;在 Windows 上,防火墙可能需要放行手柄(见 docs/setup.md)。
基础功能无需其他东西:接收端自带手柄接受的证书(自行提供证书是可选的),可执行文件已内置 Python。从 PyPI 或源码安装需要 Python 3.11 或更高版本。
可选:耳机音频需要 ffmpeg,Windows 上的虚拟游戏手柄需要驱动,macOS 上也需要(Linux 上的不需要),抓包需要 tcpdump。
安装 可执行文件。每个 release 都提供 Windows x86_64、macOS(Apple silicon)和 Linux x86_64 的压缩包,内含两个程序 stadiacast 和 stadiacast-provision,均为单文件并内置 Python。解压后在终端运行 stadiacast 即可。这些构建未签名:macOS 会在每个程序首次启动时阻止运行,直到你在「系统设置 → 隐私与安全性 → 仍要打开」中允许,或用 xattr -d com.apple.quarantine stadiacast stadiacast-provision 清除两者的隔离标记;Windows SmartScreen 可能会发出警告。
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。