Rubylight Download 2.2.10
On this page
  1. Defaults worth knowing
  2. Capture and video
  3. Displays and RTSS
  4. Controllers
  5. MoonDeck
  6. Settings for one app or device
  7. Save, reconnect and restart
  8. Multiple instances
  9. Updates
  10. Further reference

Configuration #

Docs · Getting started · Troubleshooting

Configure the current Windows Rust host in the Rubylight console, normally at https://localhost:47990. Open Settings and search by a setting's name or configuration key. Resolution, stream frame rate, bitrate and codec are normally chosen in the client.

Start with the defaults below. Settings imported from an older installation keep their saved values; upgrading does not reset them to these defaults.

Defaults worth knowing #

Setting / key Default What it means
Capture method — capture auto Prefers Windows Graphics Capture (WGC), with Desktop Duplication (DDX) as fallback.
Compute conversion — gpu_compute_conversion true Uses a separate compute queue for supported AMD capture and colour conversion paths.
Encode from GPU memory — wgc_direct_encoder_input true Keeps captured frames on the GPU instead of copying them through system memory.
Encoder — encoder auto Selects an available encoder for the capture GPU.
AMD usage — amd_usage ultralowlatency AMD's lowest-latency preset. The driver also turns on its internal low-latency mode, and the lowest latency for AV1.
AMD quality — amd_quality speed Favours low encoding latency.
Frame pacing — frame_pacing arrival Encodes arriving frames, limited to the requested stream rate.
Video packet pacing — pacing_max_bitrate_kbps 0 Automatic: twice the encoder bitrate on confirmed Wi-Fi or mobile routes; up to 800 Mbps on other routes. PyroWave keeps its separate bandwidth policy.
HEVC / AV1 support — hevc_mode, av1_mode 0 Automatic capability detection; only working profiles are offered.
PyroWave — pyrowave true Offers PyroWave to clients that support it.
Virtual display — virtual_display_mode Windows 11: per_client; Windows 10: disabled A display for each device on Windows 11; a physical monitor on Windows 10. Requires the virtual display driver when enabled.
Virtual display layout — virtual_display_layout exclusive Turns other displays off while the virtual display is used. A Remote Monitor follows it while it streams: exclusive turns the other displays off and makes it primary, the primary layouts make it primary, and it keeps the place the remote monitor layout gives it. Choose Extended to use a remote monitor beside your own.
Physical display preparation — dd_configuration_option verify_only Requires the selected monitor to be active; resolution, refresh and HDR policies are separate.
Display HDR — dd_hdr_option auto Matches the streamed display's HDR state to the stream.
Limit every stream — frame_limiter_enable false Manual limiting is off; virtual-display automatic limiting can still apply.
Limiter — frame_limiter_provider auto Uses RTSS when installed, otherwise the NVIDIA driver where available.
Virtual display refresh — frame_limiter_auto_virtual_framegen legacy Runs the virtual display at twice the stream rate and enables automatic frame limiting.
Update checks — update_check_interval 86400 seconds Checks once a day.
Automatic installation — auto_update false Announces available updates; installation is opt-in.
Include pre-releases — notify_pre_releases false Release candidates are offered only when enabled.

These are defaults for unset keys, not a list of values you must copy into a configuration file.

Capture and video #

Keep Capture method on Automatic and compute conversion enabled for normal use. On supported AMD hardware, the compute path lets capture and colour conversion run alongside graphics work. Unsupported textures can fall back to the graphics path. The internal wgc_compute_copy switch also defaults to true; it is primarily useful for controlled troubleshooting.

The installed service runs WGC through a helper in the signed-in user's session. WGC can fall back to DDX when unavailable. Selecting a particular capture method is useful when investigating a problem; check Logs to see which path actually opened.

