Sunshine + Moonlight 实现低延迟远程串流
本文最后更新于:4 个月前
前言
这两天沉迷于搞远程串流,市面上有很多远程串流软件,我用过的就有如:Windows远程桌面连接、向日葵、Pasec等。最终还是选择了Sunshine + Moonlight的方案,在这里写一篇博客记录下整个过程。
网络篇
公网IPv4申请(可选)
由于Moonlight支持公网IPv6访问,因此拥有IPv6地址的用户可以跳过本步骤。
对各运营商来说IPv4地址是紧缺资源,所以申请各运营商的IPv4地址的难易程度也不尽相同。
本人目前在郑州市区使用的是联通的宽带,申请过程非常简单。只需要拨打联通宽带“98480”电话,告诉客服你需要申请公网IP即可,等客服确认你的身份,并且询问过你开公网IP的用途(家用远程设备访问、游戏服务器搭建等)后当时就能开通。
光猫改桥接模式
但这时虽然拿到了公网IP还不能直接使用,宽带运营商在装家用带宽时会将光猫默认设置为路由模式,此时的光猫除了进行一般的光电信号转换外,还有路由器的功能。
而我们的终端设备需要连接家里的路由再过光猫才能与互联网沟通,此时路由器与光猫组成双NAT,如果我们需要远程访问家庭网络中的设备,则需要在两个路由器上都进行端口映射,十分繁琐。
所以这时我们要把光猫由路由模式改为桥接模式,砍掉它的路由功能只保留光电信号转换功能。
这里就以我的设备为例,讲解下光猫的桥接模式修改。
首先找到家里的光猫,背面会提供以下信息,需要记住后面会用到:
- Web页面地址
- 默认用户名
- 默认用户密码

接下来在浏览器中输入Web页面地址192.168.1.1进入光猫的管理界面。

输入默认用户名,默认密码并登录。

在 “网络 - 宽带配置” 选项卡中将对应的连接模式由 “PPPoE” 改为 “Bridge”,并确认,此时设备会处于断网状态。
早些年各运营商会把改桥接功能藏在超级用户里(防止客户乱改导致需要工程师频繁上门维护),现在需要改桥接的用户多了联通就把这个功能放在默认普通用户里了,可以不用再费尽心思的找超级管理账户的账号密码了。如果你的光猫仍然需要超级账户才能改桥接,请自行搜索或询问运营商取得超级管理账户和密码。

这里可以顺便来到 “网络 - WLAN配置” 选项卡中,将所有SSID的 “SSID使能” 关闭,以关闭光猫的无线功能,减少对路由器的信号干扰。
到这一步光猫的设置就完成了,现在转到路由器的设置,不同路由器有不同的设置方式,但殊途同归,这里拿我用的TP-LINK路由举例说明。

登录路由器的管理界面后将 “上网方式” 由 “自动获得IP地址” 改为 “宽带拨号上网(PPPoE)”。然后输入宽带账号和宽带密码(一般写在光猫上或打运营商电话取得),这时拨号上网的功能就转移到路由器上了,待路由获取到IP,设备就将恢复联网。
此时路由获取的IP地址即为公网IP,可以通过百度搜索 “IP” 来对照路由IP是否相同来判断是否真的获取到了公网IP。

需要注意的是,设置完路由器拨号后,光猫的Web页面将不能通过192.168.1.1访问,如需管理光猫设备需要将路由改回 “自动获得IP” 地址再进行操作。
动态域名解析(DDNS)
家庭用户一般从运营商申请到的公网IPv4都是动态公网IP,根据不同运营商的服务策略申请到的IP会在数小时到数月内发生更改,如果不进行动态域名解析(DDNS)那么我们需要频繁的查看路由器当前的IP地址是否被更改,十分的麻烦。
路由器或网络上有很多提供免费DDNS的服务商(TPLINK、花生壳等),通过注册账号即可申请到免费的域名来解析我们获得的动态公网IP。

依然以TP-LINK路由器为例,其内置DDNS应用,我们可以很简单的申请到一个xxx.tpddns.cn地址用来解析我们的动态公网IP,之后Moonlight中需要我们填入目标IP时直接通过输入该地址解析即可。
IP - MAC绑定
在上一步中我们实现了动态公网IP的DDNS(相当于固定了路由的IP地址),但同一路由器中可能连接有其他不同的设备,且这些设备的局域网内IP地址也时常变动,如果我们想精准的访问内网中的设备就需要将内网IP与设备的MAC地址绑定。
MAC地址也叫物理地址、硬件地址,由网络设备制造商生产时烧录在网卡的相关芯片当中,MAC地址通常表示为12个16进制数,其地址是全球唯一的,可以当作网络硬件的身份证。

