Low-latency P2P screen mirroring & recording between macOS and Android
Real-time Android screen streaming to macOS with PIP compositing, neon annotations, and HEVC recording — all over LAN with zero cloud dependency.
┌─────────────────────────┐ LAN (TCP:9999 + WebRTC) ┌──────────────────────────┐
│ Android Sender │ ◄══════════════════════════════════════► │ macOS Director │
│ (Honor Magic V2) │ │ (Apple Silicon) │
│ │ ┌─────────────────────────────────┐ │ │
│ MediaProjection │ │ Signaling: JSON-over-TCP │ │ ScreenCaptureKit │
│ → ScreenCapturerHook │ │ Media: WebRTC VP8/HW │ │ → MetalCompositor │
│ → WebRTC PeerConn │────│ Metadata: DataChannel │───│ → AVAssetRecorder │
│ → DataChannel (fold) │ │ Discovery: Bonjour/NSD │ │ → AudioMixer │
│ │ └─────────────────────────────────┘ │ → EphemeralCanvas │
└─────────────────────────┘ └──────────────────────────┘
- Screen Capture — 60fps via ScreenCaptureKit with GPU acceleration
- 3-Pass Metal Compositor — Mac screen + Android PIP + Neon annotations
- HEVC Recording — H.265 up to 8K with AAC-LC 256kbps audio
- Dynamic PIP — Cubic-eased transitions for fold state morphing
- Ephemeral Annotations — Neon glow strokes baked directly into MP4
- System Audio Mixing — ScreenCaptureKit audio bridged to AVAudioEngine
- Auto-Discovery — Zero-config Bonjour browser with auto-reconnect
- Cyberpunk Dashboard — Real-time telemetry: FPS, P2P status, fold state
- Floating HUD — Glassmorphism toolbar with record, annotate, spotlight, color picker
- Hotkeys —
⌘⌥1/2/3for PIP layout switching
- Hardware Capture — MediaProjection → EGL → WebRTC (zero software copies)
- Fold State Propagation — WindowInfoTracker → DataChannel → Mac PIP morph
- Orientation Tracking — Real-time screen rotation sync
- Premium Haptics — Taptic Engine composition API patterns
- Foreground Service — Android 14+ compliant background capture
- Cyberpunk UI — Grid background, neon glow, radar animations, telemetry panel
| Layer | macOS | Android |
|---|---|---|
| UI | SwiftUI + AppKit | Jetpack Compose + Material3 |
| Capture | ScreenCaptureKit (SCStream) | MediaProjection + EGL |
| Compositing | Metal + Core Image | — |
| Recording | AVAssetWriter (HEVC/AAC) | — |
| Audio | AVAudioEngine + PCM bridging | — |
| WebRTC | WebRTC.framework (M125) | io.github.webrtc-sdk:android:125.6422.07 |
| Signaling | NWConnection (TCP client) | ServerSocket (TCP server) |
| Discovery | NWBrowser (Bonjour) | NsdManager (mDNS) |
| Haptics | NSHapticFeedbackManager | VibratorManager + Composition API |
- macOS 14+ with Xcode 15+ and Swift 5.9+
- Android Studio Hedgehog+ with API 34 SDK
- Both devices on the same LAN
Android (Sender):
cd android
./gradlew assembleRelease
# Install APK from android/app/build/outputs/apk/release/macOS (Director):
cd mac
swift build -c release
# Binary at .build/release/MacDirector- Launch the Android app → tap LINK (grants screen capture permission)
- Launch the Mac app → click MODO DUAL ELYSIUM (auto-discovers Android via Bonjour)
- WebRTC handshake completes automatically (ICE trickle over TCP:9999)
- Click INICIAR GRABACIÓN to record the composited output as MP4
- Use
⌘⌥1/2/3to switch Android PIP layouts - Draw neon annotations directly on screen (baked into recording)
├── android/
│ └── app/src/main/java/com/jsm/core/
│ ├── MainActivity.kt # Compose UI + orchestration
│ ├── foldable/
│ │ └── FoldStateListener.kt # WindowInfoTracker bridge
│ ├── sensory/
│ │ └── SensoryFeedbackManager.kt # Haptic patterns
│ ├── signaling/
│ │ ├── NsdBroadcaster.kt # Bonjour/NSD registration
│ │ └── SignalingServer.kt # TCP JSON signaling server
│ └── webrtc/
│ ├── CaptureForegroundService.kt # Android 14+ lifecycle
│ ├── RTCClient.kt # PeerConnection + DataChannel
│ └── ScreenCapturerHook.kt # MediaProjection → WebRTC
├── mac/
│ ├── Package.swift
│ └── Sources/MacDirector/
│ ├── JSMApp.swift # SwiftUI entry point
│ ├── MainRouter.swift # Central orchestrator
│ ├── Capture/
│ │ ├── AudioMixer.swift # System audio → AVAudioEngine
│ │ └── ScreenCaptureManager.swift # SCStream 60fps
│ ├── Recorder/
│ │ └── AVAssetRecorder.swift # HEVC + AAC writer
│ ├── Renderer/
│ │ ├── EphemeralCanvas.swift # Neon annotations + cache
│ │ ├── LayoutMorphEngine.swift # Cubic PIP transitions
│ │ └── MetalCompositor.swift # 3-pass GPU pipeline
│ ├── Sensory/
│ │ └── SensoryFeedbackManager.swift # Haptics + sounds
│ ├── Signaling/
│ │ ├── BonjourBrowser.swift # Zero-config discovery
│ │ └── SignalingClient.swift # TCP client + auto-reconnect
│ ├── UI/
│ │ ├── DashboardView.swift # Cyberpunk dashboard
│ │ ├── HotKeyObserver.swift # ⌘⌥ keyboard shortcuts
│ │ └── MainHUD.swift # Floating glassmorphism toolbar
│ └── WebRTC/
│ ├── RTCController.swift # PeerConnection receiver
│ └── RTCVideoSink.swift # CVPixelBuffer extractor
└── README.md
| Resource | Protection | Threads |
|---|---|---|
LayoutMorphEngine.currentLayout |
os_unfair_lock |
Main ↔ SCStream Capture |
EphemeralEngine._cachedStrokes |
os_unfair_lock |
Main ↔ SCStream Capture |
AudioMixer.systemAudioNode |
NSLock |
SCStream Audio ↔ AVAudioEngine Render |
SignalingServer.clientWriter |
synchronized |
Accept ↔ Client Handler |
// Newline-delimited JSON over TCP:9999
{"type":"offer","sdp":"<base64-encoded-SDP>"}
{"type":"answer","sdp":"<base64-encoded-SDP>"}
{"type":"ice","candidate":"...","sdpMid":"audio","sdpMLineIndex":0}- LAN-only — No STUN/TURN servers, zero cloud exposure
- No credentials in repo — All secrets excluded via
.gitignore - TCP_NODELAY — Minimal signaling latency, no buffering
Proprietary. All rights reserved. © 2026 JSM Engineering.