H.264, HEVC and AV1 depend on the encoder and client. For hevc_mode and av1_mode, the choices are 0 Automatic, 1 Off, 2 SDR only and 3 SDR and HDR. Restart after changing advertised codec support. There is no 4:4:4 switch: the host offers 4:4:4 for a codec only when the startup check encodes it on a hardware encoder. AMD's encoder makes 4:2:0 only, so an AMD host offers 4:4:4 through PyroWave alone.

For native HDR, enable HDR in the client and use an HDR-capable display and encoder path. Leave Display HDR on Automatic so Rubylight can set the source display appropriately. 10-bit SDR instead of HDR (prefer_sdr_10bit, default false) deliberately keeps the stream in SDR; leave it off when you want HDR. RTX HDR is a separate SDR-to-HDR conversion feature, with its own hardware requirements.

PyroWave needs a compatible client and much more bandwidth than conventional codecs. Desktop and game test scenes on AMD give two warning levels. The floor warns about severe detail loss; the recommendation targets clean pictures in those tests. Passing the floor alone does not mean a clean picture.

Stream Severe-loss floor Recommended
720p60 139 Mbps 277 Mbps
1080p60 187 Mbps 399 Mbps
4K60 747 Mbps 1593 Mbps

These values are rounded up to whole Mbps. Below 1080p the floor/recommendation are 2.5/5 bits per pixel per frame; at 1080p and above they are 1.5/3.2. The smaller desktop's one-pixel text needed more bits per pixel. Rates scale with pixel count and frame rate within each band: halve them at 30 fps, double them at 120 fps. Other sizes are estimates; actual quality depends on text size, textures and the picture. The console stream card uses red below the floor and amber below the recommendation, and the log distinguishes both. The October 12, 2026 Rubylight 2.2.9 validation rechecked these budgets on synthetic desktop and game pictures; it measures decoded quality, not sustained network throughput. Original October 7 method and criteria.

Set the bitrate in Moonlight and leave network headroom for packet overhead and recovery data. The 4K60 recommendation needs more than gigabit Ethernet. Client and host limits still apply: stream setup allows up to 2 Gbps, while the client's runtime /bitrate endpoint caps changes at 500 Mbps. If the client or network cannot carry the recommended rate, use HEVC or AV1. Enabling PyroWave does not force ordinary Moonlight clients to use it. NVIDIA users should use Vibepollo.

A Rubylight client can change the stream's resolution and frame rate without reconnecting, for example when a foldable phone opens its inner screen. The encoder restarts at the new size with a keyframe and pacing follows the new rate; the PC's display keeps its mode and the picture is scaled to fit. stream_reconfigure (default true) turns this off for the host, a device or an app; clients that never ask are unaffected. Control messages describes the request.

VRR is client-negotiated. A VRR request can use a 1000 Hz virtual display when automatic virtual refresh is enabled. That is the host's virtual display rate, not a claim that your TV or monitor refreshes at 1000 Hz. Client and display support still matter.

Packet pacing limits video bursts. With pacing_max_bitrate_kbps = 0, H.264, HEVC and AV1 use twice the negotiated encoder bitrate when Windows identifies the host's route as Wi-Fi or mobile broadband, bounded to 1–800 Mbps. Ethernet, loopback, VPN, Tailscale and unknown routes retain the rc.19 default of 800 Mbps. A known physical Ethernet link caps that at 80% of its reported speed. For virtual Ethernet adapters such as Hyper-V vSwitches, the host tries to resolve the physical adapter through Windows' interface stack. Missing or ambiguous bindings keep the wired default. The host cannot detect a wireless client behind a wired access point from its own Ethernet route.

Set pacing_max_bitrate_kbps to a positive value in kbps to override the automatic policy, including for PyroWave. For example, 120000 paces at 120 Mbps. The existing floor of 110% of the stream bitrate still applies, and a known Ethernet link can lower the limit to 80% of link speed. This changes packet spacing, not the encoded bitrate; reconnect after saving. PyroWave's automatic policy retains 95% of a known Ethernet link, or 1.25 times its per-frame wire demand (at least 110% of the stream bitrate) on other routes, so its high-bandwidth intra frames are not restricted by the conventional-codec default. Measurements and pacing math.

