Turn your Android tablet or smartphone into a high-performance, ultra-low-latency secondary monitor for Windows using Apollo and Moonlight.
SubMonitor seamlessly automates the creation of a Windows virtual display and streams it to your Android device. By leveraging USB Tethering instead of standard ADB reverse tunneling, SubMonitor unlocks full UDP streaming capabilities with near-zero latency, smooth 60+ FPS refresh rates, and hardware-accelerated encoding.
+-------------------------------------------------------------+
| Windows PC |
| +---------------------+ +-------------------------+ |
| | SubMonitor | -----> | Apollo Server | |
| | (CLI / Auto-Setup) | | (Virtual Display + H264)| |
| +---------------------+ +-------------------------+ |
+----------------------------------------------|--------------+
|
USB Cable | (USB Tethering / UDP+TCP)
v
+-------------------------+
| Android Device |
| (Moonlight / Artemis) |
+-------------------------+
- Ultra-Low Latency Streaming: Uses USB Tethering (RNDIS / USB Ethernet) to support native UDP transport, providing noticeably lower latency and higher stability compared to TCP-based solutions.
- Automatic Resolution Detection: Queries device resolution over ADB (
wm size) and automatically configures the virtual display to match your device's native aspect ratio and resolution. - Virtual Display Integration: Integrates directly with Apollo (Sunshine fork with dynamic virtual display driver support).
- Live Screen Toggle: Switch between Android only and main monitor + Android while streaming, with no reconnect.
submonitor.py mode toggleattaches/detaches the physical monitor through the Windows display API and never touches Apollo, so the session stays up. - Extended & Headless Modes:
display.headlessinconfig.yamldecides which mode a new stream starts in. - Safe State Teardown: Automatically restores original configuration files and cleans up virtual displays when terminating (
Ctrl+Corsubmonitor stop). - One-Command CLI & Launchers: Includes convenient helper scripts (
submon.cmd,submon.ps1) for instant startup.
- Windows 10 / 11 (64-bit)
- Python 3.10+
- Apollo: Install from ClassicOldSong/Apollo Releases.
- Android SDK Platform Tools (ADB):
- Can be installed via
winget install Google.PlatformToolsor placed in your systemPATH.
- Can be installed via
- Moonlight Game Streaming (or Artemis) app installed from Google Play or GitHub.
- USB Debugging enabled in Developer Options (used for automatic resolution query).
- USB Tethering enabled in Network / Tethering settings.
-
Clone the repository:
git clone https://github.com/naga361111/SubMornitor.git cd SubMornitor -
Create a virtual environment and install dependencies:
python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -r requirements.txt
Check that ADB, Apollo, and your USB tethering connection are properly detected:
python submonitor.py setup(Or run submon setup)
Run SubMonitor to configure and launch Apollo:
python submonitor.py start(Or simply run submon)
What happens automatically:
- Detects connected Android device and fetches screen resolution.
- Updates Apollo configuration and initializes the virtual display.
- Detects the USB tethering IP address (e.g.,
192.168.42.x) and displays connection instructions.
- Connect your Android device to the PC via USB cable and enable USB Tethering.
- Open Moonlight on Android.
- Tap Add PC (or the
+icon) and enter the Connection IP printed in the SubMonitor console. - When prompted with a PIN in Moonlight, open Apollo Web UI in your browser (
https://localhost:47990), go to PIN, and enter the code to pair. - Tap Desktop in Moonlight to start using your Android device as a secondary monitor!
To shut down Apollo and restore original display settings:
- Press
Ctrl+Cin the running terminal, or - Run:
python submonitor.py stop
| Command | Description |
|---|---|
python submonitor.py setup |
Inspects environment, ADB connection, Apollo installation, and network interfaces. |
python submonitor.py start |
Configures virtual display, starts Apollo, and outputs connection info. |
python submonitor.py stop |
Restores original configuration and stops Apollo service and processes. |
python submonitor.py status |
Checks the status of Apollo, connected devices, and network adapters. |
python submonitor.py mode |
Shows the current screen mode and active displays. |
python submonitor.py mode android |
Android only — detaches every physical monitor, leaving the virtual display live. |
python submonitor.py mode both |
Main monitor + Android — reattaches physical monitors alongside the virtual display. |
python submonitor.py mode toggle |
Flips between the two. Handy to bind to a hotkey. |
Windows batch and PowerShell wrapper scripts are provided in the root directory:
# Start directly using the virtual environment
.\submon.cmd
# or
.\submon.ps1
# Run specific subcommands
.\submon.cmd status
.\submon.cmd stopYou can customize display, streaming, and tool options in config.yaml:
# SubMonitor Configuration
display:
width: 0 # 0 = Auto-detect device resolution via ADB
height: 0
refresh_rate: 60 # Target refresh rate (Hz)
position: "right" # Position relative to primary monitor
headless: false # false = Extended desktop (default, main monitor stays on); true = Android only
streaming:
codec: "h264" # "h264" or "hevc"
bitrate: 10000 # Bitrate in kbps (10 Mbps default)
fps: 60 # Target frame rate
connection:
method: "usb_tethering" # "usb_tethering" (recommended) or "adb_reverse"
tools:
adb_path: "" # Custom path to adb.exe (auto-detected if empty)
apollo_path: "" # Custom path to sunshine.exe / apollo.exe (auto-detected if empty)
apollo_web_port: 47990 # Apollo Web UI portFor the best experience, configure the following inside the Moonlight app on your Android device:
- Resolution: Match the resolution printed by SubMonitor (e.g., native tablet resolution).
- Frame Rate: Match
display.refresh_rate(e.g., 60 FPS or 120 FPS). - Video Bitrate: 10–20 Mbps for USB tethering (USB provides high bandwidth with zero packet loss).
- Video Codec: H.264 or HEVC (HEVC offers better compression efficiency).
- Touch Mode: Set to Touchscreen or Trackpad depending on your preference.
- Ensure USB Tethering is turned ON in Android Settings (
Settings -> Network & internet -> Hotspot & tethering -> USB tethering). - Verify that Windows recognizes the RNDIS / Remote NDIS adapter under
ipconfig /all. - If USB tethering is unavailable, SubMonitor will automatically fall back to providing your local Wi-Fi/LAN IP address.
- Ensure USB Debugging is enabled on Android (
Settings -> Developer options -> USB debugging). - Run
adb devicesin terminal and confirm the device is listed asdevice(notunauthorizedoroffline). Grant USB debugging authorization if prompted on your phone/tablet screen.
- Some Windows configurations require Administrator privileges to control the Apollo Windows service. Run PowerShell or Command Prompt as Administrator if service control fails.
- Make sure firewall rules allow traffic on Apollo streaming ports (UDP 47998-48000, 48002, 48010).