eufy-bridge

Turns a Eufy battery doorbell into an always-on RTSP camera for your NVR, and only wakes the doorbell when there’s something to see.

install
cp eufy-bridge.env.example eufy-bridge.env   # a second Eufy account
docker compose up -d --build
status
live tested on the T8214; motion trigger not yet watched end to end
version
0.1.0
stack
Node.js / ffmpeg / libx264 / MediaMTX / Docker / eufy-security-client
source
github.com/nickallevato/eufy-bridge ↗
links
traps found on the way ↗ · eufy-security-client ↗
since

What it is

Eufy’s battery doorbells have no RTSP stream and no local stream of any kind. The only open port is Eufy’s own P2P protocol on UDP 32108, and it answers only when the doorbell is awake. An NVR wants a camera that is always there.

The bridge logs into Eufy as a second account the doorbell is shared to. On a motion, person or ring push, or when someone opens the live view, it starts the P2P stream for 45 seconds and re-encodes it into one RTSP feed. Between events it plays a five-second loop of the last frame it saw, dimmed, blurred and stamped idle - last live HH:MM. Shinobi, Frigate and VLC see a camera that never went to sleep.

Why the switch doesn’t show

The idle loop and the live re-encode share an identical SPS, checked byte for byte. Same geometry, same profile and level, no B-frames. Every cut lands on a keyframe and one 10 fps clock paces both, so the muxer only ever copies. -tune zerolatency would have made the live path faster, but it flips one bit in the SPS, so it’s out.

What it costs

Idle~0.2% of one core, 28 kbps, ~0.3 GB a day on the NVR’s disk
Live~21–26% of one core, ~1.4 Mbps, ~8 MB per 45-second event
Opening the stream → live picture1.3 s, through an nginx mirror that wakes the doorbell for video and leaves the JPEG snapshot free

What it isn’t yet

It’s 0.1.0 and the README says so. The library underneath, eufy-security-client, was archived in September; the bridge stays pinned to a version that works, and when Eufy changes their protocol somebody ports it to the successor. Nobody has watched a real motion event go end to end yet. No audio. The control API has no authentication, so it stays on a trusted network.

The section of the README I’d read first is Traps found on the way. Shinobi saves snap: "1" as the number 1, then only builds the JPEG output for the string. Nothing errors. The snapshot just isn’t there.

writing about it

1