Hacker News new | ask | show | jobs
by moonlighter 109 days ago
Unifi cams don't stream RTSP, they stream FLV v1 (FlashVideo) on 3 streams over plain TCP on port 7550, one per quality channel. And yes, they stream that TO the NVR who adopted them only... then the NVR recodes and sends RTSP (configurable).

For the adoption stage, UniFi cameras broadcast on UDP port 10001 using a proprietary TLV (Type-Length-Value) protocol. The Protect console listens on this port and picks up new cameras immediately. 4 bytes `\x01\x00\x00\x00` sent as UDP broadcast to `255.255.255.255:10001`

The response then contains these fields:

  | Hex Code | Field | Data |
  |----------|-------|------|
  | `0x01` | MAC Address | 6-byte hardware address |
  | `0x02` | MAC + IP | Combined MAC and IPv4 address |
  | `0x03` | Firmware Version | String |
  | `0x0B` | Hostname | String |
  | `0x0C` | Platform (Short Model) | String |
  | `0x0A` | Uptime | 64-bit integer |
  | `0x13` | Serial | String |
  | `0x14` | Model (Full) | String |
  | `0x17` | Is Default | Boolean (adopted vs unmanaged) |
After discovery, the Protect console: 1. Connects to the camera via SSH (default credentials) 2. Configures the Inform URL (TCP 8080) 3. Camera registers with the controller

So conceivably at step 2 you could use your own modified URL to point to your own NVR and then grab the FLV streams from there.

1 comments

Thanks!

> 1. Connects to the camera via SSH (default credentials) 2. Configures the Inform URL (TCP 8080)

Not what I expected but okay. Looks like there's a `set-inform` command. It looks like it opens a TLS connection, doesn't check the certificate, and tries to opens a websocket:

    GET /camera/1.0/ws HTTP/1.1
    Pragma: no-cache
    Cache-Control: no-cache
    Host: ...
    Origin: http://ws_camera_proto_secure_transfer
    Upgrade: websocket
    Connection: close, Upgrade
    Sec-WebSocket-Key: ...
    Sec-WebSocket-Protocol: secure_transfer
    Sec-WebSocket-Version: 13
    Camera-MAC: ...
    Camera-IP: ...
    Camera-Model: 0xa601
    Camera-Firmware: 5.0.83
    Device-ID: ...
    Adopted: false
    x-guid: be9d8e45-62a8-ae84-8b23-71723c7decaf
I might try accepting the websocket but I have a feeling I'll get stuck about there without knowing what the server is supposed to send over it. I'm debating if I'm willing to buy a Unifi Protect device or not.

...then again I did a search for a couple strings and ran across https://github.com/keshavdv/unifi-cam-proxy . It's the opposite direction of what I want (makes a standard camera work with Unifi Protect) but maybe contains the protocol details I'm looking for...

> ...then again I did a search for a couple strings and ran across https://github.com/keshavdv/unifi-cam-proxy . It's the opposite direction of what I want (makes a standard camera work with Unifi Protect) but maybe contains the protocol details I'm looking for...

Actually, yes. I got lazy and just asked Claude Code to write a server, using that as a reference...and it worked. It was able to change the password and have it start streaming flv video. Not exactly a production-quality implementation but as a proof-of-concept it's quite successful.

There you go! I wrote a proxy server to deal with Unifi cameras and also dewarp their 360 camera streams... and used Claude Code to reverse-engineer most of what's going on. Sniff the entire network traffic between their NVRs and cams via Wireshark/TShark, grabbing the NVR's web socket streams, and also had it write a custom METAL shader pipeline native to Apple silicon to replace ffmpeg which was way too slow to deal with 5K 360 streams and dewarp them. All in a matter of hours. Amazing times ;)
I actually just registered here to comment the first time after lurking for years ;) I had the displeasure to upgrade from a broken g3 flex to a g5 flex, and then finding out they cut out the rtsp stream functionality for unknown (probably business) reasons. I dont plan to buy a protect appliance, and frigate should still handle my nvr stuff, so this comment thread comes really handy right now. Is there any possibility for you to publish this proxy to github or similar?
If I'm understanding correctly moonlighter's proxy speaks Ubiquiti's protocol on both ends, "just" altering the video stream along the way. Which is pretty cool but not what you're looking for.

I'd like to make a production-quality version of what you're looking for: acts as an RTSP server, adopts Ubiquiti cameras. As a single-binary thing that you could run anywhere, maybe even on the camera itself. (self-adoption? emancipation, as in "emancipated minor"?) But it'll take me a bit. My RTSP library right now is client-only, so it needs a bit of expansion to do this. Server support is in my TODO list along with several other changes. https://github.com/scottlamb/retina/issues/89