Mirror or extend your Windows desktop onto an iPad over Wi-Fi or USB,
and control the PC with touch, a keyboard or Apple Pencil.
Download · Setup guide · Known issues · Website · Release notes
EternalMonitor streams your Windows desktop to an iPad and sends your input back. A small Windows app captures the screen and encodes it on your graphics card. The iPad app decodes the video in hardware and draws it with Metal, and every tap, keystroke and Pencil stroke travels back to the PC. It is free, open source under the MIT license, and needs no account.
- Extend or mirror. Add the iPad as an extra display beside your monitor, or mirror any screen you have. The extra display exists only while the iPad is connected, so Windows never keeps a phantom monitor around.
- Wi-Fi or USB. Stream over your home network, or plug in a cable for a steadier picture that also charges the iPad. A cable takes over a running Wi-Fi session, and unplugging it falls back to Wi-Fi.
- Touch, keyboard and pointer. Tap to click, drag, scroll with two fingers and hold to right-click. Hardware keyboards, trackpads and mice work too, with sticky modifiers and middle-click.
- Apple Pencil as a real pen. Windows receives Windows Ink pressure and tilt, and the pen lands under the tip on any monitor layout. Drawing mode ignores your palm on the canvas, and Clip Studio Paint works with its Tablet PC setting.
- Fit or fill. Fit shows the whole PC picture, with bars where the shapes differ. Fill uses the iPad's entire screen and trims the edges that don't fit.
- PC audio. Sound plays on the iPad as Opus, with a jitter buffer and loss concealment. You can mute it without stopping the video.
- Loss repair for real Wi-Fi. When a packet goes missing, the iPad asks for that fragment again right away, so one dropped packet rarely costs a frame. The bitrate adapts between 4 and 50 Mbps.
- Your GPU does the work. NVIDIA NVENC, AMD AMF or Intel Quick Sync encode H.264 by default, or HEVC if you prefer it, at 30, 60, 90 or 120 fps.
- Pairing. The first Wi-Fi connection asks for a six-digit code or a QR scan. After that the iPad remembers the PC. USB needs no code.
- Recovers and explains. The picture comes back by itself after the lock screen, a display change or a stream restart. When something does go wrong, both apps say what happened and what to do, and Send feedback writes an email to the studio with your setup filled in.
- Updates in one click. A popup tells you when a new version is out. On Windows, Update now checks the download and installs it with one Windows prompt; the iPad app opens TestFlight. The Windows app runs without a console window.
| Requirements | Get it | |
|---|---|---|
| Windows | Windows 10 version 1809 or later, or Windows 11, 64-bit, with NVIDIA, AMD or Intel graphics | EternalMonitor-Setup.exe (v0.3.2 current stable) |
| iPad | iPadOS 17 or later | TestFlight v0.3.2, build 316. The public beta is open: install TestFlight, then open the link on your iPad. |
Install both apps from the same version. The older v0.1 releases use a different protocol and cannot connect to the v0.3 iPad app.
Testing it? Send bugs and feedback through the form on the download page, which emails hello@sideband.studio, or open a GitHub issue.
The installer is not code-signed yet, so Windows SmartScreen asks before it runs. Choose More info, then Run anyway, only after checking that the file's SHA-256 matches the one on the release page.
For USB you also need Apple's free Apple Devices app, open while you stream. Windows can only reach an iPad over a cable through it, and EternalMonitor tells you when it is closed or missing. Apple Devices needs Windows 10 version 22H2 (build 19045) or Windows 11, so on older Windows 10 connect over Wi-Fi.
Next, follow the setup guide. It walks through installing both apps, pairing, USB, the extended display and drawing, with the exact button names you will see.
v0.3.2 places Apple Pencil correctly on PCs with more than one monitor, adds Fill, plain-language messages, Send feedback and one-click Windows updates, and opens on graphics drivers that crashed 0.3.1 at startup. Install it with iPad TestFlight v0.3.2, build 316.
Windows and iPad diagnostics include device details, app errors and stream statistics. Reports include PC names and network addresses, but exclude screen content, audio and pairing credentials. Disable automatic sharing in Settings. On iPad, open Settings > Support > Diagnostics to copy or export a report.
The release checks passed on Windows, macOS and iPad simulators. Problems we know about are on the Known issues page, and earlier physical-device results remain in docs/hardware-verification.md.
Known limits:
- The stream is not encrypted. Pairing keeps other devices out, so use a network you trust, such as your home Wi-Fi.
- The Windows app is the only host. The host builds on macOS for development, but there it streams a test pattern instead of your screen.
- Apple Pencil (USB-C) has no pressure sensor, so its strokes keep one width.
Known issues lists every problem we know about, with what to do about each one.
The Windows host is written in Rust. It captures the desktop with DXGI, encodes on the GPU through FFmpeg, and sends each frame as numbered UDP fragments. Over USB the same messages travel through a framed tunnel that Apple's device service provides. The iPad app is native Swift. It reassembles fragments, decodes with VideoToolbox and renders with Metal. On Wi-Fi it also requests any fragments that are missing. PC audio is captured with WASAPI and sent as Opus, and the iPad conceals lost audio instead of requesting it again. Input and receiver reports go back on the same session, and the host uses those reports to adapt the bitrate.
ARCHITECTURE.md describes the pipeline and protocol v2, and docs/decisions.md explains why each part works the way it does.
The workspace holds the Rust host (host/), the protocol crate eternal-wire
(proto/) and the Swift iPad app (ios/).
Windows host
Requirements: Windows 10 version 1809 or later, Rust 1.98.0 (pinned by
rust-toolchain.toml, MSVC), an FFmpeg 7.1 shared SDK and LLVM/libclang for
bindgen.
# Point the build at your FFmpeg 7.1 shared SDK (the folder with bin\avcodec-*.dll)
$env:FFMPEG_DIR = "C:\ffmpeg"
cargo build --release -p eternal-host
.\target\release\eternal-host.exe # optional port argument, default 9876The host is a Windows GUI program, so it opens no console window. Started
from a terminal it prints its log there, but the prompt returns at once;
cargo run -p eternal-host waits for it. With ETERNAL_HEADLESS=1 and output
redirected (> host.log) it gets its own console, so Ctrl+C in the terminal
can't reach it: press Ctrl+C in that console's window, or use Task Manager.
scripts\win\Stop-Host.ps1 stops only hosts that remote.sh run-host started.
scripts\build-installer.ps1 builds the full Setup.exe with Inno Setup and the
same FFMPEG_DIR. scripts\package.ps1 builds a bare zip.
macOS development loop (no Windows needed)
On macOS the host swaps screen capture for a synthetic test pattern. The protocol, encoder, transport and supervisor all run for real.
brew install ffmpeg@7 pkgconf xcodegen
export PKG_CONFIG_PATH=/opt/homebrew/opt/ffmpeg@7/lib/pkgconfig
cargo test --workspace # unit, golden-vector and synthetic end-to-end tests
ETERNAL_CAPTURE=synthetic cargo run -p eternal-hostIf Xcode's command-line tools are the selected developer directory, prefix Xcode
commands with DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer.
iPad app
cd ios
xcodegen generate # project.yml is the source of truth
xcodebuild test -project EternalMonitor.xcodeproj -scheme EternalMonitor \
-destination 'platform=iOS Simulator,name=iPad Pro 11-inch (M4)'To run on a physical iPad, open the generated project in Xcode and pick your own signing team.
End-to-end tests
./scripts/e2e_ios.sh # synthetic host to the iPad simulator, H.264
EM_CODEC=hevc ./scripts/e2e_ios.sh
scripts/test_ios.sh # iPad unit and UI tests
scripts/e2e_matrix.sh # UDP, loss, burst, USB, audio, pairing, input, lifecycle
scripts/soak.sh 1800 # 30-minute frame-rate and memory checkEach row checks the decoded frame rate (at least 55 fps), drops, repairs and the
rendered pixels. e2e_matrix.sh --real runs the Windows hardware rows through the
runner in scripts/win/; read scripts/win/README.md
first. CI runs the Rust suites on Linux, macOS and Windows, the iPad tests and a
streaming system test on every pull request.
Host environment variables
| Variable | Effect |
|---|---|
ETERNAL_ENCODER |
Force an encoder (h264_nvenc, h264_amf, h264_qsv, libx264) |
ETERNAL_HEVC |
1 or 0 overrides the HEVC preference |
ETERNAL_FPS |
Override the host frame rate; the iPad's preference still caps it |
ETERNAL_INPUT |
Encoder input: yuv420 (default), auto or bgra |
ETERNAL_MAX_DGRAM |
Media datagram size, 576 to 1400 bytes |
ETERNAL_CAPTURE |
synthetic swaps DXGI for a generated test pattern |
ETERNAL_AUDIO |
synthetic selects the deterministic audio test source |
ETERNAL_HEADLESS |
1 runs without the window; Ctrl+C shuts down cleanly |
ETERNAL_ABR |
0 disables adaptive bitrate |
ETERNAL_VDD_TIMEOUT_SECS |
How long to wait for the virtual display to attach |
ETERNAL_AMF_DIAG |
1 writes AMF bitstream diagnostics |
ETERNAL_LEGACY_PTS |
1 restores the old frame-counter timestamps |
ETERNAL_DROP, ETERNAL_REORDER, ETERNAL_JITTER_MS |
Test only: inject loss, reordering or jitter |
ETERNAL_USB_DIRECT |
Test only: a TCP endpoint in place of the USB tunnel |
Contributions are welcome, from transport and encoders to rendering and docs.
Read CONTRIBUTING.md before opening a pull request. To talk an
idea through first, message aldobenches285 on Discord.
Found a bug? Open an issue with both app versions and the host log. Report security problems privately as described in SECURITY.md.
EternalMonitor is released under the MIT License, © 2026 Sideband Studio. The Windows installer also ships third-party components under their own licenses, including the Virtual Display Driver and FFmpeg.
Built by Sideband Studio. Questions go to hello@sideband.studio.


