Two quality improvements: Preset: ultrafast -> veryfast. Unlocks Main profile with CABAC entropy coding, hexagonal motion search, 3 reference frames, and adaptive quantization — typically 30-40% better quality at the same bitrate. The desktop handles the extra encoding cost trivially (150+ fps at 1080p). Downscaling: the receiver now advertises its display resolution in the signaling answer (display_width/display_height, 0 = unknown). When the capture exceeds the display (e.g. 2256x1504 source on a 1920x1080 receiver), the sender scales down preserving aspect ratio before encoding — the same sws_scale pass that already converts the pixel format also handles the resolution change, so there is no extra step. This concentrates the entire bitrate into pixels the display actually shows (~2.7x more bits per visible pixel at 4000 kbps when going from 2256x1504 to 1620x1080). The renderer caches the display size during window creation (native monitor resolution in fullscreen/KMSDRM; window size otherwise). The receiver includes it in every signaling answer; the sender pipeline computes aspect-preserving, even-rounded scaled dimensions when the display is smaller than the capture. meson test 5/5 in both configurations, valgrind clean.
screen_cast
A native Linux peer-to-peer screencast application.
- Send your desktop or a window to another Linux machine.
- Receive a stream and render it in a window.
- Discover receivers on the LAN via mDNS/Avahi; negotiate sessions with JSON signaling; stream H.264 over RTP/UDP.
Built with C++20, Meson, PipeWire, FFmpeg, and SDL3.
Quick start
Requirements:
- C++20 compiler with
<format>(GCC 13+, Clang 18+) - Meson >= 0.63, Ninja
- FFmpeg development packages (
libavcodec,libavutil,libswscale) - SDL3 development package (
sdl3) - nlohmann JSON (
nlohmann_json) and Avahi client (avahi-client) - For the sender only: PipeWire dev (
libpipewire-0.3) and libportal
Build and run tests:
meson setup build
meson compile -C build
meson test -C build --print-errorlogs
Stream between two machines:
screencast --receive # machine A: announces itself, opens a window
screencast --send # machine B: discovers A, negotiates, streams
See docs/RUNBOOK.md for all modes, flags, and validation procedures.
Receiver on a small ARM board (e.g. Raspberry Pi Zero 2 W)
The receiver does not need the sender's PipeWire/portal capture stack. On the board, run:
sudo ./scripts/install-receiver.sh
screencast --receive
The script installs the dependencies, builds a receiver-only binary
(-Dsender=false), runs the test suite, and installs to /usr/local/bin
(override with SC_RECEIVER_INSTALL_DIR). It needs Raspberry Pi OS Trixie
or newer (GCC 13+ for C++20 <format>), builds SDL3 from source when the
distribution does not package it, and enables avahi-daemon. It also
installs and enables a systemd service so the receiver starts at boot —
systemctl status screencast-receiver to check on it.
Performance note: decoding is software H.264; on very small boards expect smooth playback for modest resolutions and reduced frame rates at high resolutions. Hardware decode is planned for Phase 7. On a headless console the receiver runs fullscreen automatically with aspect-preserving letterboxing.
Architecture
See docs/ARCHITECTURE.md for module boundaries and design rules.
Roadmap
Development is split into phases in docs/PHASES.md.
Current phase: Phase 7 — Resilience and polish.
License
MIT — see LICENSE (to be added).