LLrdc (Low Latency remote desktop) is an entirely web-based, low-latency remote desktop and container solution.
- XFCE4 Desktop in Docker: Runs a full Ubuntu 24.04 and XFCE4 desktop environment inside a reproducible Docker container.
- Web-Based Client: Access your desktop entirely via a modern web browser—no client software required.
- High-Performance Streaming: Leverages WebRTC for ultra-low latency video streaming, with fallback to WebCodecs/WebSockets. Uses variable bitrate (bitrate drops on static screens) with an optional peak bandwidth cap.
LLrdc provides convenient bash scripts to handle all Docker operations easily.
- Docker installed
To build the Docker image, run the included build script from the repository's root directory:
./docker-build.shThis will automatically create a Docker image tagged danchitnis/llrdc:latest. The build process compiles the Go backend and configures the X11/XFCE environment.
Once built, start the container using the run script:
./docker-run.shTo enable GPU acceleration (NVENC) on NVIDIA systems, add the --gpu flag:
./docker-run.sh --gpuThe script will automatically detect and map CUDA/NVCC paths and switch to h264_nvenc encoding for high-performance streaming.
To see verbose debug logs, you can use the following flags:
--debug-ffmpeg: Shows real-time ffmpeg frame rate and encoder reports.--debug-x11: Shows X11 keyboard warnings and XFCE session startup errors.--debug: Enables both ffmpeg and X11 debug logging.--hdpi [percent]or-h [percent]: Enables High DPI scaling for the XFCE desktop. If no percentage is provided, it defaults to200(2x scaling). Example:--hdpi 150for 1.5x scaling.
By default, the server auto-detects your primary IP address for WebRTC. If you have multiple network interfaces (e.g., Tailscale, VPNs, or multiple LANs), you can use the following flags to control which interfaces are used for the stream:
--iface <name>or-i <name>: Only allow WebRTC to use the specified interface (e.g.,eth0).--exclude-iface <name>or-x <name>: Prevent WebRTC from using the specified interface (e.g.,tailscale0).
# Example: Exclude Tailscale and use real IP
./docker-run.sh -x tailscale0Open your browser and navigate to:
http://localhost:8080
You should see your XFCE4 desktop session running and ready for interaction.
LLrdc supports bidirectional clipboard synchronization between the host browser and the remote desktop.
- Keyboard shortcut (Cmd+V / Ctrl+V): Works immediately. When you paste, the browser captures the clipboard text, sends it to the remote, and injects Ctrl+V into the active remote application.
- Context menu paste in remote apps: After pasting once via Cmd+V, the remote clipboard is synced. Subsequent context menu paste operations in remote applications (e.g., mousepad → right-click → Paste) will use the synced text.
Text copied in the remote desktop (e.g., via Ctrl+C in a terminal) is automatically synced to the host browser clipboard within ~1 second.
Clipboard synchronization can be disabled if it impacts performance or is not needed:
- At runtime: Uncheck "Enable Clipboard Sync" in the config panel (Input tab).
- At startup: Set
ENABLE_CLIPBOARD=falseor use--enable-clipboard=false.
When disabled, all clipboard polling, sync, and focus management are turned off.
LLrdc can be configured using command-line flags (when running the binary directly in a custom container) or environment variables (when using docker-run.sh).
The llrdc binary supports the following flags, categorized by their primary use case:
--port: Port for both HTTP and WebRTC UDP (default:8080).--fps: Target frames per second (default:30).--video-codec: Choice ofvp8(default),h264,h264_nvenc,h265,h265_nvenc,av1, orav1_nvenc.--chroma: Chroma subsampling format,420(default) or444. See Chroma 4:4:4 below.--use-gpu: Enable GPU acceleration for NVENC codecs.--use-debug-ffmpeg: Enable verbose FFmpeg logging.--use-debug-x11: Enable verbose X11/XFCE session logging.--display-num: X11 display number inside the container (default:99).--wallpaper: Path to a custom wallpaper image.--webrtc-public-ip: Manually set the public IP for ICE candidates.--webrtc-interfaces: Comma-separated allowlist of network interfaces.--webrtc-exclude-interfaces: Comma-separated blocklist of network interfaces.--enable-clipboard: Enable clipboard synchronization (default:true).
--test-pattern: Run with an FFmpegtestsrcpattern instead of capturing the X11 desktop.--test-minimal-x11: Start a bare X11 session without the full XFCE desktop environment (useful for automated UI tests).
When using docker-run.sh, you can pass these environment variables to override defaults:
PORT=9090 HOST_PORT=9090 FPS=60 VIDEO_CODEC=h264 ./docker-run.sh| Variable | Description | Flag Equivalent |
|---|---|---|
PORT |
Server internal port | --port |
FPS |
Target frames per second | --fps |
VIDEO_CODEC |
Encoder selection | --video-codec |
CHROMA |
Chroma subsampling (420 or 444) |
--chroma |
USE_GPU |
Enable GPU acceleration | --use-gpu |
USE_DEBUG_FFMPEG |
Enable FFmpeg debug logs | --use-debug-ffmpeg |
USE_DEBUG_X11 |
Enable X11 debug logs | --use-debug-x11 |
WEBRTC_PUBLIC_IP |
Public IP override | --webrtc-public-ip |
TEST_PATTERN |
Use FFmpeg test pattern | --test-pattern |
TEST_MINIMAL_X11 |
Skip XFCE startup | --test-minimal-x11 |
WALLPAPER |
Custom wallpaper path | --wallpaper |
ENABLE_CLIPBOARD |
Enable clipboard sync | --enable-clipboard |
Chroma 4:4:4 avoids chroma subsampling, improving clarity for text and sharp edges on remote desktops. It can be toggled at runtime from the config panel (Quality tab) or set at startup with --chroma 444.
| Codec | 4:4:4 Support | Notes |
|---|---|---|
h264 (CPU) |
✅ | Uses high444 profile |
h264_nvenc (GPU) |
✅ | Uses high444p profile. CPU usage increases (~50-85%) due to required CPU-side BGR→YUV444p conversion before GPU upload |
h265 (CPU) |
✅ | Uses main444-8 profile |
h265_nvenc (GPU) |
✅ | Uses rext profile. CPU usage increases due to CPU-side conversion. |
av1 (CPU) |
✅ | Uses libaom-av1 |
av1_nvenc (GPU) |
❌ | NVIDIA NVENC SDK does not support AV1 4:4:4 encoding on any current GPU architecture |
vp8 |
❌ | VP8 does not support 4:4:4 |
Note: When using
h264_nvencorh265_nvencwith chroma 444, CPU usage increases because FFmpeg must convert frames from BGR0 to YUV444p on the CPU before uploading to the GPU. NVIDIA'sscale_cudafilter does not support this conversion.