可以看到我的局域网内有很多设备,我只想通过外网访问我的台式机,这里我添加了一个绑定设置,使得路由器只给某一确定的MAC地址(台式机)绑定固定的内网IP地址192.168.0.100,之后无论内网设备如何变动我的台式机都只会拥有唯一的内网IP 192.168.0.100。
DMZ主机或端口映射(虚拟服务器)
之前两步,我们“固定”了公网和内网设备IP地址,唯一确定了我们想访问设备的地址,但现在还不能外网直接访问目标设备,因为实际上拥有公网IP的是路由器而非目标设备,所以这一步我们要做的就是将设备的端口一一映射到路由器中,达成我们访问路由器某一端口就能直接访问目标设备端口的目的。完成这一目标我们有两个方案可选:DMZ主机和端口映射(虚拟服务器)。
DMZ主机
所谓DMZ主机,即完全开放我们内网中的某一设备给公网,适用于内网中只有单设备需要被外部访问的情况,我目前只需要外网能够访问我的台式机即可,所以选择了这种方案。

设置DMZ主机的方式也十分简单,只需要设置目标设备的内网IP地址即可,这里我们填上192.168.0.100就大功告成了。
端口映射(虚拟服务器)
端口映射,TP-LINK中又称为虚拟服务器,指的是我们将内网中的某一设备的某一端口映射到路由器的某一端口上,来达到外网访问的目的。适用于内网中有多设备需要被外网访问的情况。由于端口可控,所以安全性相比DMZ主机来说更高,但操作略显繁琐。

在上图中我们添加了一条映射规则,映射192.168.0.100(台式机)的7210端口给路由器的7210端口,并且允许TCP/UDP两种协议数据通过。内外部端口可以不同,可以类比着添加需要的其他映射规则。
需要注意的点是开通端口映射的设备务必完成IP - MAC绑定步骤,并且不要尝试绑定外部的80和443端口。
至此我们已经完成了对路由器的全部设置,可以开始进行串流软件的安装。
串流篇
方案优势
在介绍Moonlight之前首先谈一谈其余的远程串流有什么缺点。
- Windows远程桌面:需要被串流方有公网IPv4,延迟较高,对视频、游戏的支持不好,只适合日常办公。
- 向日葵:需要注册账号,高级功能需要付费解锁,恼人的弹窗广告,免费版也只适合日常办公。
- Pasec:需要注册账号,需要被串流方有公网IPv4。
在我看来Parsec和Sunshine的远程串流质量不相上下,但Moonlight + Sunshine有让人不能拒绝的理由:
- 跨平台:Windows、Mac、Linux、Android
- 丰富的编码器:H.264、H.265、AV1
- 公网IPv6访问
- 命令行指令:丰富的指令输入,拓展性极强
接下来介绍这套方案的具体搭建步骤。
软件安装
原本使用Moonlight串流只需要连接上NVIDIA的SHIELD GameStream服务就可以。但是这项服务在2023年的2月份被停止了,所以需要使用Sunshine代替这项服务的位置。
Sunshine是Github上的开源项目,项目地址:
Sunshine:https://github.com/LizardByte/Sunshine
Sunshine安装在需要被串流的设备上,这里我将它安装在我的台式机上,安装过程略过一路Next即可。
Moonlight是Github上的开源项目,项目地址:
moonlight-qt(for Windows, Mac, Linux, and Steam Link):https://github.com/moonlight-stream/moonlight-qt
moonlight-android:https://github.com/moonlight-stream/moonlight-android
Moonlight安装在接收串流的设备上,如手机、平板、笔记本等上,Github里分为两个版本,qt适用于Windows, Mac, Linux 和 Steam Link,android自成一个版本按需下载。
Sunshine配置
初次启动Sunshine,网页会提醒设置账户及密码,填入后并记住供以后使用。
大部分配置默认或按需调整即可,这里我介绍几个比较重要的设置。
IPv6访问配置

如果需要开启IPv6访问,需要在 “Configuration - Advanced - Address Family” 中选择 “IPv4 + IPv6”。
编码器配置(N卡)

由于我使用的是NVIDIA 30系列显卡,所以同一页面中的 “Force a Specific Encoder” 我选择 “NVIDIA NVENC” 强制使用独立显卡进行编码(而不使用CPU的核芯显卡 “Intel QuickSync” 进行编码)。