Leave AMF's low-latency mode and AV1 latency mode on Driver default. In the October 12, 2026 Rubylight 2.2.9 property sweep, default ultra-low-latency usage already read back internal low latency for H.264/HEVC and AV1 latency mode 3 on the RX 7900 XT. Explicitly forcing the same settings produced similar timings across three runs, not exact equality or a demonstrated speedup. With Low latency or Transcoding usage, single auto/forced pairs changed the readbacks from off to on and showed mean reductions of 0.30-0.31 ms for HEVC and 1.01-1.37 ms for AV1. These are eight-second synthetic 1440p120/20 Mbps component tests, not full-stream latency measurements. The October 7 audit documents earlier measurements and the RX 9000 HEVC-freeze concern; forcing these settings remains opt-in.

Adaptive quantization (amd_vbaq) is off for H.264 and on for HEVC and AV1 when unset. In the October 12, 2026 Rubylight 2.2.9 settings comparison, explicitly turning H.264 AQ on reduced VMAF in all four cases: by 1.44 and 11.89 points on the two clips at 1440p120/20 Mbps, and by 0.06 and 0.41 at 50 Mbps. Turning AQ off gave mixed HEVC results, while AV1 VMAF rose in all 14 tested cases by 0.0009-0.2301 points in SDR and 0.0051-0.4822 in converted HDR. Those small AV1 gains do not establish a universal visual-quality benefit; the HDR scores also use converted SDR footage. Set AQ to On or Off to compare your own content, or Driver default to leave it to the driver. The October 8 findings remain a separate historical result.

The current default-quality results cover 32 cases; the settings comparison adds 116 alternatives for quality preset, rate control, AQ, usage and high-motion boost. Each case encoded and scored exactly 180 frames, with no minimum VMAF pass threshold. CBR increased p99 frame size in every tested case; its score changes depended on codec and content. Ten high-motion-boost requests completed but lacked effective-setting readback, so their application is unverified. Encode-time deltas use earlier baselines rather than randomized matched trials. HDR rows convert SDR footage with 203-nit white and do not establish native-HDR perceptual quality.

Leave split-frame encoding on Automatic. AMF can split one HEVC or AV1 frame across a Radeon's two encoder engines (amd_split_frame), and the driver decides whether it does. Automatic asks for it only when the GPU has two engines and the driver has it off; On asks whenever there are two engines, and Off disables the property. In the October 12, 2026 Rubylight 2.2.9 sweep, RX 7900 XT readbacks were 1 for Automatic/On and 0 for Off. Identical-input synthetic throughput was similar: for example, two-run means for 4K HEVC were 197.32 / 197.37 / 197.36 FPS respectively. This does not mean every frame had identical timing or prove how the driver used its engines. The sweep completed 708/720 calls; twelve pre-analysis cases failed and remain documented. It did not assess decoded quality. H.264 has no split-frame property; single-engine GPUs get no property write. Historical October 7 measurements remain separate.

AMF rate-control limits are optional. In Settings → Encoders → AMD AMF, the advanced controls below use the client's requested bitrate and frame rate. All default to 0, which leaves the corresponding property to the driver. Reconnect after saving. An unsupported explicit request is reported as an AMF setting error; the effective values appear in the AMF encoder settings log line.

Key Values Meaning
amd_peak_bitrate_ratio 0, or 1–2 Peak bitrate as a multiple of the stream bitrate; the console offers 1×, 1.5× and 2×. This is not an individual-frame cap.
amd_vbv_buffer_frames 0, or 0.5–2 Rate-control buffer in nominal frame budgets. One budget is bitrate divided by frame rate, including fractional rates.
amd_max_frame_size 0, or 1–8 Requested maximum encoded frame size in nominal frame budgets, including recovery keyframes. Uses MaxAUSize for H.264, HevcMaxAUSize for HEVC and Av1MaxCompressedFrameSize for AV1.

