news 2026/9/9 12:38:02

Sunshine 应用添加实战指南:从桌面到游戏启动的配置示例与命令体系详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Sunshine 应用添加实战指南:从桌面到游戏启动的配置示例与命令体系详解

Sunshine 应用添加实战指南:从桌面到游戏启动的配置示例与命令体系详解

【免费下载链接】SunshineSelf-hosted game stream host for Moonlight.项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine

本文档是给 Moonlight 客户端用户添加可串流应用(Application)的配置实战指南,围绕 Sunshine 仓库中 docs/app_examples.md 的核心示例展开。读者在 Web UI 的 Applications(应用)管理页添加条目时,将掌握桌面直连、Steam / Epic 启动器 URI 与二进制三种启动方式,以及针对不同桌面环境与显卡的分辨率切换 Prep Command(预备命令)写法,并理解各字段在 src/process.cpp 中的实际执行语义。

目录

  1. 理解应用配置的核心概念
  2. 通用示例:桌面与 Steam Big Picture
  3. 游戏启动器示例:Epic 与 Steam 游戏
  4. Prep Commands:分辨率与刷新率切换
  5. 附加考虑事项
  6. 总结与进一步阅读

一、理解应用配置的核心概念

1.1 为什么要「逐应用」配置

并非所有应用都以相同的方式启动:桌面环境、Steam 自带自更新进程、Epic 启动器需要通过 URL Scheme 唤醒游戏、有的游戏二进制必须带工作目录运行。Sunshine 因此在应用条目中提供了若干灵活字段,从而让主机的输出行为(分辨率、刷新率、HDR)与「应用是否仍在运行」的判定完全可控。

1.2 需要理解的关键字段

在 src/confighttp.cpp 的saveApp接口注释中,Sunshine 完整定义了应用条目的 JSON 结构,字段说明如下:

字段类型含义
name字符串应用显示名(Application Name)
output字符串日志输出文件路径(Log Output Path)
cmd字符串应用启动命令(Command)。为空表示启动桌面(Desktop)
index整数保存位置索引,-1表示新建,更新已有应用时传入其当前索引
exclude-global-prep-cmd布尔是否跳过 Sunshine 配置文件中global_prep_cmd定义的所有全局预备命令(见 docs/configuration.md 的global_prep_cmd小节)
elevated布尔该应用命令是否以管理员权限启动
auto-detach布尔应用启动后 5 秒内即优雅退出时,是否将其视为脱离型(detached)命令继续串流
wait-all布尔是否等待整个进程组退出(而非只等待初始进程)才算应用结束
exit-timeout整数关闭应用时,向进程组发送终止信号后等待的秒数
prep-cmd数组预备命令数组,每项含do(启动前执行)、undo(应用退出后执行)与可选的elevated
detached数组需要分离式启动(不阻塞应用运行状态判定)的命令,每项为一个命令字符串
image-path字符串应用图标路径,必须是 png 文件(可填desktop.pngsteam.png等仓库内置图标)
working-dir字符串应用工作目录,留空时默认指向目标程序所在目录

1.3 默认工作目录与「空命令 = 桌面」的底层逻辑

原文给出了两条重要约定,均可在源码中得到印证:

  • Working Directory 缺省时,Sunshine 默认将其设置为目标应用所在目录。在 src/process.cpp 中,无论是do/undo预备命令(第 224-226 行)还是 detached 命令(第 253-255 行)、主cmd(第 269-271 行),都执行了同一逻辑:_app.working_dir.empty() ? find_working_directory(cmd, _env) : path(_app.working_dir)
  • cmd留空时 Sunshine 不会启动任何进程,而是进入「桌面占位」模式placebo = true,见 src/process.cpp),此时串流目标是整个桌面,应用持续「运行」直到客户端断开。

此外,Sunshine 还会在启动应用时向子进程注入一组SUNSHINE_*环境变量(src/process.cpp),包括:

  • SUNSHINE_APP_IDSUNSHINE_APP_NAME:当前应用标识
  • SUNSHINE_CLIENT_NAME:客户端名称
  • SUNSHINE_CLIENT_WIDTHSUNSHINE_CLIENT_HEIGHTSUNSHINE_CLIENT_FPSSUNSHINE_CLIENT_HDR客户端本次请求的分辨率、帧率与 HDR 开关
  • SUNSHINE_CLIENT_GCMAPSUNSHINE_CLIENT_AUDIO_CONFIGURATION2.0/5.1/7.1)等音频配置

这些环境变量是下文中所有「动态分辨率切换」命令的数据来源。


二、通用示例:桌面与 Steam Big Picture

2.1 Desktop(桌面直连)

当你只想把整个桌面画面串流给 Moonlight 时,添加如下条目(原文的@code{}记号在 Web UI 中即对应相应输入框内容):

字段
Application NameDesktop
Imagedesktop.png

对应的apps.json条目与仓库中预置的 src_assets/linux/assets/apps.json 完全一致:应用名Desktop、无cmd,图片为desktop.png。该示例文件同时给出了一个「Low Res Desktop」变体,用prep-cmd在启动前把显示器切到 1920x1080、退出后还原到 1920x1200,可以作为最简单的 Prep Command 参考:

{ "name": "Low Res Desktop", "image-path": "desktop.png", "prep-cmd": [ { "do": "xrandr --output HDMI-1 --mode 1920x1080", "undo": "xrandr --output HDMI-1 --mode 1920x1200" } ] }

2.2 Steam Big Picture(大屏模式)

Steam 启动后其主进程会被自更新进程替换并退出,因此必须以 detached(分离式)命令启动,并用prep-cmdundo负责在串流结束后关闭大屏模式。各平台字段如下:

平台Application NameCommand Preparations → UndoDetached Commands
FreeBSD / LinuxSteam Big Picturesetsid steam steam://close/bigpicturesetsid steam steam://open/bigpicture
macOSSteam Big Pictureopen steam://close/bigpictureopen steam://open/bigpicture
WindowsSteam Big Picturesteam://close/bigpicturesteam://open/bigpicture

原仓库示例 src_assets/linux/assets/apps.json 中的 Steam Big Picture 条目即采用此写法,image-pathsteam.png

{ "name": "Steam Big Picture", "detached": [ "setsid steam steam://open/bigpicture" ], "prep-cmd": [ { "do": "", "undo": "setsid steam steam://close/bigpicture" } ], "image-path": "steam.png" }

理解这一结构的代码语义:在 src/process.cpp 中,detached数组中的每条命令都会通过run_command启动后立即调用child.detach()脱离管理,主进程是否存活不会影响串流会话;而prep-cmd中的do(启动前)与undo(应用退出后)是同步等待执行的。值得注意do留空会被跳过(if (cmd.do_cmd.empty()) continue;,见 src/process.cpp),这正是上面条目中do为空的原因——Steam 的开启动作交给 detached 完成。

[!TIP] 本示例相关的单元测试可在 tests/unit/test_process.cpp 中查看。


三、游戏启动器示例:Epic 与 Steam 游戏

原文强调:使用启动器的 URI 方式最稳定一致,因为它不依赖游戏二进制路径随商店更新而变化。

3.1 Epic Game Store 游戏(以《Surviving Mars》为例)

URI 方式
字段
Application NameSurviving Mars
Commandscom.epicgames.launcher://apps/d759128018124dcabb1fbee9bb28e178%3A20729b9176c241f0b617c5723e70ec2d%3AOvenbird?action=launch&silent=true

其中路径段:AppCatalogItemId:AppItemId(冒号被编码为%3A)由 Epic 启动器为每个游戏生成,可在启动器中获取。

Binary(带工作目录)
字段
Application NameSurviving Mars
CommandMarsEpic.exe
Working Directory"C:\Program Files\Epic Games\SurvivingMars"
Binary(不带工作目录)
字段
Application NameSurviving Mars
Command"C:\Program Files\Epic Games\SurvivingMars\MarsEpic.exe"

后两者对比直观演示了工作目录规则:如果你不填 Working Directory,就必须把 Command 写成完整可执行文件路径,让 Sunshine 依据「默认工作目录 = 程序所在目录」的规则(见上文 src/process.cpp)自行推断;若提供了 Working Directory,则 Command 只需写可执行文件名。

