Skip to content

About

🐧 Low-latency peer-to-peer remote desktop for Windows and Fedora. No port forwarding, works behind CGNAT, controllers + Discord-safe audio.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Penguin Stream: low-latency remote desktop for Windows and Linux. No port forwarding. Works behind CGNAT.

Latest release Windows 10/11 Fedora Ubuntu / Debian MIT license

Install, click Share this screen, send the invitation. That's the whole setup.

Direct P2P · CGNAT-ready · Keyboard, mouse and controllers you can toggle live · Discord-safe audio

Download

Get the installers from the latest release.

System File How
Windows 10/11 x64 PenguinStream-<version>-Setup.exe Installer (per-user, no admin needed)
PenguinStream-<version>-Portable.exe Runs without installing
Fedora 44 penguin-stream-<version>-1.fc44.x86_64.rpm sudo dnf install ./penguin-stream-*.x86_64.rpm
Ubuntu 24.04 LTS penguin-stream_<version>.ubuntu24.04_amd64.deb sudo apt install ./penguin-stream_*.ubuntu24.04_amd64.deb
Ubuntu 26.04 LTS penguin-stream_<version>.ubuntu26.04_amd64.deb sudo apt install ./penguin-stream_*.ubuntu26.04_amd64.deb
Debian 13 penguin-stream_<version>.debian13_amd64.deb sudo apt install ./penguin-stream_*.debian13_amd64.deb

SHA256SUMS.txt in each release lists the checksums. Both computers need the same version. Peers on different versions refuse to connect instead of half-connecting.

Note

Windows SmartScreen: the builds aren't code-signed yet, so Windows may say "unrecognized app". Choose More info → Run anyway.

Fedora codecs: the RPM works with Fedora's stock FFmpeg libraries, NVENC included. AMD/Intel GPU encoding (VA-API H.264) needs RPM Fusion's Mesa drivers. See docs/FEDORA.md.

Ubuntu/Debian: pick the .deb for your release. Each is built against that release's own FFmpeg, PipeWire and SDL, and apt pulls in everything it needs. Use apt install ./file.deb (with the ./), not dpkg -i, so dependencies are installed.

How to use it

  1. Host (the computer being shared): open Penguin Stream → Share this screen. On Wayland, pick the screen in the system dialog (and allow remote control if you want the other person to use your keyboard/mouse).
  2. Send the invitation privately (chat/DM). It stays the same every time you share, so your friend can keep it and reuse it. New code replaces it only when you ask, e.g. if it reached the wrong person.
  3. Viewer: open Penguin Stream → Connect to a screen → paste → Connect. Next time, Reconnect to the last host is one click.
  4. Both sides see four verification words. The host clicks Allow only if they match.

If the connection drops, nobody has to start over: the host keeps sharing on the same invitation, and the viewer reconnects by itself and gets straight back in without a new approval. Only Stop sharing or Disconnect ends it.

The stream opens in its own window. During a session either side can switch control on or off instantly:

Keyboard & mouse Controllers Game mode (mouse lock)
Host (Live session page) allow / revoke allow / revoke —
Viewer (Live session page) send / stop send / stop on / off
Viewer (stream window) Ctrl+Alt+Shift+M …+G …+Z

Ctrl+Alt+Shift+X toggles fullscreen, …+Q disconnects. Controllers appear on a Linux host through uinput and on a Windows host as virtual Xbox 360 pads (needs the free ViGEmBus driver).

Audio without the echo

The host's desktop audio streams to the viewer on both Windows and Linux. If you're in the same Discord call while sharing, you don't want your friend hearing everyone twice (themselves included). So by default Penguin Stream leaves voice-chat apps out of the streamed audio: Discord, TeamSpeak, Zoom, Teams, Mumble and others. You still hear the call normally. You can also leave out other apps, or stream only one app (just the game). See docs/AUDIO.md.

