The Problem
USB webcams are mediocre and Wi-Fi phone-as-webcam apps add latency, re-encode video, or route through cloud services. This repo replaces that stack with a direct USB path: the phone's hardware H.264 encoder feeds OBS at ~91 ms measured latency (720p60), with no PC-side re-encoding and no network hop beyond localhost.
What This Does
An Android app (app/src/main/java/com/local/pococam/) captures via Camera2 and encodes with the phone's MediaCodec hardware encoder. A Python relay (server.py) receives the framed H.264 stream through an ADB reverse tunnel, wraps it in timestamped MPEG-TS, and pushes it to OBS as a Media Source over UDP (primary) or HTTP (fallback). The phone screen can be locked; a foreground CameraService keeps the encoder running with the display off.
The repo ships a prebuilt PocoCam.apk and Windows launcher scripts (install_and_run.bat, run_server.bat, setup.ps1). The README documents verified performance on a POCO F7: 720p30/60, 1080p30/60, and 4K30 sustained, with 4K60 correctly reported as unsupported rather than silently substituted.
How It Is Wired
Execution starts in two places. On the phone, MainActivity.java starts a session; CameraService.java owns the real work—Camera2 capture, MediaCodec encode, and the localhost TCP socket that carries framed H.264 out of the process. On the PC, server.py is the relay and the hub: every frame passes through it, so it carries the widest blast radius of any file here. A failure there kills the stream; it is also the only file that touches the network (UDP/HTTP to OBS) and the filesystem (no persistent state beyond logging).
The full path is three hops: camera surface → MediaCodec encoder → ADB reverse tunnel → server.py → OBS. No decode/re-encode occurs anywhere in the chain. CameraService.java is the second-most consequential file; it owns encode configuration and mode negotiation against the Camera2 API. MainActivity.java is thin UI and session orchestration. The Gradle files (app/build.gradle, build.gradle) configure the Android build only; the Python relay is standard-library-only.
How To Use It
From the README, verbatim workflow:
- First-time setup: run
install_and_run.bat(installs the APK and launches the server). If ADB is missing,setup.ps1downloads Google's Platform-Tools. - Normal use: run
run_server.batafter the app is installed. - Requirements: Windows 10/11, Python 3.10+ as
pythoninPATH, OBS Studio, Android 8.0/API 26+.
The APK SHA-256 is documented in the README (FAB7E37051167FF3ACF1A257D5550CC671FA90CD8562FC5B090250BAD26EAF15). In OBS, add a Media Source pointed at the relay's UDP/HTTP endpoint.
Real-World Use
For a streamer or remote worker: phone plugged into USB, run_server.bat running, OBS Media Source live. OBS Virtual Camera then exposes the composed output to Zoom or Teams. The phone stays locked and cool—the README reports thermal status 0 and ~24% of one CPU core during a screen-off 720p60 test.
Code Health & Issues
Static analysis findings (heuristic, verify against code):
- Med/SDLC — No test files detected; untested code paths — repository-wide.
- Med/SDLC — No CI/CD pipeline; no automated build/test gate —
.github/or CI config absent. - Med/SDLC — No LICENSE file; unclear usage/redistribution rights — root.
- Low/Risk — Dependencies declared without a lockfile; non-reproducible builds —
app/build.gradle.
The Android app is two Java files and the relay is one Python file, so the untested surface is small but real. The missing LICENSE is the more practical blocker for anyone wanting to redistribute or modify.
The Bottom Line
A focused, working solution with measured performance data and a prebuilt APK—good for anyone who wants a low-latency phone webcam in OBS today. The trade-offs are the Windows-only tooling, the absence of tests and CI, and the missing license. If you need a DirectShow camera for Zoom without OBS in the middle, this is not that project.