之后来到 “Configuration - NVIDIA NVENC Encoder” 选项卡,更改
“Performance preset” 为 "P6" 、 “Two-pass mode” 为 “Full resolution
(slower)” 以提高编码质量。如果出现编码过载(依照任务管理器 - GPU - Video
Encode是否满载判断)或者编码延迟过高(Moonlight性能统计中可看编码延迟,快捷键ctrl + alt + shift + S
)可以适当降低编码质量。
快速应用启动配置
Sunshine默认给出了Desktop和Steam的应用程序配置,这里我以 Steam 和 Forza Horizon 5 为例讲解如何配置应用程序的快速启动
Steam
- “Application Name” 填入 “Steam” (不要在Sunshine中填入任何中文字符,很有可能会导致Moonlight报Error -1错误)
- “Command Preparations” 中填入一条 Undo 命令 “steam -shutdown” 用于在用户退出串流后退出steam,并且勾选 “Run with Admin”。
- “Detached Commands” 加入一条命令 “steam steam://open/bigpicture” 用于以大屏幕模式启动Steam。
- “Detached Commands” 加入一条命令 “steam -tenfoot” 在Steam已启动的情况下切换为大屏幕模式(此命令在当前Steam版本下不可用)。
- “Working Directory” 中填入你的Steam安装目录,如 “C:Files (x86)”。
- 勾选 “Run as administrator”。
- Save保存。
Forza Horzon 5
- “Application Name” 填入 “Forza Horizon 5” (不要在Sunshine中填入任何中文字符,很有可能会导致Moonlight报Error -1错误)
- “Command Preparations” 中填入一条 Undo 命令 “steam -shutdown” 用于在用户退出串流后退出steam,并且勾选 “Run with Admin”。
- “Detached Commands” 加入一条命令 “steam steam://rungameid/1551360” 用于启动该游戏。
- “Working Directory” 中填入你的Steam安装目录,如 “C:Files (x86)”。
- 勾选 “Run as administrator”
- 点击 “Find Cover”,Sunshine将根据填入的 “Application Name” 自动检索目标封面,选择最适合的一个。
- Save保存。

完成后Moonlight中将显示所有已创建的应用。
Moonlight的配置非常简单,且都有汉化这里就不再细讲了。
到这一步应该能够实现最基本的公网串流了,实测在同市环境下网络延迟不超过20ms。
但这套方案还有很多问题需要解决:
- 串流开始后需要手动切换分辨率及刷新率。
- 设备睡眠或关机后无法被唤醒。
- 被串流设备需要保持显示器开启才能串流画面。
下面来一一介绍可行的解决方案。
分辨率及刷新率自动切换
自建分辨率及刷新率(N卡)
Windows系统通常会预设几个常用的分辨率及刷新率,但不一定会给出你拥有的所有设备的分辨率及刷新率。
比如我的手机分辨率是 2400 * 1080 @ 120Hz,笔记本的分辨率是 2560 * 1600 @ 60Hz 这些都不在预设分辨率内,所以需要自建分辨率。
首先打开NVIDIA控制面板,选择 “显示” 选项卡下的 “更改分辨率” ,点击 “自定义” 按钮。

在这里创建两个目标分辨率及刷新率即可。

自动切换插件ResolutionAutomation
Github上有人为Sunshine开发了一款插件名叫ResolutionAutomation,能够在每次串流开始和结束后,自动切换被串流设备的分辨率及刷新率,以适应不同的显示设备。
项目地址:https://github.com/Nonary/ResolutionAutomation
下载后解压到任意位置,以管理员身份运行Install.bat即可。
该插件会在Sunshine中添加一个预备命令,用于执行分辨率变换脚本,最好在Sunshine的Configuration中勾选 “Run as Admin” 以使用管理员权限执行。

设备睡眠和关机唤醒
因为节电或其它种种原因,我们的设备并不会保持永远开机的状态,所以开启设备睡眠和关机唤醒功能是很有必要的。
睡眠唤醒
首先打开 “设备管理器 - 网卡 - 属性 - 电源管理” 勾选 “允许此设备唤醒计算机” 与 “只允许幻数据包唤醒计算机”。

其次开启此功能还需要主板BIOS支持,这里以微星Z690主板为例。

重启电脑,按delete进入BIOS后,按F7进入高级模式,在 “高级 - 唤醒事件设置” 选项卡中开启 “Resume By Intel CNVI”。
设置完成后,可以使用Moonlight自带的Wake on Lan功能实现公网唤醒睡眠中的设备。
关机唤醒
对于关机中的设备唤醒,网上有帖子说只需要关闭Windows的快速启动即可,但我实测没法通过这种方式唤醒,不知道是哪里出现了问题。
且这种方式有个弊端就是要求设备必须是正常关机(S5)才能被唤醒,对于意外断电导致的电脑关机则无能为力。
所以我选择使用智能插座(gosund CP5 PRO)的方式,通过远程控制开关通断的方式唤醒关机状态下的电脑。

这里,依然要进入BIOS,在 “高级 - 电源管理设置” 选项卡中将 “AC电源掉电再来电的状态” 设置为开机即可。
息屏串流
(施工中)等显卡欺骗器到了再写……