Your Phone, Your Web-Camera
A Premium, High-Performance Mobile-to-PC Webcam Application with Zero Latency.
About | Architecture | Core Design | Setup | Visual Showcase
camXlink is a high-performance, real-time mobile-to-PC webcam application that lets you use your phone's camera as a system webcam on Windows. It works similarly to Iriun Webcam and Camo Studio, with a focus on minimal latency and near-zero CPU overhead on the desktop.
|
Hardware H.264 compression on the mobile device and direct shared memory writing on Windows bypasses slow IPC layers entirely. |
Tauri desktop backend in Rust and native OS camera modules keep CPU utilization at near-zero levels. |
|
Seamlessly stream over local Wi-Fi with automatic UDP beacon discovery or via ultra-stable USB tunnel with auto ADB reverse. |
Registers as a native virtual DirectShow device, letting you use it in Zoom, Teams, OBS, Discord, and web browsers. |
camXlink runs on a client-server model over a local network (Wi-Fi or USB tunnel). The heavy lifting — capturing, orientation correction, and hardware encoding — happens entirely on the phone, keeping the PC cool and responsive.
graph TD
subgraph "Mobile Client (React Native + Native OS Modules)"
Cam[Camera Capture: CameraX / AVFoundation] -->|Portrait / HDR / Stabilization| PostProc[Native Image Filter]
PostProc -->|Hardware H.264 Encoder| H264Enc[Android MediaCodec / iOS AVAssetWriter]
H264Enc -->|Length-Prefixed H.264 NAL Units| NetSend[Native TCP Socket Client]
NetSend <-->|Bidirectional Commands: Zoom, Exposure, Torch, Lens| CtrlHandler[Control Handler]
Disc[UDP Broadcast Listener]
end
subgraph "Desktop Studio (Tauri + Rust Backend + React Frontend)"
UDPSrv[UDP Broadcast Beacon] -->|Local Subnet Discovery| Disc
NetRecv[TCP Server] <-->|Duplex Video Stream & Settings Control| NetSend
TauriBE[Tauri Rust Backend] <-->|IPC commands & window state| TauriFE[Tauri Frontend: React/TS]
NetRecv -->|Broadcast Stream| Channel[Tokio Broadcast Channel]
Channel -->|H.264 bytes| FfmpegVC[FFmpeg VCam Decoder]
Channel -->|H.264 bytes| FfmpegMJ[FFmpeg MJPEG Decoder]
FfmpegMJ -->|MJPEG frames| MJPEG[HTTP MJPEG Server]
MJPEG -->|Native MJPEG Stream| TauriFE
FfmpegVC -->|Raw RGB24 scaled + corrected| VC[Virtual Camera Driver / DLL Interface]
end
subgraph "OS Video Pipeline (Windows Host)"
VC -->|Shared Memory| DS[DirectShow Filter / MF Virtual Camera]
DS -->|Virtual Webcam Input Device| Zoom[Target Apps: Zoom, Teams, OBS, Discord]
end
style Cam fill:#f9f,stroke:#333,stroke-width:2px
style DS fill:#bbf,stroke:#333,stroke-width:2px
style Zoom fill:#bfb,stroke:#333,stroke-width:2px
style Channel fill:#fdd,stroke:#333,stroke-width:2px
Raw frames (YUV/RGBA) are captured natively via Android CameraX or iOS AVFoundation and immediately compressed on hardware H.264 encoders (MediaCodec on Android), minimizing network bandwidth and bypassing the React Native JS Bridge entirely.
Frames are transmitted over TCP using a custom framing format: [1-byte battery][3-byte big-endian length prefix][raw H.264 bytes], operating in full-duplex mode.
Instead of converting bytes to base64 and passing them over Tauri IPC to a canvas (which is CPU-expensive), the Rust backend runs a lightweight HTTP server on 127.0.0.1:9012. An ffmpeg subprocess decodes incoming H.264 to MJPEG, served as multipart/x-mixed-replace. The React frontend renders a plain <img> pointing to http://localhost:9012/live.mjpeg — the browser decodes and composites it using GPU acceleration.
A second concurrent ffmpeg subprocess decodes H.264 directly into raw RGB24 frames scaled and orientation-corrected to 1280x720 (-vf scale=1280:720,vflip,hflip -pix_fmt rgb24 -f rawvideo). Rust reads exactly 1280 * 720 * 3 bytes from this subprocess's stdout via read_exact — no parsing, no decoding, no scaling in Rust. The raw frame is written directly into shared memory exposed by a registered DirectShow Source Filter DLL, making the stream instantly visible as a physical webcam across Windows.
When a user adjusts a slider (zoom, exposure) or toggle (torch, lens select) in the React dashboard, Tauri calls a Rust command which publishes a settings payload onto an async channel. A writer task serializes it to a line-delimited JSON packet and sends it down the duplex TCP socket. The phone's background reader parses the JSON and applies it to the native camera session lock.
- Wi-Fi: The PC broadcasts a JSON beacon on UDP port
9010every 2 seconds. The phone listens, discovers the PC, and shows it in the connections list. - USB (Android): Tauri triggers
adb reverse tcp:9011 tcp:9011. The phone connects to127.0.0.1:9011as if local, bypassing Wi-Fi jitter and charging the battery.
- PC: Node.js and Rust toolchain (
rustupwith MSVC build tools). - Android phone: USB Debugging enabled in Developer Options.
- Virtual camera driver: OBS Studio installed (registers the DirectShow shared memory driver).
Note
Zero PATH Prerequisites for FFmpeg & ADB: Portable binaries for both FFmpeg and ADB (Android Platform Tools) are bundled directly with the application, so they do not need to be installed on the host system or added to the system PATH.
-
Download Portable Binaries: Before launching the app, download the bundled FFmpeg and ADB binaries to the resources folder:
# Run from the desktop directory powershell -File scripts/download-ffmpeg.ps1 powershell -File scripts/download-adb.ps1
-
Install Dependencies & Launch Dev Server:
npm install npm run tauri dev
This starts the Rust compilation, opens the desktop UI, and launches the UDP/TCP/HTTP services.
cd mobile
npm install- Wi-Fi mode: Ensure PC and phone are on the same subnet, then run the app. The phone auto-discovers the PC.
- Android:
npx react-native run-android - iOS:
npx react-native run-ios
- Android:
- USB mode (Android): Connect via USB, click "Configure Android USB" in the desktop app, then tap "Connect via USB" on the phone.



