Open-source screen casting for Linux
Cast anything. Nearby. — Open-source Linux desktop screen casting app.
Nearby Cast is a lightweight, open-source Linux desktop application that streams your screen to compatible devices on your local network — Google Cast / Chromecast and Android TV. Device discovery is handled via mDNS, requiring zero manual configuration.
Feature Summary:
Feature | Support -- | -- Automatic device discovery | ✅ mDNS Google Cast / Chromecast | ✅ Android TV | ✅ Local network casting | ✅ Wayland | ✅ X11 | ✅ Open source | ✅ MITNearby Cast is released under the MIT License. See LICENSE for details.
Last updated: August 2026 | Author: kenan-karimli
Cast anything. Nearby. — Open-source Linux desktop screen casting app.
Nearby Cast is a lightweight, open-source Linux desktop application that streams your screen to compatible devices on your local network — Google Cast / Chromecast and Android TV. Device discovery is handled via mDNS, requiring zero manual configuration.
Feature Summary:
| Feature | Support |
|---|---|
| Automatic device discovery | ✅ mDNS |
| Google Cast / Chromecast | ✅ |
| Android TV | ✅ |
| Local network casting | ✅ |
| Wayland | ✅ |
| X11 | ✅ |
| Open source | ✅ MIT |
The project is split into two main layers:
┌─────────────────────────────────────────────┐
│ Tauri Desktop App │
│ (React + TypeScript frontend) │
│ │
│ - mDNS device discovery │
│ - User interface │
│ - Manages cast_launcher.py subprocess │
└──────────────────┬──────────────────────────┘
│ subprocess
▼
┌─────────────────────────────────────────────┐
│ cast_launcher.py (Python) │
│ │
│ wf-recorder → FIFO pipe → ffmpeg │
│ │ │ │
│ (Wayland capture) (H.264 encode) │
│ │ │
│ HTTP Media Server │
│ (fMP4 / HLS stream) │
│ │ │
│ Chromecast / ATV │
└─────────────────────────────────────────────┘
Inter-component communication:
cast_launcher.py as a child processSESSION_DIR and SESSION_TOKEN environment variables0700 permissionsstatus.json| Technology | Version | Purpose | |—|—|—| | Tauri | v2.x | Lightweight Rust-based desktop framework | | React | ^19.0.0 | UI components | | TypeScript | ^5.7.3 | Type safety | | Vite | ^6.1.0 | Build tool | | Lucide React | ^0.475.0 | Icon library |
| Technology | Version | Purpose | |—|—|—| | Python 3 | 3.x | Streaming orchestration | | wf-recorder | System | Wayland screen capture | | ffmpeg | System | Video encoding | | pychromecast | pip | Google Cast protocol |
| Format | Target |
|—|—|
| .deb | Debian / Ubuntu |
| .rpm | Fedora / RHEL |
| .bin | Universal binary |
| Flatpak | Sandboxed install |
| Snap | Ubuntu Snap Store |
cast_launcher.py — Streaming OrchestratorThis ~974-line Python script manages the entire capture → encode → serve → cast lifecycle.
Key functions:
select_video_encoder() — probes available hardware/software encoders and picks the best one (h264_vaapi → h264_nvenc → h264_qsv → libx264)start_capture() — starts the wf-recorder | ffmpeg pipeline, passing raw video through a FIFO pipecast_to_tv() — connects to the Cast receiver via pychromecast and instructs it to load the media URLUniversalHandler — session-token-gated HTTP media server; implements growing-file streaming for fMP4wait_for_stream() — reads ffmpeg progress output and updates the status JSON in real timeget_monitor_resolution() — detects monitor resolution via wlr-randr, hyprctl, or xrandrsrc-tauri/)The Rust-based desktop shell:
session_dir and session_token and passes them to cast_launcher.pysrc/)status.json to display live cast stateThe HTML_PLAYER template inside cast_launcher.py:
hls.js library<video src> directly for fMP4 transport?src=live.mp4 or ?src=live.m3u8Monitor / Window
│
▼
wf-recorder (Wayland)
--muxer=rawvideo -c rawvideo -x bgr0 -r 30
│
FIFO pipe (capture.raw.pipe)
│
▼
ffmpeg
-f rawvideo -pix_fmt bgr0 -framerate 30
+ audio (PulseAudio monitor / silence)
→ H.264 encode (VA-API / NVENC / QSV / libx264)
→ fMP4 (live.mp4) or HLS (live.m3u8 + .ts segments)
│
▼
HTTP Media Server (0.0.0.0 : random port)
Session-token-protected URL
│
▼
pychromecast → Cast receiver
play_media(URL, content_type, stream_type="LIVE")
Latency tuning:
frag_duration=500000 (0.5 s fragments)-fflags nobuffer+flush_packets -flags low_delayprobesize=32, analyzeduration=0Encoder selection uses an automatic probe mechanism — a real one-frame encode is attempted for each candidate before it is accepted:
Priority order:
1. h264_vaapi (VA-API — Intel / AMD GPU, per /dev/dri/renderD*)
2. h264_nvenc (NVIDIA GPU)
3. h264_qsv (Intel Quick Sync)
4. libx264 (Software fallback — always available)
Cast-optimized encoding parameters:
-bf 0) — reduces latencyNEARBY_CAST_ENCODER env var forces a specific encoderSelected via the NEARBY_CAST_TRANSPORT environment variable:
NEARBY_CAST_TRANSPORT=fmp4 (default)
video/mp4NEARBY_CAST_TRANSPORT=hls
The project uses multiple layers of isolation:
Session isolation:
SESSION_DIR with mode 0700Media server authorization:
/{SESSION_TOKEN}/live.mp4404Process management:
wf-recorder, ffmpeg) are saved in children.jsonSIGTERM / SIGINT handlers gracefully stop both processes and clean up temp filescurl -fsSL https://raw.githubusercontent.com/kenan-karimli/nearby-cast/main/install.sh | sh
The installer auto-detects your Linux distribution and installs the appropriate package.
Download the latest release from [GitHub Releases](https://github.com/kenan-karimli/nearby-cast/releases/latest):
| Package | System |
|---|---|
.deb |
Debian, Ubuntu, Linux Mint |
.rpm |
Fedora, openSUSE, RHEL |
.bin |
Any Linux |
The cast launcher requires the following to be installed:
wf-recorder — Wayland screen captureffmpeg — video encodingpython3 — runtime for cast_launcher.pypython3-pychromecast — Google Cast protocolgit clone https://github.com/kenan-karimli/nearby-cast.git
cd nearby-cast
npm install
npm run dev # Vite dev server
npm run tauri # Tauri development build
npm run build # TypeScript + Vite production build
| Script | Description |
|---|---|
npm run dev |
Start Vite dev server |
npm run build |
Production build |
npm run typecheck |
TypeScript type check (no emit) |
npm run tauri |
Tauri CLI |
npm run virtual-receivers |
Start virtual Cast receiver server |
npm run test:virtual |
E2E test against virtual receivers |
npm run test:protocols |
E2E + production path tests |
npm run test:latency |
Measure stream latency |
npm run test:stress |
Stability under load |
npm run test:all |
Run every test suite |
The tools/virtual-receivers/ directory contains a comprehensive test suite that allows testing the full pipeline without real Cast hardware:
| Script | Purpose |
|---|---|
e2e_test.py |
Full end-to-end cast flow |
production_path_test.py |
Production pipeline validation |
failure_test.py |
Error and failure scenario handling |
latency_test.py |
Stream latency measurement |
stress_test.py |
Stability under sustained load |
run_all_tests.py |
Sequential runner for all suites |
Lab mode (NEARBY_CAST_LAB_MEDIA=1):
ffmpeg lavfi testsrc instead of wf-recorderNEARBY_CAST_LAB_CAST_LOAD)| Device | Protocol | Status |
|---|---|---|
| Google Chromecast | Google Cast | ✅ Supported |
| Chromecast with Google TV | Google Cast | ✅ Supported |
| Android TV | Google Cast / fMP4 LIVE | ✅ Verified |
| Google Nest Hub | Google Cast | ✅ Supported |
| Cast-enabled smart TVs | Google Cast | ✅ Supported |
| Requirement | Details |
|---|---|
| OS | Linux |
| Display server | Wayland recommended (wlroots-compatible: Sway, Hyprland, GNOME Wayland); X11 also supported |
| Network | Same local network as the Cast device |
| GPU / CPU | Any; hardware encoder strongly recommended for performance |
Wayland compositor detection (in get_monitor_resolution):
wlr-randr — wlroots-based compositorshyprctl — Hyprlandxrandr — X11 / XWayland fallback| Variable | Default | Description |
|---|---|---|
NEARBY_CAST_SESSION_DIR |
— | Required. Path to the session directory |
NEARBY_CAST_SESSION_TOKEN |
— | Required. HTTP URL authorization token |
NEARBY_CAST_TRANSPORT |
fmp4 |
Transport mode: fmp4 or hls |
NEARBY_CAST_ENCODER |
auto |
Force encoder: auto, h264_vaapi, h264_nvenc, h264_qsv, libx264 |
NEARBY_CAST_LAB_MEDIA |
— | Set to 1 to enable Wayland-free lab mode |
NEARBY_CAST_LAB_CAST_LOAD |
— | Virtual receiver HTTP endpoint for lab casts |
NEARBY_CAST_ALLOW_LOOPBACK |
— | Set to 1 to permit casting over loopback |
XDG_RUNTIME_DIR |
/run/user/<uid> |
Wayland runtime directory |
WAYLAND_DISPLAY |
wayland-1 |
Wayland display socket |
Nearby Cast is released under the MIT License. See [LICENSE](https://github.com/kenan-karimli/nearby-cast/blob/main/LICENSE) for details.
| *Last updated: August 2026 | Author: [kenan-karimli](https://github.com/kenan-karimli)* |