These are encoder bit budgets, not extra queued frames or packet-pacing settings. A smaller budget trades picture quality for smaller frames. Intra refresh remains client-negotiated and does not replace an explicit recovery-keyframe request. See the rate-control measurements before changing these controls. NVIDIA users should use Vibepollo.

amd_rc remains vbr_latency by default. For an affected AMD stream, amd_max_frame_size=1 or 2 lets you compare smaller recovery frames against picture quality; 0 restores the driver default. These caps cut the largest recovery frames sharply. They are off by default because they trade picture quality for smaller frames.

Displays and RTSS #

Under Settings → Display, select a physical display or choose a virtual display per device/shared by all devices. Exclusive switches other monitors off; choose Extended to keep the existing desktop active. The primary and isolated variants control where the virtual display sits in that desktop.

Resolution and refresh policies default to auto (dd_resolution_option, dd_refresh_rate_option). Virtual refresh follows the frame-limiting policy unless a manual or device display mode overrides it. To leave a physical monitor's resolution, refresh and HDR unchanged, select Disabled for dd_configuration_option.

A disconnect can leave the app and its display available for reconnection. Enable dd_config_revert_on_disconnect if you want the display configuration restored on disconnect; it defaults to false. Without it, a disconnected device's display is kept while its app runs for dd_paused_virtual_display_timeout_secs (default 7200 seconds; 0 keeps it until the app closes). A client that sends nothing for ping_timeout (default 10000 ms) ends its stream. Maintenance provides display restoration and saved-baseline controls.

Under Settings → Frame limiting:

Controllers #

Settings → Input → Controller type controls which virtual controller games see. Every pad comes from the VHF gamepad driver that the installer brings; no other driver is needed.

gamepad = auto matches each client's controller. PlayStation clients get a DualSense, the only pad with adaptive triggers; it also carries motion, battery, touchpad, lightbar and rumble. A game's trigger effects reach the player only if the client forwards them to a real DualSense. Nintendo clients get a Switch Pro. Other clients get an Xbox Series pad, or a DualSense when they have motion sensors or a touchpad and motion_as_ds4 or touchpad_as_ds4 is enabled. Both preferences default to enabled, so a Steam Deck reporting motion gets a DualSense.

vhf_xbox, vhf_xbox_one, vhf_ds4, vhf_ds5 and vhf_switch give every client that pad: vhf_ds5 a DualSense, vhf_ds4 a DualShock 4 without adaptive triggers. Logs name the profile for each connected controller.

Earlier releases also offered Xbox 360 (x360) and DualShock 4 (ds4) through ViGEmBus. Since rc.25 Rubylight changes those settings to vhf_xbox_one and vhf_ds4 when it loads them, in the host configuration, app and device overrides, and configurations imported from Sunshine, Apollo or Vibepollo. An installed ViGEmBus is no longer used and can be uninstalled.

Steam Deck #

A Steam Deck can reach the host as a real Steam Deck controller: Rubylight serves the Deck's own USB controller (Valve 28de:1205) over USB/IP on the host's loopback address, and usbip-win2 attaches it with its signed driver, so Windows sees a Steam Deck plugged into a USB port. Steam on the host then recognises a Steam Deck and applies the Deck's Steam Input layout, with both trackpads, the gyro, the back grips (L4, R4, L5, R5), the Steam and "…" buttons and rumble. Games see whatever Steam Input makes of it, as on a Deck.

Moonlight passes on the Deck's own controls only when Steam Input is off for Moonlight on the Deck. With it on, Steam on the Deck turns the controls into a virtual pad first: the host still gets a Steam Deck with the buttons, sticks and triggers, but no gyro, trackpads or back grips, because Moonlight never receives them. On the Deck, open Moonlight's controller settings in Steam, choose to disable Steam Input, and reconnect. If the paired device's name says Steam Deck (SteamOS calls it steamdeck) and its controller arrives without a gyro, the stream card says this.