3.2 Steam 游戏(以《Surviving Mars》,Steam AppID 464920 为例)

URI 方式(推荐)
平台Detached Commands
FreeBSD / Linuxsetsid steam steam://rungameid/464920
macOSopen steam://rungameid/464920
Windowssteam://rungameid/464920

所有平台只需填 Detached Commands,无需 prep 命令——和 Steam Big Picture 一样,因为 Steam 主进程自更新的特性要求分离式启动。

Binary(带工作目录)
字段FreeBSD / Linux / macOS 值Windows 值
CommandMarsSteamMarsSteam.exe
Working Directory$(HOME)/.steam/steam/SteamApps/common/Surviving Mars"C:\Program Files (x86)\Steam\steamapps\common\Surviving Mars"

[!NOTE] Linux/macOS 的 Steam 默认库位于$(HOME)/.steam/steam/SteamApps(对应 Windows 的C:\Program Files (x86)\Steam\steamapps),若你安装了额外的 Steam 库,请把路径替换为实际安装目录。原文保留了路径中Survivng Mars的拼写,配置时以你机器上的实际目录名为准。

Binary(不带工作目录)

Command 直接写完整可执行文件路径:

平台Command
FreeBSD / Linux / macOS$(HOME)/.steam/steam/SteamApps/common/Surviving Mars/MarsSteam
Windows"C:\Program Files (x86)\Steam\steamapps\common\Surviving Mars\MarsSteam.exe"

四、Prep Commands:分辨率与刷新率切换

游戏/桌面运行时往往需要把显示器临时切换为客户端请求的分辨率与帧率(尤其是不同步的物理显示与无线串流场景),串流结束后再还原。Sunshine 为此在每个应用条目中提供了prep-cmd数组,并在运行时通过SUNSHINE_CLIENT_WIDTH / HEIGHT / FPS / HDR环境变量(见 src/process.cpp)把客户端请求值传给命令。do命令在应用启动前同步执行,若失败则中止本次启动(返回非零退出码会令proc_t::start()返回 -1,见 src/process.cpp);undo命令在会话结束后执行,用于恢复物理显示器。

以下按平台与显示服务器整理原文给出的完整命令表。

4.1 Linux

X11(通用及 GNOME/X11)
Prep StepCommand
Dosh -c "xrandr --output HDMI-1 --mode ${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} --rate ${SUNSHINE_CLIENT_FPS}"
Undoxrandr --output HDMI-1 --mode 3840x2160 --rate 120

[!TIP] 上述命令仅在 xrandr 模式已存在时有效。macOS 与 iOS 客户端使用非标准分辨率,通常需要先动态创建新模式。可以将do换成调用自定义脚本:

bash -c "${HOME}/scripts/set-custom-res.sh \"${SUNSHINE_CLIENT_WIDTH}\" \"${SUNSHINE_CLIENT_HEIGHT}\" \"${SUNSHINE_CLIENT_FPS}\""

脚本set-custom-res.sh内容如下(可存至~/scripts/chmod +x):

#!/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、创建新模式后施加到当前活动显示器,并通过--scale调节 UI 缩放比例。需要恢复壁纸时可取消最后一行xwallpaper的注释。

Wayland(wlroots 系合成器,如 Hyprland)
Prep StepCommand
Dosh -c "wlr-xrandr --output HDMI-1 --mode \"${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}Hz\""
Undowlr-xrandr --output HDMI-1 --mode 3840x2160@120Hz

[!TIP]wlr-xrandr仅适用于 wlroots 系合成器(Hyprland、Sway 等),其余 Wayland 合成器请使用下列专门方案。

GNOME(Wayland)
Prep StepCommand
Dosh -c "displayconfig-mutter set --connector HDMI-1 --resolution ${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} --refresh-rate ${SUNSHINE_CLIENT_FPS} --hdr ${SUNSHINE_CLIENT_HDR}"
Undodisplayconfig-mutter set --connector HDMI-1 --resolution 3840x2160 --refresh-rate 120 --hdr false
  • 需要先安装displayconfig-mutter工具,相关安装说明请查看其上游仓库。可替代工具包括gnome-randr-rustgnome-randr.py,但两者均已停止维护,且不支持较新 Mutter 的 HDR、VRR 特性,故不推荐。
  • HDR 支持自 GNOME 48 起提供。可用displayconfig-mutter list检查显示器是否支持 HDR;若不支持,请将doundo命令中的--hdr参数一并移除。
KDE Plasma(Wayland 与 X11)
Prep StepCommand
Dosh -c "kscreen-doctor output.HDMI-A-1.mode.${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}"
Undokscreen-doctor output.HDMI-A-1.mode.3840x2160@120

[!CAUTION] X11 与 Wayland 下的显示器名称可能不同,例如同一台显示器在 X11 叫HDMI-A-0,在 Wayland 下可能叫HDMI-A-1,务必根据当前会话类型使用正确的名称。

[!TIP] 用kscreen-doctor -o可列出所有可用显示器及其支持的属性,然后将命令中的HDMI-A-1替换为你要用于 Moonlight 的显示器名。你也可以硬编码显示器模式编号(如kscreen-doctor output.HDMI-A1.mode.0),或用上面的do命令动态采用 Moonlight 客户端请求的分辨率(该值有一定概率不被物理显示器支持)。

NVIDIA
Prep StepCommand
Dosh -c "nvidia-settings -a CurrentMetaMode=\"HDMI-1: nvidia-auto-select { ViewPortIn=${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}, ViewPortOut=${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}+0+0 }\""
Undonvidia-settings -a CurrentMetaMode="HDMI-1: nvidia-auto-select { ViewPortIn=3840x2160, ViewPortOut=3840x2160+0+0 }"

4.2 macOS

使用displayplacer工具切换分辨率(该工具由 jakehilborn 维护,需按其在 GitHub 仓库的说明安装)。

Prep StepCommand
Dosh -c "displayplacer \"id:<screenId> res:${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} hz:${SUNSHINE_CLIENT_FPS} scaling:on origin:(0,0) degree:0\""
Undodisplayplacer "id:<screenId> res:3840x2160 hz:120 scaling:on origin:(0,0) degree:0"

命令中的<screenId>请替换为运行displayplacer list输出的目标显示器 ID。

4.3 Windows

Sunshine 在 Windows 上内置了分辨率/刷新率切换能力(相关实现见 src/platform/windows/display_base.cpp、display_ram.cpp 等文件),并非必须使用第三方工具;若希望用外部工具,可参考 QRes(从 SourceForge 下载):

Prep StepCommand
Docmd /C "FullPath\qres.exe /x:%SUNSHINE_CLIENT_WIDTH% /y:%SUNSHINE_CLIENT_HEIGHT% /r:%SUNSHINE_CLIENT_FPS%"
UndoFullPath\qres.exe /x:3840 /y:2160 /r:120

注意 Windows 下环境变量引用采用%VAR%语法(而非 Unix 的${VAR}),且需把FullPath\qres.exe替换为 QRes 的实际安装路径。


五、附加考虑事项

5.1 Linux(Flatpak 环境)

[!CAUTION] Flatpak 包运行在沙箱中,默认无法访问宿主机。因此Sunshine 的 Flatpak 版本要求所有命令以flatpak-spawn --host作为前缀,例如flatpak-spawn --host xrandr ...,否则命令无法操作宿主的显示输出。

5.2 Windows:提升命令权限(Elevating Commands)

如果将 Sunshine 作为 Windows 服务运行(默认方式),应用可能需要在无 UAC 弹窗的情况下以管理员权限执行命令。可在 Web UI 中勾选相应选项,或在apps.json中为命令添加"elevated": true。该选项同时适用于普通cmd/prep-cmd,进程会以当前登录用户身份被提升启动(对应 src/platform/windows/misc.cpp 中retrieve_users_token的令牌获取逻辑)。完整示例:

{ "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在 src/confighttp.cpp 中被从旧版本常用的字符串"true"/"false"规范化为真正的布尔值(同一处理还覆盖exclude-global-prep-cmdauto-detachwait-all与整数型的exit-timeout);随后在配置解析时被填充为 src/config.h 定义的prep_cmd_t{ do_cmd, undo_cmd, elevated },并最终传入platf::run_command(elevated, ...)执行。

5.3 相关代码路径速查

若想从源码层面验证以上行为,可按下列路径深入:

  • 应用条目的 JSON 完整格式与保存逻辑:src/confighttp.cpp(saveApp
  • prep-cmd结构体定义(do_cmd/undo_cmd/elevated):src/config.h
  • 应用启动时序:prepdo→ detached → 主cmd→ 应用退出后反向执行 prepundo:src/process.cpp 与 src/process.cpp(terminate
  • 客户端请求注入的环境变量(SUNSHINE_CLIENT_*):src/process.cpp
  • auto-detach的 5 秒优雅退出判定:src/process.cpp
  • 仓库内置的应用示例文件:src_assets/linux/assets/apps.json
  • 其它平台内置apps.json:src_assets/macos/assets/apps.json、src_assets/windows/assets/apps.json

六、总结与进一步阅读

本文从「为什么要逐应用配置」出发,介绍了 Sunshine 应用条目的全部核心字段,逐一演示了桌面、Steam Big Picture、Epic 与 Steam 游戏在 URI / 二进制两种启动方式下的完整填法,并系统整理了各桌面环境与显卡在 X11、Wayland、macOS、Windows 下的分辨率切换 Prep Command。需要特别记住的三条规则是:工作目录缺省指向程序所在目录、cmd留空即为桌面直连、Steam 系必须走 detached 启动。结合源码可见这些字段都对应 src/process.cpp 中明确的执行分支,理解后可大幅提升排查启动异常的效率。

关于 Sunshine 全部配置项(含global_prep_cmd等)的完整说明见 docs/configuration.md;本文中命令用到的SUNSHINE_CLIENT_*环境变量的注入逻辑可回溯 src/process.cpp。若需要更多第三方应用案例,可继续阅读 docs/awesome_sunshine.md 社区资源清单。

【免费下载链接】SunshineSelf-hosted game stream host for Moonlight.项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 12:36:56

EV2400刷成MSP430仿真器:固件烧录与调试实战指南

简介&#xff1a;面向MSP430F5529/5528等新型号MCU的EV2400固件刷写资源包&#xff0c;内置三种大小不同但功能一致的固件&#xff0c;最大版本适配F5529&#xff0c;最小版本适配F5528&#xff0c;并附带一块经测试的MSP430F5528开发板PCB文件。开发者可使用UNIFLASH配合EZFET…

作者头像 李华
网站建设 2026/9/9 12:36:53

热流平衡如何决定核聚变等离子体的密度天花板

逼近密度极限时等离子体为何会“漏水”&#xff1a;热流平衡如何决定核聚变的密度天花板在托卡马克装置上泡了这么多年实验&#xff0c;有一个现象我每次看都觉得很微妙&#xff1a;你小心翼翼地往等离子体里加燃料&#xff0c;密度一点一点爬升&#xff0c;眼看着离Greenwald密…

作者头像 李华
网站建设 2026/9/9 12:35:41

Rust轻量级流式编排引擎ruflo:核心抽象、背压机制与实战解析

前几天凌晨两点&#xff0c;线上群突然炸了。Kafka 的 lag 一路飙升&#xff0c;消费者明明在跑&#xff0c;消息就是消费不进去。我盯着监控面板看了半天&#xff0c;最后定位到问题出在流处理框架的配置上——一个字段类型写错了&#xff0c;整个拓扑直接卡死&#xff0c;既没…

作者头像 李华
网站建设 2026/9/9 12:34:03

杭州哪里有上门回收旧电脑?笔记本一体机回收流程

家里闲置的旧笔记本、一体机占地方又没用&#xff0c;想出手却不知道杭州哪里有能上门回收的商家&#xff0c;也不清楚完整的回收流程是怎样的&#xff0c;会不会要自己扛着电脑跑门店、会不会被压价、数据会不会泄露。2026 年杭州本地实体回收品牌万修电脑&#xff0c;提供全品…

作者头像 李华