用 Mac 串流 Windows 游戏时遇到的几次故障
用 Mac 串流 Windows 游戏时遇到的几次故障
我用 Mac mini M4 接收 Windows 笔记本上的 GTA5 画面:Windows 运行 Sunshine,Mac 运行 Moonlight。Windows 的 RTX 3050 Ti Laptop 只有 4 GiB 专用显存,游戏、桌面和编码会竞争资源。排障发生于 8 月 30—31 日,后续记录延续到 9 月 15 日;本文日期按 KB 首次 Git 入库采用 9 月 15 日。
最需要修订的是根因叙述:旧版进程崩溃、编码等待超时和画面色带是三类不同的问题。显存高水位是一个线索,HAGS 是一个待验证因素,不能把两周内的恢复记录写成已经证实并根治了 HAGS 故障。
先搭一个可验证的基础会话
链路分为捕获、编码、网络传输、解码和显示。Sunshine 的 Web 管理界面、配对控制通道和视频数据不是同一项检查。网页能打开不证明 UDP 视频顺畅;ping 低延迟也不能排除串流丢包、队列或解码问题。
Windows 游戏/桌面 → Sunshine 捕获 → NVENC 编码
↓
网络传输与缓冲
↓
Moonlight 解码 → macOS 显示从官方发布渠道安装 Sunshine 和 Moonlight,记录版本、驱动、显示器/MUX 模式和网络连接方式。在 Windows 上通过 Sunshine UI 建立管理账号,使用安装器提供的防火墙规则,并确认规则作用域匹配当前网络。Mac 添加主机、输入配对 PIN,再先开 Desktop 会话,不直接用高负载游戏当第一项测试。Moonlight 官方搭建说明
验证顺序是:能配对 → 能看到桌面 → 输入与音频正常 → 确认硬件编码/解码 → 再开游戏。初始分辨率和帧率应固定;一次只调整一项。跨网络访问再单独检查路由和访问范围,不把所有端口暴露作为排障捷径。具体端口应以所装版本和自定义基础端口为准,不能照抄本记录的非默认端口。
Running 为什么会掩盖崩溃
历史 Sunshine 0.23.1 出现画面冻结、重新连接失败。服务仍显示 Running,但日志不断出现完整启动序列。Windows 服务恢复机制可能把崩溃进程重新拉起,因此需要同时检查 PID、StartTime 和 Application 事件。
Get-Service SunshineService
Get-Process sunshine -ErrorAction SilentlyContinue | Select-Object Id,StartTime,Responding
Get-WinEvent -FilterHashtable @{
LogName='Application'; Id=1000; StartTime=(Get-Date).AddHours(-3)
} | Where-Object Message -match 'Sunshine' |
Select-Object TimeCreated,Id,Message
Get-Content 'C:\Program Files\Sunshine\config\sunshine.log' -Tail 100历史事件中一分钟内出现 6 次崩溃,异常 0x80000003、相同模块与偏移。它支持“重复触发同类崩溃路径”,但 breakpoint 异常不单独证明是哪条断言,更不证明具体证书校验代码错误。记录里的配对对象和证书情况是线索,缺少 Dump 与调用栈,不保留原文“证书错乱就是确定根因”的定论。
处理时先备份 config、配对状态与事件日志,再通过 UI 检查配对或按官方流程升级。手改 sunshine_state.json 会影响配对与格式兼容,不作为通用第一步。历史升级至 v2025.628.4510 后连续串流 50 分钟未崩溃,说明当时表现改善,不等于所有超时一起消失,也不是今天必须使用该旧版。
encode wait timeout 说明哪一段没有完成
另一轮日志出现 frame 1 encode wait timeout,同时设备读数为 3688/4096 MiB、92% 利用率、60 W。说明该窗口内显存和 GPU 活动较高,编码等待未按期完成;并没有记录可单独证明“NVENC 因分配显存失败而永久卡死”的分配错误或驱动栈。
nvidia-smi --query-gpu=timestamp,name,memory.used,memory.total,utilization.gpu,power.draw --format=csv -l 2连续采集与 Sunshine 日志对齐时间,比一张高水位截图更有用。保留游戏场景、桌面分辨率、编码配置与客户端统计;WDDM 不支持的字段保留 N/A。如果结束进程失败,也先记录错误、残留 PID、服务状态,不能把它直接叫作 Unix 意义的僵尸进程。
降低游戏纹理或后台负载、先建立串流再启动游戏,都是合理的本机试验,但效果需同条件复测。原文的固定“80% 安全线”、每个设置节省几百 MiB,以及 MUX 必须保持独显直连,不作为所有机器的结论。显示路径和跨适配器捕获本身也应检查。
HAGS 参数与关闭 HAGS 是两回事
Sunshine 的 nvenc_realtime_hags 管理 HAGS 开启时的编码调度优先级;设为 disabled 不等于在 Windows 中关闭 HAGS。官方说明涉及 NVIDIA、实时优先级及高显存使用时的冻结风险,降低优先级也存在捕获性能取舍。Sunshine 配置说明
历史记录确认 HAGS 开启,设置 nvenc_realtime_hags=disabled 后仍发生超时,后续未做关闭系统 HAGS 后的匹配对照。因此本文只把 HAGS/驱动调度列为假设。上游 issue #863可帮助设计实验,但那是不同显卡、驱动和版本的报告,不能替代这台机器的验证。
下一轮应固定版本、驱动、显示模式、场景、分辨率、帧率和码率,分别测试系统 HAGS 开/关,按要求重启,再比较编码延迟、超时次数、游戏帧率和恢复情况。驱动升级另做一轮,不要把多个变化放进同一次“修复”。这是建议的验证路径,未在写作期间执行。
位深、色度和能力通告不要混在一起
原 KB 把 hevc_mode=4 解释成 10-bit 4:4:4 开关。核对官方配置后,这个映射不能成立:文档中的 0/1/2/3 处理能力通告,Main10 也不等于 4:4:4。位深、色度采样、HDR、色彩范围和实际编码 profile 要分别确认。
历史确实观察到改参数后渐变色带变化,但没有完整的前后协商记录,因此不保留“用某个数值一定得到 10-bit 4:4:4”“编码缓冲精确减半”的说法。调整后查看服务端创建编码器日志与 Moonlight 会话统计,确认实际格式,再比较同一场景截图或观感。
对带宽、画质和稳定性做取舍时,先固定输出分辨率和帧率,再单项调整码率、codec、HDR 或游戏画质。客户端支持某种格式不代表服务器、驱动和当前显示路径都支持。两侧指标要对应:网络掉帧、解码掉帧和编码延迟不是同一件事。
两周记录实际证明了什么
| 时间 | 原始动作摘要 | 可以采用的结论 |
|---|---|---|
| 9 月 1 日 | 10:50, 23:54 | 有 2 次记录动作 |
| 9 月 2 日 | 23:52 | 有 1 次记录动作 |
| 9 月 3 日 | 00:46, 11:54, 22:35, 22:45, 23:50 | 有 5 次记录动作;不能沿用原文“当天 4 次” |
| 9 月 4—15 日 | 没有列出新的超时动作 | 未记录同类动作;不是带负载分母的可靠性证明 |
共 8 次与超时对应的看门狗重启,另有 5 次服务停止后的拉起,类别要分开。KB 记载会话可恢复;动作日志本身只能证明触发与执行,不能单独证明零丢帧、零影响或游戏状态永远安全。
原脚本扫日志尾部、判断三分钟内错误,并用五分钟去重。保留它的设计思路,但新方案还应记事件唯一标识、上次已处理位置、重启前后的 PID、退出码与会话探针;重启失败不更新“成功”标志。日志轮转、时间回拨、重复运行和没有活跃会话时的旧错误都要纳入验证。没有做这些测试,就不发布一个声称通用可用的自动重启脚本。
排障决策与回滚
| 现象 | 下一份证据 | 最小干预 |
|---|---|---|
| 服务 Running,PID 不断换 | Event 1000、启动日志、Dump | 备份后处理版本/配对,不先调码率 |
| PID 稳定,编码超时 | 编码器日志、同步 GPU 读数 | 固定变量测试负载与调度 |
| 编码正常,客户端掉帧 | Moonlight 统计、网络路径、解码信息 | 单项降低码率或输出负载 |
| 颜色异常 | 实际 codec/profile/HDR/范围 | 同场景格式对照 |
每次记录原配置与版本,停用旧看门狗后再测新版本,避免自动重启掩盖结果。失败时恢复单项设置或备份,保留证据再选择维护窗口重启。后台 GPU 与虚拟屏管理见系列另一篇,不要把退出 LegionZone 或关闭虚拟屏与编码器故障混为一个修复。
本文日期采用主 KB 首次 Git 提交日期 2026-09-15(UTC+8),提交 6d198b9。合并来源保留在元数据中;历史操作时间与入库时间分别注明。修订后的配置示例未在生产设备执行。