Moonlight sends trackpad touches from builds whose SDL reads the Deck's trackpads (SDL 3).

With the virtual pad (no usbip-win2, or Virtual pad), Moonlight's Steam controller with gyro gets a DualSense:

Setting motion_as_ds4 and touchpad_as_ds4 both off keeps a Deck's virtual pad an Xbox pad, without its gyro and trackpads.

MoonDeck #

MoonDeck works with Rubylight. It launches Steam games from the Steam Deck through Moonlight, with MoonDeck Buddy managing Steam on the host. You only need one host app for MoonDeck; you do not need to add each Steam game to Rubylight.

  1. Install MoonDeck on the Steam Deck and MoonDeck Buddy on the Windows host. Keep Buddy running, pair it through MoonDeck's settings, and pair Moonlight with Rubylight.
  2. In Rubylight's Library, add an app with Name set to MoonDeckStream and Command pointing to "<BuddyInstallDirectory>\bin\MoonDeckStream.exe". Replace <BuddyInstallDirectory> with Buddy's actual installation folder and keep the quotes around the path.
  3. Under the app's Behavior, turn off Keep the stream when a launcher exits within 5 seconds (auto-detach) and save. Wait for every process the app starts (wait-all) can stay enabled. These correspond to the options in MoonDeck's host setup guide.
  4. In Buddy's settings.json, next to its executable on Windows, set sunshine_apps_filepath to the full path of Rubylight's apps.json, then restart Buddy. For a standard installed service, the JSON entry is "sunshine_apps_filepath": "C:\\ProgramData\\Butterpollo\\config\\apps.json". For a portable or custom profile, use apps.json in the active profile folder, unless file_apps points elsewhere. Buddy's automatic lookup looks for Sunshine and can otherwise find the wrong installation or no app list. See Sunshine apps filepath in Buddy configuration.
  5. Select the Rubylight host in MoonDeck and use MoonDeckStream as its host app. The name must match the app saved in Rubylight.

Controls with MoonDeck #

Moonlight carries controller, keyboard and mouse input to Rubylight. MoonDeck launches a separate Steam shortcut for the stream, so configure the running MoonDeck shortcut's controller layout on the Deck; settings on the standalone Moonlight shortcut do not configure it.

For host-side Steam Input with the Deck's own controls, follow the Steam Deck controller setup: install usbip-win2 on the host, use a client that exposes the required controls, and disable client-side Steam Input for the shortcut MoonDeck actually launches. Start Steam on the host before connecting when using Steam Deck controller → Automatic. This mode depends on the client sending raw controls; a working button layout alone does not confirm gyro, trackpad or back-grip passthrough.

If controls do nothing, check the paired device's Controllers permission under Devices and the console's stream warnings. Keyboard and mouse mappings also need their respective device permissions. See input troubleshooting for permissions and the VHF gamepad driver.

Settings for one app or device #

Edit an app in Library or a paired device in Devices to set its display, HDR and other overrides. Leave an override unset to inherit the host configuration.

For general configuration overrides, Rubylight applies host settings → device overrides → app overrides. Only supported stream, input, display and encoder keys are accepted; host-wide network, identity and path settings cannot be overridden per stream.

Display selection has dedicated rules: a device's explicit virtual-display mode takes priority over the app's mode, and its display mode (WIDTHxHEIGHTxREFRESH) overrides the host's resolution/refresh policy. This does not change the frame rate requested for the encoded stream.

Display choice from the client #

A client can choose, for one stream, what the PC's displays do. Rubylight Android sets it per PC under This PC → Display on the PC. The client sends hostDisplay with /launch or /resume:

