- 音视频
【免费下载链接】foundation-sunshine
Sunshine fork: an enhanced sunshine, a self-hosted game streaming host for Moonlight with HDR10/HDR Vivid, virtual displays, advanced audio, optimized encoders, and a modern control panel.
本文以 foundation-sunshine 官方文档 docs/app_examples.md 为主体,结合 src/process.h、src/process.cpp、src/config.cpp 等源码,系统讲解如何在 Sunshine 中添加游戏与应用、配置启动命令、工作目录、分离命令(Detached Commands)与准备命令(Prep Commands)。读完本文,你将掌握跨 Linux / macOS / Windows 三平台的常见应用配置模板、基于环境变量的分辨率/帧率联动方案,以及 Windows 服务模式下命令提权等高级技巧。
并非所有应用都以相同方式启动:有的需要以 URI 协议唤起,有的要求固定工作目录,有的启动后主进程会被更新程序杀死,还有的必须在管理员权限下运行。因此 Sunshine 将应用配置抽象为若干字段,并针对常见场景提供了官方示例。理解这些示例背后的字段语义与执行逻辑,是配置好自托管串流主机、获得"一键开玩"体验的关键。
一、应用配置的核心字段与执行逻辑
在 Sunshine 中,一个应用条目由以下核心字段组成(对应 src/process.h 中proc_app_t的定义):
| 字段 | 含义 | 备注 |
|---|---|---|
name | 应用名称 | 显示在 Moonlight 客户端与 Web UI 中 |
cmd | 主命令 | 应用的启动命令,可含参数 |
detached | 分离命令列表 | 由 Sunshine 启动但脱离其生命周期管理,见下文 |
working-dir | 工作目录 | 部分游戏必须设置才能正常运行 |
elevated | 是否以管理员权限启动 | 仅 Windows 服务模式有效,值为字符串"true"/"false" |
image-path | 应用图标/封面 | 留空则使用默认图标 |
output | 日志文件路径 | 可用来收集应用输出日志,排查启动失败 |
prep-cmd | 准备命令数组 | 每个元素含do(启动前执行)与undo(退出后执行) |
exclude-global-prep-cmd | 是否跳过全局准备命令 | 字符串"true"/"false" |
原文档特别提醒两点:
- 示例中未展示的字段一律留空。你可以通过
image-path字段为应用添加封面图,通过output字段指定日志文件,进一步提升使用体验。 - 当未指定
working-dir时,工作目录默认为目标应用可执行文件所在的文件夹。这一默认行为对应 src/process.cpp 的find_working_directory():它从命令中解析出可执行文件路径,并取其父目录作为工作目录。
prep-cmd的执行时机由 src/process.cpp 控制:应用启动前按顺序执行每个do命令,应用退出后执行对应undo命令;若cmd为空而仅配置detached,则只启动分离命令而不进行生命周期托管。这一机制是下文"分辨率切换"等场景的基础。
二、通用示例(Common Examples)
2.1 Desktop:最简单的桌面串流
| 字段 | 值 |
|---|---|
| Application Name | Desktop |
| Image | desktop.png |
这是最基础的配置:应用名称为Desktop,配上一张封面图(src_assets/common/assets目录下的desktop.png),命令字段留空。Sunshine 会把它当作"直接串流当前桌面"的入口,即不做任何额外启动操作,直接进入桌面画面。
2.2 Steam Big Picture:三平台的分离命令写法
Steam 启动后会先运行自更新进程,随后杀掉最初的启动进程。如果按普通cmd托管,Sunshine 会误判应用已退出。因此必须使用detached(分离命令),让命令脱离 Sunshine 的生命周期管理,对应 src/process.h 注释中"commands detached from Sunshine"的说明:
| 平台 | 字段 | 值 |
|---|---|---|
| Linux | Application Name | Steam Big Picture |
| Linux | Detached Commands | setsid steam steam://open/bigpicture |
| Linux | Image | steam.png |
| macOS | Application Name | Steam Big Picture |
| macOS | Detached Commands | open steam steam://open/bigpicture |
| macOS | Image | steam.png |
| Windows | Application Name | Steam Big Picture |
| Windows | Detached Commands | steam://open/bigpicture |
| Windows | Image | steam.png |
要点解析:
- Linux 使用
setsid让 Steam 脱离当前会话,避免串流进程树清理误杀 Steam; - macOS 用
open唤起应用,这是 macOS 启动 GUI 应用的标准方式; - Windows 直接用
steam://open/bigpicture协议 URI 唤起 Big Picture 模式; detached命令的启动在 src/process.cpp 中实现,日志会输出Spawning [...] in [...],便于确认命令确实被发起。
2.3 Epic 游戏商店游戏:URI 与二进制两种启动路径
官方指出:使用 URI 方法在不同游戏之间的一致性最好,因为它不依赖具体安装路径。
URI 方式(Windows)
| 字段 | 值 |
|---|---|
| Application Name | Surviving Mars |
| Commands | com.epicgames.launcher://apps/d759128018124dcabb1fbee9bb28e178%3A20729b9176c241f0b617c5723e70ec2d%3AOvenbird?action=launch&silent=true |
该 URI 由三部分组成:游戏 ID(d759128018124dcabb1fbee9bb28e178)、可选的安装 ID(20729b9176c241f0b617c5723e70ec2d)以及应用名Ovenbird,三者用%3A(即冒号的 URL 编码)连接,action=launch&silent=true表示静默启动。实际使用时可到 Epic 游戏目录的.egstore文件中找到对应 ID 替换。
二进制方式(带工作目录,Windows)
| 字段 | 值 |
|---|---|
| Application Name | Surviving Mars |
| Command | MarsEpic.exe |
| Working Directory | "C:\Program Files\Epic Games\SurvivingMars" |
命令只写可执行文件名,配合引号包裹的完整工作目录,让进程在正确的目录下启动。注意 Windows 路径中的反斜杠需按 JSON 转义规则书写。
二进制方式(不带工作目录,Windows)
| 字段 | 值 |
|---|---|
| Application Name | Surviving Mars |
| Command | "C:\Program Files\Epic Games\SurvivingMars\MarsEpic.exe" |
命令直接给出带完整路径的可执行文件,Sunshine 会自动将工作目录推导为该 exe 所在目录(见 src/process.cpp 的find_working_directory)。两种写法都能启动游戏,区别仅在于工作目录的显式与隐式。
2.4 Steam 游戏:同样优先推荐 URI
URI 方式(三平台)
| 平台 | 字段 | 值 |
|---|---|---|
| Linux | Application Name | Surviving Mars |
| Linux | Detached Commands | setsid steam steam://rungameid/464920 |
| macOS | Application Name | Surviving Mars |
| macOS | Detached Commands | open steam://rungameid/464920 |
| Windows | Application Name | Surviving Mars |
| Windows | Detached Commands | steam://rungameid/464920 |
464920是《Surviving Mars》的 Steam AppID。使用steam://rungameid/<AppID>协议可绕过安装路径差异,是最稳的 Steam 游戏启动方式;Steam 主进程同样是"启动即自更新"型程序,因此统一走detached。
二进制方式(带工作目录,三平台)
| 平台 | 字段 | 值 |
|---|---|---|
| Linux | Application Name | Surviving Mars |
| Linux | Command | MarsSteam |
| Linux | Working Directory | ~/.steam/steam/SteamApps/common/Survivng Mars |
| macOS | Application Name | Surviving Mars |
| macOS | Command | MarsSteam |
| macOS | Working Directory | ~/.steam/steam/SteamApps/common/Survivng Mars |
| Windows | Application Name | Surviving Mars |
| Windows | Command | MarsSteam.exe |
| Windows | Working Directory | "C:\Program Files (x86)\Steam\steamapps\common\Surviving Mars" |
Linux/macOS 下工作目录中的~会被展开,Windows 下则需使用引号包裹的完整绝对路径(注意官方文档中Survivng为原样例拼写,实际请以你机器上的目录名为准)。
二进制方式(不带工作目录,三平台)
| 平台 | 字段 | 值 |
|---|---|---|
| Linux | Application Name | Surviving Mars |
| Linux | Command | ~/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam |
| macOS | Application Name | Surviving Mars |
| macOS | Command | ~/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam |
| Windows | Application Name | Surviving Mars |
| Windows | Command | "C:\Program Files (x86)\Steam\steamapps\common\Surviving Mars\MarsSteam.exe" |
直接给出完整可执行路径,工作目录自动推导为其所在目录。此方式下若游戏依赖 CWD 加载资源,可能出现资源读取失败,这也是官方推荐 URI 方案的原因之一。
三、Prep Commands:分辨率与刷新率联动切换
Prep Commands 的核心价值:在串流会话开始前,把主机显示器切换到与客户端匹配的分辨率/刷新率;会话结束后还原。Sunshine 会在启动应用前注入客户端参数环境变量,供 Prep 命令读取:
| 环境变量 | 含义 | 注入位置 |
|---|---|---|
SUNSHINE_CLIENT_WIDTH | 客户端请求的宽度(像素) | src/nvhttp.cpp、src/process.cpp |
SUNSHINE_CLIENT_HEIGHT | 客户端请求的高度(像素) | 同上 |
SUNSHINE_CLIENT_FPS | 客户端请求的帧率 | 同上 |
这三个变量在会话建立时由服务端根据客户端分辨率协商结果写入子进程环境,因此do/undo命令中可以直接${SUNSHINE_CLIENT_WIDTH}形式引用。
3.1 Linux X11(xrandr)
| Prep Step | Command |
|---|---|
| Do | sh -c "xrandr --output HDMI-1 --mode ${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} --rate ${SUNSHINE_CLIENT_FPS}" |
| Undo | xrandr --output HDMI-1 --mode 3840x2160 --rate 120 |
官方提示:上述命令仅在对应 mode 已存在时有效。macOS 与 iOS 客户端使用非标准分辨率,通常需要先创建新 mode。可将Do命令替换为自定义脚本:
bash -c "${HOME}/scripts/set-custom-res.sh \"${SUNSHINE_CLIENT_WIDTH}\" \"${SUNSHINE_CLIENT_HEIGHT}\" \"${SUNSHINE_CLIENT_FPS}\""set-custom-res.sh内容如下:
#!/bin/bash set -e # Get params and set any defaults width=${1:-1920} height=${2:-1080} refresh_rate=${3:-60} # You may need to adjust the scaling differently so the UI/text isn't too small / big scale=${4:-0.55} # Get the name of the active display display_output=$(xrandr | grep " connected" | awk '{ print $1 }') # Get the modeline info from the 2nd row in the cvt output modeline=$(cvt ${width} ${height} ${refresh_rate} | awk 'FNR == 2') xrandr_mode_str=${modeline//Modeline \"*\" /} mode_alias="${width}x${height}" echo "xrandr setting new mode ${mode_alias} ${xrandr_mode_str}" xrandr --newmode ${mode_alias} ${xrandr_mode_str} xrandr --addmode ${display_output} ${mode_alias} # Reset scaling xrandr --output ${display_output} --scale 1 # Apply new xrandr mode xrandr --output ${display_output} --primary --mode ${mode_alias} --pos 0x0 --rotate normal --scale ${scale} # Optional reset your wallpaper to fit to new resolution # xwallpaper --zoom /path/to/wallpaper.png脚本流程:先用cvt依据目标宽高与刷新率生成 modeline,再xrandr --newmode注册、--addmode绑定到当前活动显示器,最后应用该 mode 并按需缩放。脚本第 4 个参数scale默认0.55,用于在分辨率不匹配时缩放画面,避免 UI/文字过大或过小。
3.2 Linux Wayland(wlr-xrandr)
| Prep Step | Command |
|---|---|
| Do | sh -c "wlr-xrandr --output HDMI-1 --mode \"${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}Hz\"" |
| Undo | wlr-xrandr --output HDMI-1 --mode 3840x2160@120Hz |
官方明确限制:wlr-xrandr仅适用于 wlroots 系合成器(如 Sway、Hyprland、River 等),其他 Wayland 合成器不受支持。注意其 mode 语法为宽x高@刷新率Hz,与 xrandr 的--rate参数不同。
3.3 GNOME(Wayland 与 X11)
| Prep Step | Command |
|---|---|
| Do | sh -c "xrandr --output HDMI-1 --mode ${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} --rate ${SUNSHINE_CLIENT_FPS}" |
| Undo | xrandr --output HDMI-1 --mode 3840x2160 --rate 120 |
以上命令在X11 会话下有效,但 GNOME Wayland 会话下xrandr无法工作,需用gnome-randr.py脚本替代——它是 xrandr 语法的即插即用替代品。可将脚本保存到/usr/local/bin并赋予可执行权限后直接替换命令中的xrandr。
3.4 KDE Plasma(Wayland 与 X11)
| Prep Step | Command |
|---|---|
| Do | sh -c "kscreen-doctor output.HDMI-A-1.mode.${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}" |
| Undo | kscreen-doctor output.HDMI-A-1.mode.3840x2160@120 |
KDE 使用kscreen-doctor工具,语法为output.<输出名>.mode.<宽x高@刷新率>,注意输出名是HDMI-A-1(带-A后缀),与 xrandr 的HDMI-1命名不同。
3.5 NVIDIA 显卡(nvidia-settings)
| Prep Step | Command |
|---|---|
| Do | sh -c "${HOME}/scripts/set-custom-res.sh ${SUNSHINE_CLIENT_WIDTH} ${SUNSHINE_CLIENT_HEIGHT}" |
| Undo | sh -c "${HOME}/scripts/set-custom-res.sh 3840 2160" |
set-custom-res.sh内容:
#!/bin/bash set -e # Get params and set any defaults width=${1:-1920} height=${2:-1080} output=${3:-HDMI-1} nvidia-settings -a CurrentMetaMode="${output}: nvidia-auto-select { ViewPortIn=${width}x${height}, ViewPortOut=${width}x${height}+0+0 }"原理:通过nvidia-settings -a CurrentMetaMode直接设置当前 MetaMode,ViewPortIn控制分辨率采样、ViewPortOut控制输出大小。若驱动未加载或 X 配置不使用 MetaMode,此命令可能无效。
3.6 macOS(displayplacer)
displayplacer是第三方分辨率切换工具。使用前需先获取screenId(可运行displayplacer list查询),再将示例中的<screenId>替换为实际值:
| Prep Step | Command |
|---|---|
| Do | displayplacer "id:<screenId> res:1920x1080 hz:60 scaling:on origin:(0,0) degree:0" |
| Undo | displayplacer "id:<screenId> res:3840x2160 hz:120 scaling:on origin:(0,0) degree:0" |
参数含义:res分辨率、hz刷新率、scaling:on开启 HiDPI 缩放、origin屏幕位置、degree旋转角度。它支持一次性配置多显示器,用+分隔多段描述。
3.7 Windows(QRes)
QRes 是 Windows 下的分辨率/刷新率切换命令行工具:
| Prep Step | Command |
|---|---|
| Do | cmd /C FullPath\qres.exe /x:%SUNSHINE_CLIENT_WIDTH% /y:%SUNSHINE_CLIENT_HEIGHT% /r:%SUNSHINE_CLIENT_FPS% |
| Undo | cmd /C FullPath\qres.exe /x:3840 /y:2160 /r:120 |
Windows 环境变量引用语法为%VAR%(而非 Linux 的$VAR),且需用cmd /C包裹。FullPath请替换为 qres.exe 的实际安装路径。除 QRes 外,Windows 平台也可考虑结合display_vdd/ 虚拟显示器方案实现分辨率跟随(见 src/platform/windows/display_vdd.cpp)。
四、附加注意事项(Additional Considerations)
4.1 Linux(Flatpak)环境
由于 Flatpak 包运行在沙箱环境中,默认无法访问宿主机,因此 Sunshine 的 Flatpak 版本要求所有命令以flatpak-spawn --host作为前缀,例如:
flatpak-spawn --host setsid steam steam://open/bigpictureflatpak-spawn --host会在宿主机上下文中执行后续命令,从而突破沙箱限制调用宿主机的显示服务器与游戏进程。
4.2 Windows:命令提权(Elevated)
如果你以服务方式安装 Sunshine(默认行为),可以指定命令是否以管理员权限运行。在 Web UI 中勾选 elevated 选项,或在 JSON 配置中设置elevated字段即可。该选项同时适用于prep-cmd与普通命令,会以当前用户身份启动进程且不弹出 UAC 提示。
官方特别提醒:JSON 中必须将
"true"/"false"写成字符串值,而不是大多数 JSON 中惯用的布尔值true/false。这对应 src/config.cpp 中elevated的解析逻辑。
完整示例(如反作弊需要管理员权限的游戏):
{ "name": "Game With AntiCheat that Requires Admin", "output": "", "cmd": "ping 127.0.0.1", "exclude-global-prep-cmd": "false", "elevated": "true", "prep-cmd": [ { "do": "powershell.exe -command \"Start-Streaming\"", "undo": "powershell.exe -command \"Stop-Streaming\"", "elevated": "false" } ], "image-path": "" }要点拆解:
- 顶层
elevated: "true":主命令以管理员权限启动; exclude-global-prep-cmd: "false":不排除全局 Prep 命令,即全局 prep 与条目级 prep 都会执行;prep-cmd数组内每项含do/undo与各自的elevated,此处 prep 以普通权限运行;output留空字符串表示不写日志;image-path留空表示使用默认封面;- 该 JSON 结构由 src/config.cpp 解析:支持
detached、working-dir、elevated、prep-cmd(含do/undo/elevated)、menu等节点,其中working-dir会先做环境变量展开并剥离多余引号。
4.3 源码侧的行为佐证
上述字段并非仅在文档中存在,执行逻辑均可在 src/process.cpp 中验证:
- 工作目录兜底:
working_dir未配置时,find_working_directory 从命令解析可执行文件所在目录;do、undo、detached命令统一复用该逻辑(见 src/process.cpp); - 分离命令:
detached命令经platf::run_command(_app.elevated, true, ...)启动,属于"发射后不管"模式(src/process.cpp); - 优雅退出兜底:若应用在启动后 5 秒内自行退出,Sunshine 会将其视为 detached 命令处理,不判定为启动失败(src/process.cpp),这正是 Steam 类"自更新后退出首进程"应用能正常工作的另一重保障;
- 环境变量注入:
SUNSHINE_CLIENT_WIDTH/HEIGHT/FPS在会话启动时写入应用环境(src/process.cpp),供所有do/undo/cmd命令引用。
五、总结:选择配置策略的决策要点
| 场景 | 推荐方案 |
|---|---|
| 直接串流桌面 | Desktop+ 封面图,命令留空 |
| Steam / Steam 游戏 | steam://...URI + Detached Commands,跨平台一致 |
| Epic 游戏 | com.epicgames.launcher://...URI 优先,其次二进制 + Working Directory |
| 客户端分辨率与主机不一致 | 按桌面环境选择对应 Prep Commands(xrandr / wlr-xrandr / kscreen-doctor / displayplacer / QRes) |
| 非标准分辨率客户端(macOS/iOS) | 使用set-custom-res.sh动态创建 mode 并配合缩放 |
| Flatpak 安装的 Sunshine | 所有命令加flatpak-spawn --host前缀 |
| Windows 服务模式 + 反作弊游戏 | 顶层"elevated": "true",prep 按需独立设置 |
掌握这些模板后,你可以直接在 Sunshine Web UI 的应用编辑页逐一填写字段,也可以参照 docs/configuration.md 了解配置文件的整体结构,再结合 src_assets/linux/assets/apps.json 等平台默认应用清单比对字段格式。所有示例均以"最小可运行"为原则——先让游戏跑起来,再逐步补充封面、日志与分辨率联动,即可获得完整的 Moonlight 串流体验。
- 音视频
【免费下载链接】foundation-sunshine
Sunshine fork: an enhanced sunshine, a self-hosted game streaming host for Moonlight with HDR10/HDR Vivid, virtual displays, advanced audio, optimized encoders, and a modern control panel.
相关推荐
大麦抢票自动化完整指南:三步搭建你的抢票脚本
大麦抢票自动化完整指南:三步搭建你的抢票脚本 大麦抢票自动化系统 ticket purchase 是一款基于 Selenium 和 Appium 的开源工具,覆
GUI 自动化RPASunshine配置完全指南:从入门到精通
Sunshine是一款开源的游戏串流服务器软件,它能够将你的游戏主机或高性能PC的游戏画面通过网络实时传输到其他设备上。无论你是在客厅、卧室还是移动设备上,都可
音视频后端Create T3 App 应用部署到 Netlify:从 netlify.toml 配置到 Dashboard 与 CLI 的完整实战指南
Create T3 App 应用部署到 Netlify:从 netlify.toml 配置到 Dashboard 与 CLI 的完整实战指南 本指南以官方文档《
开发工具CLI代码生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考