Version: 1.0.0
Platform: macOS · Windows · Linux
Tech stack: Electron 29 · Node.js · ADB · scrcpy
License: MIT
- Overview
- Architecture
- Installation & Setup
- Connecting Your Android Device
- Features In-Depth
- Keyboard & Mouse Control Reference
- Global Hotkeys
- Quality & Performance Tuning
- Recording & Screenshots
- Wireless (WiFi) Connection
- Multi-Device Support
- Settings
- Building for Distribution
- Troubleshooting
- Security & Privacy
- Project File Structure
ScreenMirror Pro is a cross-platform desktop application that mirrors your Android device's screen in real-time with ultra-low latency and gives you full mouse and keyboard control — all without root access or any special Android app installation.
| ScreenMirror Pro | Vysor | AirDroid | |
|---|---|---|---|
| Open protocol | ✅ scrcpy | ❌ proprietary | ❌ proprietary |
| No root | ✅ | ✅ | ✅ |
| Local only | ✅ | ❌ cloud | ❌ cloud |
| Multi-device | ✅ | 💰 paid | 💰 paid |
| Recording | ✅ | 💰 paid | 💰 paid |
| Dark UI | ✅ | ❌ | ❌ |
| Free | ✅ | limited | limited |
┌─────────────────────────────────────────────────────────┐
│ Electron Main Process │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ ADBManager │ │StreamManager │ │ControlManager │ │
│ │ │ │ │ │ │ │
│ │• Poll devs │ │• Launch scrcpy│ │• touch/swipe │ │
│ │• Wireless │ │• WS server │ │• keyevent │ │
│ │• QR pair │ │• Screencap │ │• text input │ │
│ │• Screenshot │ │ fallback │ │• clipboard │ │
│ └─────────────┘ └──────────────┘ └───────────────┘ │
│ │
│ ┌──────────────────┐ ┌─────────────────────────────┐ │
│ │ RecordingManager │ │ IPC Layer │ │
│ │• scrcpy --record │ │ contextBridge (secure) │ │
│ │• adb screenrecord│ │ No nodeIntegration │ │
│ └──────────────────┘ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│ IPC
┌────────────────┴────────────────┐
│ │
┌───────▼────────┐ ┌────────▼────────┐
│ Main Window │ │ Mirror Window │
│ (Renderer) │ │ (per device) │
│ │ │ │
│ • Device list │ │ • Canvas/WebGL │
│ • Sidebar │ │ • WS client │
│ • Wireless │ │ • Input capture │
│ modal │ │ • Toolbar │
│ • Settings │ │ • Status bar │
└────────────────┘ └─────────────────┘
| Decision | Rationale |
|---|---|
| Electron over Tauri | Wider ecosystem, faster iteration, no Rust toolchain required |
| scrcpy subprocess | Battle-tested <100ms latency, H264 hardware acceleration |
| WebSocket bridge | Decouples stream from IPC; supports future WebRTC upgrade |
| contextBridge IPC | Security: renderer has no direct Node.js access |
| Screencap fallback | Works even without scrcpy installed (lower fps, higher compat) |
| ADB polling vs events | Simple 2s poll avoids adb track-devices daemon dependency |
# macOS (Homebrew)
brew install node
brew install android-platform-tools # provides ADB
brew install scrcpy # recommended for full 60fps H264
# Ubuntu/Debian
sudo apt install adb scrcpy nodejs npm
# Windows
# 1. Install Node.js from https://nodejs.org
# 2. Install ADB: https://developer.android.com/studio/releases/platform-tools
# 3. Install scrcpy: https://github.com/Genymobile/scrcpy/releases
# 4. Add both to PATH# Install dependencies
npm install
# Development mode (with DevTools)
npm run dev
# Production mode
npm start- Open Settings on your Android device
- Go to About phone (or About device)
- Tap Build number exactly 7 times — you'll see "You are now a developer!"
- Go back to Settings → System → Developer options
- Enable USB debugging
- Connect via USB cable
- On the "Allow USB debugging?" prompt on device — tap Allow ✓
Android 11+: For wireless pairing, also enable Wireless debugging in Developer options.
adb devices
# Should show:
# List of devices attached
# ABCDEF123456 deviceThe app uses scrcpy to capture and stream the device screen:
- H.264 hardware-encoded on the device (very low CPU overhead)
- Streamed as a binary H264 bitstream over a local WebSocket
- Rendered on an HTML5
<canvas>element in the mirror window - Fallback: if scrcpy is not installed, uses
adb exec-out screencap -pat ~10fps
| Preset | Max Resolution | Bitrate | Target FPS |
|---|---|---|---|
| Native | Device native | 8 Mbps | 60 |
| HD 1080p | 1080p | 4 Mbps | 60 |
| 720p (default) | 720p | 2 Mbps | 30 |
| 480p | 480p | 1 Mbps | 30 |
All input is relayed via adb shell input commands:
| User action | ADB command |
|---|---|
| Mouse click | input tap X Y |
| Mouse drag | input swipe X1 Y1 X2 Y2 duration |
| Right-click | input swipe X Y X Y 600 (long press) |
| Scroll wheel | input swipe cx cy cx ey 200 |
| Keyboard char | input text 'char' |
| Special key | input keyevent KEYCODE |
| Paste clipboard | ADB broadcast → device clipboard |
- Model name & brand
- Android version
- Screen resolution
- Battery level (with color indicator)
- Connection type (USB / WiFi)
| Action | Result on Device |
|---|---|
| Left click | Tap at position |
| Click + drag | Swipe gesture |
| Right click | Long press (600ms) |
| Scroll up/down | Swipe up/down |
| Key | Android Action |
|---|---|
F1 |
Home button |
F2 / Escape |
Back button |
F3 |
Recent apps |
F4 |
Power button |
Arrow keys |
D-pad navigation |
Enter |
Confirm / OK |
Backspace |
Delete |
| All printable chars | Text input to device |
Press ⌘V / Ctrl+V while the mirror window is focused — the clipboard text is
sent to the Android device's clipboard and can be pasted with long-press → Paste.
These work system-wide (even when the app window is not focused):
| Hotkey | Action |
|---|---|
⌘⌥D (Mac) / Ctrl+Alt+D (Win/Linux) |
Show / hide main window |
⌘⌥R (Mac) / Ctrl+Alt+R (Win/Linux) |
Toggle recording on focused mirror |
⌘⌥S (Mac) / Ctrl+Alt+S (Win/Linux) |
Screenshot on focused mirror |
brew install scrcpy # required for H264 pathscrcpy uses hardware H264 encoding on device and streams at full 60fps over the USB 2.0 bus, which has ~5ms physical latency.
- Use 5GHz WiFi for best results
- Expected latency: 50–150ms on same network
- Recommended quality: 720p @ 2Mbps
- Switch to a lower quality preset in the toolbar dropdown
- Ensure USB cable is USB 3.0 (blue port preferred)
- Close other apps consuming network bandwidth
- Try
adb kill-server && adb start-serverto restart ADB daemon
- Click ⏺ Record in the mirror window toolbar (or
⌘⌥R) - A timer appears in the status bar
- Click Stop (or
⌘⌥Ragain) when done - File saved to your configured recordings directory (default:
~/Movies/ScreenMirror Pro/)
Recording uses:
- scrcpy
--recordif available → proper MP4 with timestamps adb shell screenrecordfallback → pulls file from device after stop
- Click 📷 Screenshot in toolbar (or
⌘⌥S) - Saved as PNG to
~/Pictures/ScreenMirror Pro/by default - File is automatically revealed in Finder/Explorer
# 1. While device is connected via USB:
adb tcpip 5555
# 2. Find device IP (Settings → WiFi → your network → IP address)
# 3. In the app: click "+" → enter IP → Connect- Settings → Developer options → Wireless debugging → Enable
- Tap Pair device with pairing code
- In the app, the QR Pair feature will appear (click the QR icon on a device card)
Click Disconnect on the device card — for wireless devices, this also runs
adb disconnect IP:PORT.
- Each connected device appears as a card in the left sidebar
- Click ▶ Mirror on any device → opens a separate floating mirror window
- Multiple mirror windows can be open simultaneously
- Each window has independent quality, recording, and always-on-top settings
Access via the ⚙️ icon in the top-right corner.
| Setting | Default | Description |
|---|---|---|
| Default quality | 720p | Preset for new mirror windows |
| Always on top | Off | Mirror windows stay above other apps |
| Recordings directory | ~/Movies/ScreenMirror Pro | MP4 save location |
| Theme | Dark | Dark / Light toggle in titlebar |
Settings are persisted via electron-store in the OS app data directory:
- macOS:
~/Library/Application Support/screenmirror-pro/ - Windows:
%APPDATA%\screenmirror-pro\ - Linux:
~/.config/screenmirror-pro/
npm run build:mac
# Output: dist/ScreenMirror Pro-1.0.0-arm64.dmg (Apple Silicon)
# dist/ScreenMirror Pro-1.0.0.dmg (Intel)npm run build:win
# Output: dist/ScreenMirror Pro Setup 1.0.0.exenpm run build:linux
# Output: dist/ScreenMirror Pro-1.0.0.AppImage
# dist/screenmirror-pro_1.0.0_amd64.debnpm run buildNote: macOS builds require Xcode Command Line Tools. Windows builds on CI require Wine if cross-compiling from macOS/Linux.
# Check ADB sees the device
adb devices
# If "unauthorized":
# → On the device: tap "Allow" on the USB debugging popup
# → Or: adb kill-server && adb start-server# Check scrcpy works standalone
scrcpy -s YOUR_DEVICE_SERIAL
# If scrcpy not installed, install it:
brew install scrcpy- Ensure no other scrcpy instance is running on the same device
- Try changing quality preset (device may not support native resolution)
- Check
adb shell getprop ro.build.version.sdk— scrcpy requires SDK 21+
- The app pulls the file from the device via
adb pull— give it a few seconds - Check the recordings directory in Settings
- Ensure the device has free storage space
# If "cannot be opened because the developer cannot be verified"
xattr -cr /Applications/ScreenMirror\ Pro.app| Property | Detail |
|---|---|
| Root required? | ❌ No |
| Special Android app? | ❌ No — uses standard ADB |
| Data sent to cloud? | ❌ Never — fully local |
| Analytics/telemetry? | ❌ None |
| Storage | Settings only, in OS app-data directory |
| Network | Only local loopback (127.0.0.1) for WebSocket stream |
| Permissions | USB access, file system (recordings dir only) |
ADB must be enabled by the device owner through Developer Options. The app cannot connect without the user physically accepting the USB debugging authorization on the device.
screenmirror-pro/
│
├── package.json # Dependencies & build config
├── README.md # Quick-start guide
├── DOCUMENTATION.md # This file — full docs
├── PROMPT.txt # The AI prompt used to generate this app
│
└── src/
├── main.js # Electron main process
│ # → Creates windows, registers IPC, hotkeys, tray
│
├── adb/
│ └── manager.js # ADB facade
│ # → Device polling, wireless connect, props, screenshot, QR
│
├── stream/
│ └── manager.js # Streaming engine
│ # → Launches scrcpy, WS server, screencap fallback
│
├── control/
│ └── manager.js # Input translation
│ # → Mouse events → adb shell input, keyboard mapping
│
├── recording/
│ └── manager.js # Session recording
│ # → scrcpy --record, adb screenrecord fallback
│
└── ui/
├── preload.js # Main window IPC bridge (contextBridge)
├── preload-mirror.js # Mirror window IPC bridge
├── index.html # Main window layout
├── styles.css # Full design system (CSS variables, dark/light)
├── app.js # Main window renderer logic
├── mirror.html # Per-device mirror window
└── mirror.js # Mirror renderer (WS, canvas, input, record)
ScreenMirror Pro — Built with ❤️ using Electron, Node.js, and the scrcpy protocol.