hostDisplay What the stream gets
exclusive A virtual display, and the PC's other displays switch off for the stream.
extended_primary A virtual display beside the PC's displays, made the primary display so games open on it.
extended A virtual display beside the PC's displays; the primary display stays as it is.
extended_isolated, extended_primary_isolated The isolated layouts of Settings → Display.
physical No virtual display; the stream shows the physical display the host and app settings select.
missing, default or anything else The host decides from its settings, as for an older client.

The choice comes before the host, device and app settings for virtual display mode and layout, including a device's Always use a virtual display. Two cases still get a virtual display after physical: a PC with no active display, and an output that names the virtual display itself. A virtual display needs its driver; without it the stream shows the physical display with a warning, as for any other request. When another stream already holds the display layout, a second stream joins that layout. The layout from before the stream comes back when the stream ends, as with the host's own settings. A display kept for reconnection is reused only when the next launch asks for the same choice, or asks for nothing. Remote Monitor and Remote Input ignore the parameter. Older Rubylight hosts and other hosts ignore it, so Rubylight Android also sends virtualDisplay=1 with the virtual choices, which those hosts honour where they support a virtual display.

Save, reconnect and restart #

Select Save changes to write the configuration. Edits are not saved merely by changing a control or switching categories. Saved stream settings are read when a new stream starts; an existing stream generally keeps its current configuration.

The console shows “Saved. Some changes apply after the host restarts.” Startup settings, including network listeners and advertised codec capabilities, need a restart. Use Restart now after disconnecting: restarting the host disconnects active streams.

For file-based configuration, the file is still named sunshine.conf for compatibility:

Installation Default profile folder
Windows service %ProgramData%\Butterpollo\config
Portable host Existing config folder beside the executable (2.2.6 or later); otherwise %LocalAppData%\ButterpolloRust\config
Explicit profile Folder passed to butterpollo.exe --config-dir <folder>

The format is key = value, one setting per line. Stop the host before editing files directly, then start it again to load them. Prefer the console for ordinary changes; old or unknown keys can be preserved without being implemented by the Rust host.

Multiple instances #

Give each instance its own profile folder and base port. An explicit --config-dir takes precedence over the portable defaults. From the extracted package, run these commands in separate PowerShell windows, one in each intended Windows session:

.\butterpollo.exe --config-dir C:\RubylightProfiles\Seat1 --port 48123
.\butterpollo.exe --config-dir C:\RubylightProfiles\Seat2 --port 48323

The consoles are at https://localhost:48124 and https://localhost:48324. These base ports also keep the instances' streaming ports separate from each other and from the default installed host. To make the port choice persist when using Start Rubylight.exe, save port = 48123 or port = 48323 in the corresponding profile's sunshine.conf. The launcher accepts --config-dir; --port is a host option.

For copied portable packages, create a separate config folder beside each copy of butterpollo.exe and set a different port in each folder's sunshine.conf before launching. Automatic selection of this adjacent folder requires 2.2.6 or later; older packages need an explicit --config-dir. Without an adjacent folder or explicit path, copies running as the same account share the per-user default, including SYSTEM's systemprofile location. Start with fresh profiles for independent identities and pair each instance separately; copying a populated profile also copies its identity and paired devices.

For multiseat use, launch each process in its intended Windows session through your multiseat software, using that session's SYSTEM token if required by your setup. The installer continues to manage one Windows service. Separate-profile startup has been smoke-tested with two simultaneous hosts; simultaneous streaming from different Windows users still needs validation.

Updates #

Automatic checking is enabled; automatic installation is not. Use Maintenance to check manually or start an offered update. Enable Include pre-releases if you want release candidates.

If you opt into Install updates automatically, the installed Windows service waits for one minute without active streams, pending connections, remote-monitor sessions or running host apps. The updater validates the selected installer against the release's size and SHA-256. Portable installations use the release download page instead.

Set update_check_interval = 0 to disable scheduled checks; manual checks remain available.

Further reference #

View this page on GitHub