Skip to main content

ip cameras

Service Summary: The DrHeck Camera Hub (https://cam.drheck.dev) provides automatic LAN discovery, low-latency live video and MP3 audio streaming, two-way RTSP ONVIF backchannel voice talk, YOLOv8n + hardware AI event capture with a web-viewable timeline and text metadata log, optical 3D click-to-zoom and optional auto-zoom on moving objects, smart floodlight/IR/LED controls, privacy sleep mode, bandwidth adaptation, and a sideloadable Google TV interface for the Reolink PoE IP cameras on 10.0.0.0/24. Access is restricted via Authentik ForwardAuth to members of the camera_access group (luke, ikura, and haruka).

Hardware Inventory & Detected Cameras

Property Camera 1 (RLC-811A (122)) Camera 2 (RLC-811A (123))
IPv4 Address (Static Lease) 10.0.0.122 (host cam1) 10.0.0.123 (host cam2)
MAC Address ec:71:db:f1:25:5a ec:71:db:6d:84:ce
Vendor / OUI Reolink (ec:71:db) Reolink (ec:71:db)
Model / Item No. RLC-811A / P430 RLC-811A / P430
Hardware Revision IPC_560B158MP IPC_560B158MP
Firmware Version v3.1.0.4695_2504301440 v3.1.0.4695_2504301440
Serial Number 141484731968753 141484731989233
Ethernet Link 100M_FULL (802.3af PoE) 100M_FULL (802.3af PoE)
Optical Zoom Range 5X Motorized (ZoomPos 0..28, FocusPos 0..238, 3D Box Zoom) 5X Motorized (ZoomPos 0..28, FocusPos 0..238, 3D Box Zoom)
Illumination IR Night Vision (auto/close) + 450 lm Warm Floodlight (1..100%) IR Night Vision (auto/close) + 450 lm Warm Floodlight (1..100%)
Audio Live Mic (16 kHz AAC -> MP3) + Two-Way Backchannel (8 kHz G.711 PCMU) + Siren Live Mic (16 kHz AAC -> MP3) + Two-Way Backchannel (8 kHz G.711 PCMU) + Siren
Time Sync (NTP) time.google.com:123 (America/New_York EDT/EST) time.google.com:123 (America/New_York EDT/EST)

Camera Services, Network Ports & Internal Operation

On firmware v3.1.0.4695_2504301440, Reolink cameras lock down legacy plaintext web/streaming ports out of the box and expose only the proprietary Baichuan management port (9000/tcp) until explicitly instructed to enable standard streaming protocols.

1. Port & Service Matrix (cmd_id = 37 GetNetPort / cmd_id = 36 SetNetPort)

Service Protocol / Port Factory Default Active State on ul Purpose & Operation
Baichuan (server) 9000/tcp Enabled Enabled Proprietary binary + XML control, telemetry, snapshot, PTZ/zoom, AI/motion alarm, and configuration bus.
RTSP (rtsp) 554/tcp, 554/udp Disabled Enabled (Auto-enabled by cam) Real-Time Streaming Protocol serving hardware-encoded main (H.265 4K) and sub (H.264 360p) video, 16 kHz AAC microphone audio, and ONVIF Backchannel (track3 PCMU/8000) speaker talkback.
ONVIF (onvif) 8000/tcp Disabled Disabled (Toggleable) Open Network Video Interface Forum profile for third-party NVR integration.
RTMP (rtmp) 1935/tcp Disabled Disabled (Toggleable) Flash/RTMP H.264 sub-stream (rtmp://<ip>:1935/bcs/channel0_sub.bcs).
HTTP (http) 80/tcp Disabled Disabled (Toggleable) Embedded camera web UI and /cgi-bin/api.cgi JSON endpoint.
HTTPS (https) 443/tcp Disabled Disabled (Toggleable) Self-signed TLS embedded camera web UI and /cgi-bin/api.cgi JSON endpoint.

2. How the Baichuan Protocol (9000/tcp) Works

All discovery, hardware control, and instantaneous snapshots are performed over TCP port 9000 using Reolink's Baichuan protocol:

  1. Binary Framing Header: Every Baichuan packet begins with a 20-byte or 24-byte little-endian binary header starting with magic bytes 0xf0debc0a, followed by cmd_id (uint32), payload length (uint32), channel_id (uint8), status code (200 OK, 400 Bad Request), and payload offset.
  2. Modern Nonce Authentication (cmd_id = 1):
    • The client sends an initial unauthenticated cmd_id = 1 request.
    • The camera replies with an XML <Encryption> challenge containing a random <nonce>.
    • The client computes uppercase MD5 digests of username + nonce and password + nonce (truncated to 31 characters) and submits the authenticated login frame.
    • Once authenticated, payload bodies are encrypted using AES-128-CFB (or XOR stream cipher depending on message class) keyed from the session nonce.
  3. Complete Baichuan Command IDs Used by cam.drheck.dev:
    • cmd_id = 80 (GetDevInfo): Model (RLC-811A), item number (P430), firmware version, serial number.
    • cmd_id = 37 / 36 (GetNetPort / SetNetPort): Inspects and enables rtsp (554/tcp), onvif (8000/tcp), rtmp (1935/tcp), http (80/tcp), and https (443/tcp).
    • cmd_id = 76 / 75 (GetLocalLink / SetLocalLink): Reads or writes DHCP vs. static IPv4 settings and MAC address.
    • cmd_id = 182 (Snap): Captures an immediate hardware-encoded JPEG frame (main 4K or sub 640x360) directly over the control socket in ~110 ms.
    • cmd_id = 56 / 57 (GetEnc / SetEnc): Reads and updates H.265/H.264 resolution, frame rate (frame), target bitrate (bitRate in kbps), and audio track embedding (<audio>1</audio>) for mainStream and subStream.
    • cmd_id = 26 / 25 (GetImage / SetImage): Reads and updates ISP sensor parameters (bright, contrast, saturation, hue, sharpen, DayNight/mode auto|color|black&white, nr3d, mirror, flip).
    • cmd_id = 44 / 45 (GetOsd / SetOsd): Reads and updates On-Screen Display overlays, including the Reolink logo watermark (<OsdChannelName><enWatermark>0|1</enWatermark></OsdChannelName>), camera name overlay, and timestamp overlay.
    • cmd_id = 288 (SetWhiteLed manual) & cmd_id = 289 / 290 (FloodlightTask): Controls manual spotlight toggle (0|1), brightness (1..100), automatic lighting mode (0 Off/Manual, 1 Smart Night AI Trigger, 3 Night Schedule), duration (60..600s), and AI trigger classes (people,vehicle,dog_cat).
    • cmd_id = 208 / 209 (LedState): Controls Infrared Night Vision LEDs (<state>auto|close</state>) and the front power status LED (<lightState>open|close</lightState>).
    • cmd_id = 263 (AudioAlarmPlay) & cmd_id = 232 / 231 (GetAudioAlarm / SetAudioAlarm): Triggers manual 1x siren or configures automatic siren on AI/motion alarm (<AudioTask><enable>0|1</enable></AudioTask>, disabled 0 by default).
    • cmd_id = 264 / 265 (GetAudioCfg / SetAudioCfg) & cmd_id = 439 / 440 (GetAudioNoise / SetAudioNoise): Controls speaker volume (0..100) and microphone 3D AI noise reduction (level 0..3).
    • cmd_id = 574 / 575 (get_privacy_mode / set_privacy_mode) & cmd_id = 52 / 53 (GetMask / SetMask): Toggles hardware Privacy / Sleep mode (<sleepState><sleep>0|1</sleep></sleepState>) and hardware privacy masks (<Shelter><enable>0|1</enable></Shelter>).
    • cmd_id = 295 (StartZoomFocus), cmd_id = 445 (Set3DPos), & cmd_id = 224 / 225 (GetAutoFocus / SetAutoFocus): Steps the 5X motorized varifocal lens (ZoomPos 0..28, FocusPos 0..238), executes 3D area click-to-zoom (posX, posY, posWidth, posHeight in 0..1000 normalized coordinates), and locks/unlocks autofocus (disable 0|1).
    • cmd_id = 342 / 343 (GetAiAlarm / SetAiAlarm) & cmd_id = 46 / 47 (GetMdAlarm / SetMdAlarm): Configures per-class on-camera AI sensitivity (0..100) and stay-time (0..8s) for people, vehicle, dog_cat, face, plus general motion sensitivity (1..50).
    • cmd_id = 38 / 39 (GetNtp / SetNtp), cmd_id = 104 / 105 (SystemGeneral), cmd_id = 106 / 107 (Dst), & cmd_id = 23 (reboot): Configures NTP synchronization (time.google.com:123), US Daylight Saving Time, EDT/EST clock sync, and device reboot.

3. RTSP Stream Endpoints & ONVIF Two-Way Audio Backchannel (554/tcp)

Once rtspEnable = 1 is set via Baichuan cmd_id = 36, each camera serves two RTSP streams plus an ONVIF two-way audio backchannel track:

  • Sub Stream (Low-Latency H.264 + AAC Audio + PCMU Backchannel):
    rtsp://admin:<password>@10.0.0.122:554/h264Preview_01_sub
    rtsp://admin:<password>@10.0.0.123:554/h264Preview_01_sub
    
    • track1: H.264 High Profile (yuv420p, 640x360, default 10 fps at 256 kbps, GOP = 4, recvonly).
    • track2: MPEG4-GENERIC AAC-hbr (16 kHz mono audio, recvonly).
    • track3 (when negotiated with Require: www.onvif.org/ver20/backchannel): G.711 PCMU (PCMU/8000, payload type 0, sendonly) for transmitting two-way voice audio directly to the camera's built-in speaker.
  • Main Stream (4K UHD H.265/HEVC):
    rtsp://admin:<password>@10.0.0.122:554/h265Preview_01_main
    rtsp://admin:<password>@10.0.0.123:554/h265Preview_01_main
    
    Encoded as HEVC / H.265 (yuvj420p, 3840x2160, default 25 fps at 6144 kbps, GOP = 2) with 16 kHz mono AAC audio.

Architecture of cam.drheck.dev

The web service on host ul (/data/docker/cam) bridges the isolated IPv4 camera LAN (10.0.0.0/24) to an authenticated, browser-compatible HTTPS service at https://cam.drheck.dev.

Component Configuration on Host ul
Service Directory /data/docker/cam (app.py, static/index.html, static/tv.html, tests/app_test.py)
Persistent State & Models /data/docker/cam/data/cameras.json, /data/docker/cam/data/yolov8n.onnx (13 MB), /data/docker/cam/data/events/ (events.json + <event_id>.jpg)
Container Name cam (cam:latest, Python 3.12 + FastAPI + reolink-aio + onnxruntime + Pillow + numpy + espeak-ng + FFmpeg 7.1)
ULA IPv6 Binding [fd77:7777:5010:0:1337:f1ac:d00d:ca30]:8000 on eth77
Nginx Reverse Proxy /etc/nginx/sites-available/cam (X-Accel-Buffering: no, proxy_buffering off, X-Authentik-Groups forwarding)
Authentik SSO & Group ProxyProvider (cam-provider, ForwardAuth) -> Application (cam) bound to Group (camera_access)
Backup & Restore /home/luke/git/backups/ul/scripts/backup/cam & /home/luke/git/backups/ul/scripts/restore/cam (.tar.xz + par2 -r10)

Key Subsystems Implemented in app.py

  1. Zero-Config Discovery (discover_cameras):
    • Reads the host kernel ARP table (/proc/net/arp mounted read-only at /host_proc_arp), matches Reolink OUIs (ec:71:db, 9c:8e:cd), queries all Baichuan settings (cmd_id 80, 37, 76, 56, 26, 264, 44, 289, 208, 232, 439, 574, 52, 224, 38, 46, 342), and auto-enables RTSP (554/tcp) and audio encoding (<audio>1</audio>).
  2. Motion & YOLOv8n AI Event Capture + Web-Viewable Timeline (event_monitor_loop, record_camera_event):
    • A background monitor coroutine (event_monitor_loop) samples sub-stream snapshots from online, non-sleeping cameras every 3.5 seconds, computing downscaled 160x90 grayscale pixel frame-differences (compute_frame_motion).
    • Whenever motion (>= 2.2% of frame pixels) or a manual capture (POST /api/cameras/{ip}/capture_event) occurs, classify_snapshot_yolo runs the 80-class COCO YOLOv8n model (yolov8n.onnx via onnxruntime, ~62 ms CPU inference on letterboxed 640x640 input with IoU 0.45 Non-Maximum Suppression).
    • Clean Unannotated Snapshots + Text Metadata: The raw JPEG snapshot is saved without drawn bounding boxes to /data/docker/cam/data/events/<event_id>.jpg, while the detected class labels, confidence percentages (confidence_pct), normalized target coordinates (box_norm), trigger types (people, vehicle, dog_cat, motion, manual), frame motion percentage, and EDT/EST timestamp (format_edt_timestamp) are recorded in /data/docker/cam/data/events/events.json and displayed in the Detection Event Timeline & Metadata Log on https://cam.drheck.dev/.
  3. Optional Auto-Zoom on Moving Objects (apply_auto_zoom_on_box):
    • Each camera has an optional Auto-Zoom on Moving Objects toggle (auto_zoom_motion, off by default).
    • When enabled, detecting a moving person/object or motion region ([x, y, w, h] in 0..1000 normalized coordinates) automatically issues Baichuan cmd_id = 445 (Set3DPos set_ptz_3d_zoom) to zoom the 5X motorized lens onto the moving target, marks the timeline event with an Auto-Zoomed badge, and restores the lens to baseline_zoom after 20 seconds of inactivity.
  4. Two-Way Audio Talk (POST /api/cameras/{ip}/talk):
    • Supports both Push-to-Talk (Browser Microphone) (recording audio/webm via MediaRecorder in the browser) and Speak Text (TTS) (synthesizing speech via espeak-ng --stdout).
    • transcode_to_mulaw converts the audio stream via ffmpeg -i pipe:0 -ar 8000 -ac 1 -f mulaw pipe:1 into 8 kHz G.711 mu-law (PCMU/8000), and stream_rtsp_backchannel_mulaw negotiates an RTSP Digest session on 554/tcp with Require: www.onvif.org/ver20/backchannel, sets up track3 (Transport: RTP/AVP/TCP;unicast;interleaved=0-1), and transmits 160-byte (20 ms) RTP packets directly to the camera's speaker.

Static DHCP Reservations on danknasty & IPv6 Support

1. Static DHCP Reservations (/etc/dhcpd.conf & ~/git/router_config/dhcpd.conf)

Both cameras have permanent static DHCP leases configured in /etc/dhcpd.conf (and synced to ~/git/router_config/dhcpd.conf) on danknasty:

  host cam1 {
    # RLC-811A (141484731968753)
    hardware ethernet ec:71:db:f1:25:5a;
    fixed-address 10.0.0.122;
  }
  host cam2 {
    # RLC-811A (141484731989233)
    hardware ethernet ec:71:db:6d:84:ce;
    fixed-address 10.0.0.123;
  }

2. IPv6 Support

  • Camera Hardware (RLC-811A Firmware v3.1.0.4695_2504301440): No native IPv6 stack on the camera SoC (10.0.0.0/24 IPv4 only).
  • Service Frontend (cam.drheck.dev): Full dual-stack IPv4 and IPv6 support via Nginx -> [fd77:7777:5010:0:1337:f1ac:d00d:ca30]:8000.

Complete Camera Controls & Settings Matrix

All settings are available interactively in https://cam.drheck.dev/ or via POST /api/cameras/{ip}/control:

Category Setting Supported Range / Values Default on ul Baichuan cmd_id Web UI / API Action
Events & AI Auto Event Capture to Timeline true / false true (Enabled) Local + 182 Auto Event Capture (action: "auto_zoom_config")
Events & AI Manual Event Capture & Classify Captures JPEG + YOLOv8n text metadata On-demand 182 + ONNX Capture Event (POST /api/cameras/{ip}/capture_event)
Events & AI Person / Vehicle / Pet AI Sensitivity 0 .. 100 (stayTime 0..8s) 60 342 / 343 (SetAiAlarm) Person / Vehicle / Pet AI Sensitivity (action: "ai_sensitivity")
Events & AI Motion Detection Sensitivity 1 .. 50 10 46 / 47 (SetMdAlarm) Motion Sensitivity (action: "ai_sensitivity")
Optics & PTZ Optical Zoom (ZoomPos) 0 .. 28 (1X .. 5X optical) 0 295 (StartZoomFocus) Zoom slider (action: "zoom")
Optics & PTZ Optical Focus (FocusPos) 0 .. 238 Auto 295 (StartZoomFocus) Focus slider (action: "focus")
Optics & PTZ 3D Click-to-Zoom (Set3DPos) posX, posY, posWidth, posHeight (0..1000) Interactive 445 (set_ptz_3d_zoom) 3D Click-Zoom button (action: "zoom_3d")
Optics & PTZ Auto-Zoom on Moving Objects false (Off) or true (On) + baseline_zoom false (Off) 445 + 295 Auto-Zoom on Moving Objects (action: "auto_zoom_config")
Optics & PTZ Autofocus Lock false (Auto) or true (Locked) false (Auto) 224 / 225 (SetAutoFocus) Autofocus Lock (action: "autofocus")
Lighting Floodlight Manual Toggle & Brightness `state: true false, brightness: 1..100` Off, 85% 288 (SetWhiteLed)
Lighting Floodlight Auto Behavior (FloodlightTask) Mode 0 (Manual), 1 (Smart Night AI), 3 (Schedule); Duration 60..600s; Triggers people,vehicle,dog_cat Mode 1, 180s 289 / 290 (FloodlightTask) Spotlight Automatic Mode / Triggers / Duration (action: "floodlight_config")
Lighting IR Night Vision LEDs auto (Auto Night IR) or close (Off) auto 208 / 209 (LedState) IR Night Vision LEDs (action: "leds")
Lighting Front Status Power LED open (On) or close (Off / Stealth) open 208 / 209 (LedState) Front Status Power LED (action: "leds")
Lighting Day / Night Sensor Mode auto, color (24/7 Color), black&white auto 26 / 25 (SetImage) Day / Night Sensor Mode (action: "image")
Deterrents & Audio Auto-Siren on Detection false (Off) or true (On) false (Off) 232 / 231 (SetAudioAlarm) Auto-Siren on Detection (action: "audio_alarm")
Deterrents & Audio Manual Security Siren Trigger 1x Off 263 (AudioAlarmPlay) Siren (1x) (action: "siren")
Deterrents & Audio Live Microphone Audio Stream 16 kHz AAC -> 64 kbps MP3 Enabled 57 + RTSP Audio: Muted / LIVE (GET /api/cameras/{ip}/audio.mp3)
Deterrents & Audio Two-Way Audio Talk (Mic & TTS) Browser MediaRecorder or espeak-ng -> 8 kHz G.711 PCMU On-demand RTSP track3 (554) Push-to-Talk (Mic) & Speak Text (POST /api/cameras/{ip}/talk)
Deterrents & Audio Mic 3D Noise Reduction Level 0 (Off), 1 (Low), 2 (Med), 3 (High) 3 (High) 439 / 440 (SetAudioNoise) Mic 3D Noise Reduction (action: "audio_noise")
Deterrents & Audio Speaker Volume 0 .. 100 (%) 92 265 (SetAudioCfg) Speaker Volume (action: "volume")
Privacy Privacy / Sleep Mode false (Awake) or true (Sleeping) false (Awake) 574 / 575 (set_privacy_mode) Privacy Sleep button (action: "privacy_mode")
Privacy Hardware Privacy Mask (Shelter) false (Off) or true (On) false (Off) 52 / 53 (SetMask) Hardware Privacy Mask (action: "privacy_mask")
Image & OSD Mounting / Orientation (mirror, flip) Normal, 180° Upside-Down, Flip, Mirror Normal 25 (SetImage) Flip 180° button (action: "image")
Image & OSD Reolink Logo Watermark false (Hidden) or true (Visible) false (Hidden) 45 (SetOsd) Reolink Logo Watermark (action: "osd")
Time & System NTP Server & Clock Sync time.google.com:123 (EDT/EST) time.google.com 38 / 39 (SetNtp) & 105 Set time.google.com & Sync EDT Clock (action: "ntp", action: "sync_time")
Time & System Reboot Camera Hardware reboot On-demand 23 (reboot) Reboot Camera (action: "reboot")

Bandwidth Adjustments for Unreliable or Slow Internet

When viewing two cameras simultaneously over a slow, high-latency, or lossy internet connection, total downstream bandwidth for $N$ cameras is governed by:

$$B_{\text{total}} = N \times f_{\text{fps}} \times S_{\text{frame}}(W, H, q) \times 8 \quad \text{bits/sec}$$

where $f_{\text{fps}}$ is the frame rate, $W \times H$ is the scaled resolution, and $q \in [2, 24]$ is the FFmpeg MJPEG quantization factor (-q:v).

Preset Mode Resolution Frame Rate JPEG q Avg Frame Size Per-Camera Bitrate 2-Camera Total WAN Bitrate Best For
HD Main Stream 1280x720 10 fps 5 ~25 KB ~2.0 Mbps ~4.0 Mbps Fast fiber / LAN full-screen inspection
Standard Live (Default) 640x360 10 fps 5 ~6.2 KB ~500 kbps ~1.0 Mbps Normal broadband / Wi-Fi
Low Bandwidth 480x270 5 fps 10 ~4.0 KB ~160 kbps ~320 kbps Congested Wi-Fi / mobile hotspot
Ultra-Low WAN 320x180 2 fps 15 ~3.1 KB ~50 kbps ~100 kbps Throttled cellular / international roaming
Unreliable WAN Snapshot (2s) 640x360 0.5 fps (1 / 2s) Native ~9.0 KB ~36 kbps ~72 kbps High packet loss / TCP reset prone links
Minimal WAN Snapshot (5s) 640x360 0.2 fps (1 / 5s) Native ~9.0 KB ~14 kbps ~28 kbps Extreme low-speed satellite / 2G fallback

Authentik Access Control (camera_access Group) & Google TV App

  • Authorized Group (camera_access): luke, ikura, haruka. Enforced at both the Nginx ForwardAuth edge (PolicyBinding on cam) and inside check_camera_access_headers() in app.py.
  • Google TV Sideloadable App (dev.drheck.cam):
    • Built APK on ul: /data/docker/cam/googletv_src/cam-googletv.apk
    • 10-Foot TV Interface: https://cam.drheck.dev/tv (authenticated automatically via baked-in 256-bit TV_AUTH_TOKEN).