Automatically switches the Preferred Codec in Virtual Desktop Streamer on a timer silently, without bringing the Streamer settings window to the foreground.
Prefer no injection? A self-contained PowerShell variant that drives the Streamer UI through Windows UI Automation lives on the
uia-powershellbranch.
There's a known issue on Meta headsets where streaming FPS drops after roughly 20–30 minutes of continuous play. Changing the codec forces the encode pipeline to reinitialize, which clears the drop and restores smooth frames.
Doing that by hand every half hour sucks, or is just not feasible for sim racing. This tool automates the workaround: it toggles between two codecs (or rotates a list) on an interval, so the stream resets on its own before the slowdown sets in. The default interval is 25 minutes; if you still see drops (some people experience at like 15 minutes?) lower it. It's a workaround until Meta fixes the garbage that is the Quest OS.
The rotator sets the codec from inside the Streamer process, writing the same live managed setting the Streamer UI itself uses:
VirtualDesktop.Streamer.StreamerSettings.Default.PreferredCodec
Because it sets the live setting directly, the switch takes effect immediately and the Streamer window never has to come to the foreground. Each switch:
VirtualDesktopSwitcher.exeinjectsVdCodecPayload.dllintoVirtualDesktop.Streamer.exe(via EasyHook).- The payload loads
VdCodecWorker.dllinto Streamer's default AppDomain. - The worker reads or sets
StreamerSettings.Default.PreferredCodecand writes the result back to the rotator.
This in-process approach is resilient across Streamer versions as long as that
managed setting path stays stable. Tested against Virtual Desktop Streamer
1.34.18 with EasyHook 2.7.7097.
- Windows (x64)
- Virtual Desktop Streamer installed, and running or startable
- The rotator must run at the same elevation level as the Streamer
Started with Windows? If Virtual Desktop Streamer launched automatically at sign-in, the rotator may not be able to reach it. Fully exit the Streamer (tray icon → Exit) and reopen it manually before running the rotator.
Heads up: because this uses process injection, antivirus or SmartScreen may flag unsigned builds. If you'd rather not inject at all, use the UI Automation fork.
Download a release, unzip it, and run the executable from that folder:
.\VirtualDesktopSwitcher.exeWith no codec arguments, it reads the current codec and opens a small popup
asking which different codec to toggle with, whether to beep before timer
switches, and how many minutes to wait
between switches (default 25, range 1–10080).
Prefer to build it yourself? See Building from source.
# Interactive setup, but start the timer at 15 minutes
.\VirtualDesktopSwitcher.exe --interval-minutes 15
# Explicit toggle pair on a 25-minute timer
.\VirtualDesktopSwitcher.exe --codecs HEVC10bit,HEVC --interval-minutes 25
# Beep during the final 5 seconds before each timer switch
.\VirtualDesktopSwitcher.exe --codecs HEVC10bit,HEVC --interval-minutes 25 --beep-warning
# Keep H.264+ active, briefly switching to H.264 to reset the stream every 25 minutes
.\VirtualDesktopSwitcher.exe --codecs H264Plus,H264 --interval-minutes 25 --switch-back
# Same, but stay on H.264 for 500 ms before switching back
.\VirtualDesktopSwitcher.exe --codecs H264Plus,H264 --interval-minutes 25 --switch-back --switch-back-delay-ms 500
# Switch once and exit
.\VirtualDesktopSwitcher.exe --codecs HEVC10bit,HEVC --once
# Switch immediately, then keep rotating on the timer
.\VirtualDesktopSwitcher.exe --codecs HEVC10bit,HEVC --switch-immediately
# Set one exact codec and exit
.\VirtualDesktopSwitcher.exe --target-codec HEVC10bit
# Show help
.\VirtualDesktopSwitcher.exe --help| Option | Description |
|---|---|
--codecs <list> |
Comma-separated codec rotation list. Skips the popup. |
--interval-minutes <n> |
Minutes between switches. Default 25, range 1–10080. |
--beep-warning |
Beep during the final 5 seconds before each timer switch. |
--no-beep-warning |
Keep timer switches silent. Default. |
--target-codec <codec> |
Set one exact codec and exit. |
--once |
Switch to the next codec once and exit. |
--switch-immediately |
Switch immediately before entering the timer loop. |
--switch-back |
Treat the first of exactly two codecs as preferred. At each interval, switch to the second codec, wait for the switch-back delay, and restore the first. The preferred codec is also restored when the tool starts. |
--switch-back-delay-ms <n> |
Milliseconds to stay on the temporary codec before restoring the preferred one. Default 50, range 0–60000. |
--streamer-path <path> |
Path to VirtualDesktop.Streamer.exe (used to launch it if not running). |
--timeout-seconds <n> |
Helper timeout in seconds. Default 15, range 1–300. |
Automatic, H264, H264Plus, HEVC, HEVC10bit, AV110bit
The interactive popup hides the currently selected codec, since the toggle target must differ from the current selection. Some GPUs or headsets do not support every codec.
With --switch-back, specify exactly two codecs. The first is the preferred
codec and the second is only used temporarily to reset the stream. For example,
--codecs H264Plus,H264 --switch-back keeps H.264+ selected between resets.
The interactive popup offers the same behavior: check Switch back to, pick
the codec to keep (it defaults to the current one), and pick the delay in
milliseconds.
Generated binaries are intentionally kept out of git. The build script downloads EasyHook from NuGet and compiles everything from source, no .NET SDK required, just the .NET Framework compiler that ships with Windows.
powershell -NoProfile -ExecutionPolicy Bypass -File .\build.ps1 -PackageThe script:
- downloads pinned EasyHook
2.7.7097from NuGet - compiles the .NET Framework x64 executable and helper DLLs using
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe - writes the release folder under
dist\ - writes
artifacts\VirtualDesktopSwitcher.zipwhen-Packageis passed
A packaged release contains:
VirtualDesktopSwitcher.exe VdCodecPayload.dll VdCodecWorker.dll
EasyHook.dll EasyHook64.dll EasyLoad64.dll EasyHook64Svc.exe
README.md LICENSE THIRD-PARTY-NOTICES.md
src\VdCodecRotator\Program.cs CLI, timer loop, injection client
src\VdCodecRotator.Payload\PayloadEntryPoint.cs EasyHook entry point
src\VdCodecRotator.Worker\StreamerCodecWorker.cs reads/sets the live setting
build.ps1 builds and packages the release
test-package.ps1 verifies the packaged release
.github\workflows\ CI build and tagged releases
- This project is not affiliated with Virtual Desktop, Inc.
- The selected toggle codec only needs to be different from the current one.
- Release packages bundle third-party notices for EasyHook and UDIS86 in
THIRD-PARTY-NOTICES.md.
MIT. See LICENSE.