Connectivity and CGNAT

  • Pairing travels end-to-end encrypted over public Nostr relays, so there's no server to run and no port to open.

  • Media goes directly peer-to-peer over UDP (ICE hole punching). That works behind most CGNATs, which use endpoint-independent mapping. The app's Network page measures your NAT type and tells you what to expect.

  • If both sides are behind strict (symmetric) NATs, traffic falls back to a TURN relay. Only one side needs a relay configured. ICE pairs the other side's normal address with your relayed one, so you set it up once and the people you invite install and configure nothing. Options in Settings → Relay:

    • Cloudflare (free, 1,000 GB/month): anycast, so it relays through the city nearest you. Paste a TURN key ID + API token; only 24-hour credentials are ever used on the wire.
    • Credentials URL: any HTTPS endpoint returning ICE servers (e.g. Metered).
    • Your own TURN server: coturn on a cheap VPS; see docs/RELAY.md.

    Save & test relay performs a real TURN allocation, so "configured" means "proven working".

Built for low latency

Every stage is chosen for latency first:

  • Capture: DXGI Desktop Duplication (Windows) or the PipeWire screencast portal (Wayland), plus X11. One monitor by default, and each new desktop frame goes to the encoder the moment it arrives.
  • Encode: hardware H.264 (NVENC p1+ull, AMF ultra-low-latency, Quick Sync low_delay_brc, VA-API depth 1), no B-frames, zero lookahead, single-frame VBV so no frame takes longer than one frame interval to send. On NVIDIA the GPU does the BGRA→YUV conversion (about 3 ms/frame less CPU work at 1440p).
  • Transport: an unordered, zero-retransmit DTLS/SCTP data channel. A late frame is dropped rather than delayed, and the host skips non-keyframes when the send queue backs up. Loss triggers an immediate keyframe request (< 100 ms recovery).
  • Encryption: AES-256-GCM, hardware-accelerated by AES-NI on every x86-64 CPU.
  • Display: decoded with slice threads (no frame-threading delay) in a native SDL window, not a browser. By default each frame is presented the moment it's decoded (no V-Sync wait).
  • Input runs on its own path, and relative mouse motion is coalesced per frame.
  • Adaptive bitrate: the host lowers the bitrate as soon as video starts queueing and restores it when the connection is clean, so a busy upload doesn't turn into seconds of delay.
  • See it: the live page measures every stage in milliseconds (capture → encode → network → decode → display) and tells you which setting would help. Profiles switch between setups in one click.

Security

End-to-end encryption uses a Noise XX handshake (Noise_XX_25519_AESGCM_SHA256) over DTLS, with 160-bit invitations, four-word verification, and explicit host approval for every new device. Relay operators and Nostr relays see only ciphertext. The local control UI is loopback-only and token-protected. Read SECURITY.md for the threat model and what has not been independently audited.

Build from source

Needs Node.js ≥ 20, CMake ≥ 3.20, a C++17 compiler, FFmpeg/SDL2/PipeWire/GLib development packages.

npm ci
cmake -S media -B media/build && cmake --build media/build -j
npm run app                 # run the desktop app from source
npm test                    # full suite, incl. crypto inside the Electron runtime and a real PipeWire audio session
npm run dist:linux          # -> dist/penguin-stream-<version>-1.fc44.x86_64.rpm (needs rpmbuild)
npm run dist:deb            # -> dist/penguin-stream_<version>.<distro>_amd64.deb (needs podman; run dist:linux first)
npm run dist:win            # -> dist/PenguinStream-<version>-Setup.exe + Portable.exe (needs podman)

The Windows build cross-compiles the media engine with MinGW in a Fedora container and packages it in electron-builder's Wine container. The Ubuntu/Debian packages build the engine inside each release's own container. Nothing gets installed on the build machine. The CLI (node node/src/cli.mjs host|connect|doctor) is still available for headless use and scripting.

See LIMITATIONS.md for exactly what has and hasn't been verified, and CHANGELOG.md for what changed in each release.

MIT licensed. Third-party components: THIRD-PARTY.md.

A penguin waddling across the ice

About

🐧 Low-latency peer-to-peer remote desktop for Windows and Fedora. No port forwarding, works behind CGNAT, controllers + Discord-safe audio.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages