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 zoom/spotlight/siren3D hardwareclick-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 Two-WayLive AudioMic (16 kHz AAC)AAC -> MP3) + IntegratedTwo-Way Backchannel (8 kHz G.711 PCMU) + Siren Two-WayLive AudioMic (16 kHz AAC)AAC -> MP3) + IntegratedTwo-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) videovideo, +16 kHz AAC audio.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. KeyComplete 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), and 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, DayNightDayNight/mode auto|color|black&white, nr3d).
  4. cmd_id = 264 /, 265mirror (GetAudioCfg /, SetAudioCfg): Reads and updates speaker volume (0..100flip).
  5. 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 overlayoverlay, 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 (<OsdChannelNamestate>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></OsdChannelNameAudioTask>, disabled 0 by default),. cmd_id = 264 / 265 (GetAudioCfg / SetAudioCfg) & cmd_id = 439 / 440 (GetAudioNoise / SetAudioNoise): Controls speaker volume (0..100) and timestampmicrophone overlay3D 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 (<OsdDatetimesleepState><sleep>0|1</sleep></sleepState>) and hardware privacy masks (<Shelter><enable>0|1</enable></OsdDatetimeShelter>). cmd_id = 288 / 290 (SetWhiteLed / GetWhiteLed): Controls the warm-white floodlight/spotlight (<FloodlightManual><status>0|1</status></FloodlightManual>) and brightness (1..100). cmd_id = 295 (StartZoomFocus), cmd_id = 445 (Set3DPos), & cmd_id = 224 / 225 (GetAutoFocus / SetAutoFocus): MovesSteps the 5X motorized varifocal lens to an exact zoom step (ZoomPos 0..28), or focus step (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 = 276342 / 343 (AudioAlarmPlayGetAiAlarm / SetAiAlarm) & cmd_id = 46 / 47 (GetMdAlarm / SetMdAlarm): TriggersConfigures theper-class built-inon-camera audibleAI securitysensitivity siren.(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:streams plus an ONVIF two-way audio backchannel track:

  • Sub Stream (Low-Latency H.264)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
    
    Encoded
    as
  • track1: H.264 High Profile (yuv420p, 640x360, default 10 fps at 256 kbps, GOP = 4, recvonly).
withtrack2: MPEG4-GENERIC AAC-hbr (16 kHz mono AACaudio, 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, static/cam-googletv.apk, 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-hub: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, WebSocketX-Authentik-Groups + streaming support)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)

HowKey Subsystems Implemented in cam.drheck.devapp.py Communicates With the Cameras

  1. Zero-Config Discovery (discover_cameras):
    • Reads the host kernel ARP table (/proc/net/arp mounted read-only at /host_proc_arp).
    ,
  2. Filters formatches Reolink IEEE MAC OUI prefixesOUIs (ec:71:db and, 9c:8e:cd) and probes TCP ports 9000 and 554 across 10.0.0.0/24 (excluding infrastructure router/switch IPs).
Connects to each discovered Reolink camera on 9000/tcp, queries hardwareall metadata (cmd_id = 80), network ports (cmd_id = 37), encoderBaichuan settings (cmd_id =80, 37, 76, 56), ISP26, image264, settings44, (cmd_id289, =208, 26232, 439, 574, 52, 224, 38, 46, 342), and audioauto-enables volume (cmd_id = 264). If rtspRTSP (554/tcp) isand disabledaudio on a newly plugged-in camera, inspect_reolink_camera automatically sends SetNetPort(rtspEnable=1)encoding (cmd_id = 36<audio>1</audio>) so live streaming works immediately without requiring the proprietary Reolink desktop/mobile client.. HybridMotion Instant-Snapshot& YOLOv8n AI Event Capture + FFmpegWeb-Viewable MJPEG StreamingTimeline (mjpeg_stream_generatorevent_monitor_loop, record_camera_event):
  • StandardA webbackground browsersmonitor cannotcoroutine natively(event_monitor_loop) decodesamples rawsub-stream RTSPsnapshots 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 H.265a streamsmanual inside <img> tags, and waiting for an RTSP H.264 IDR keyframecapture (GOPPOST = 4) introduces a 1–2 second blank delay on initial load. Furthermore, RLC-811A sub-streams output limited-range yuv420p(progressive) frames; FFmpeg 7.1's mjpeg encoder rejects non-full-range YUV unless explicit color-range conversion (format=yuvj420p) and -strict unofficial are specified. To solve both problems, /api/cameras/{ip}/mjpegcapture_event) occurs, classify_snapshot_yolo executesruns athe two-stage80-class pipeline:COCO
    YOLOv8n Stage 1model (<150yolov8n.onnx via onnxruntime, ~62 ms FirstCPU Frame)inference on letterboxed 640x640 input with IoU 0.45 Non-Maximum Suppression). Clean Unannotated Snapshots + Text Metadata: ImmediatelyThe fetches a singleraw JPEG snapshot viais 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/. 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 = 182445 (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 yields it asrestores the first --frame part so the browser displays an image immediately. Stage 2 (Continuous Live Transcode): Spawns ffmpeg over TCP RTSP:
      ffmpeg -nostdin -loglevel error -rtsp_transport tcp -analyzeduration 1500000 \
        -flags low_delay -i rtsp://admin:@10.0.0.123:554/h264Preview_01_sub -an \
        -vf "fps=10,scale=640:-2,format=yuvj420p" -strict unofficial \
        -f mpjpeg -boundary_tag frame -q:v 5 -
      
      Stage 3 (Automatic Fallback): If the RTSP socket ever drops, the generator transparently falls backlens to streamingbaseline_zoom Baichuanafter JPEG20 snapshotsseconds atof the requested interval. inactivity. IntegerTwo-Way StateAudio NormalizationTalk for(POST Spotlight Control/api/cameras/{ip}/talk):
      • Reolink'sSupports Baichuanboth Push-to-Talk (Browser Microphone) (recording SetWhiteLed (cmd_id = 288) XML parser requires <status>1</status> or <status>0</status> and rejects Python boolean strings (<status>True</status>) with status code 400. app.py normalizes stateaudio/webm via normalize_floodlight_state(req.state)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 integerthe 1camera's or 0.speaker.

      Static IPs vs. DHCP Reservations on danknasty & IPv6 Support

      1. Should the Cameras Be Configured for Static IPs?DHCP Reservations (/etc/dhcpd.conf & ~/git/router_config/dhcpd.conf)

      YesBoth —cameras pinninghave the cameras' IPv4 addresses viapermanent static DHCP reservationsleases on danknasty is recommended.

      Currently, both cameras use DHCP (<Dhcp><enable>1</enable></Dhcp>) and received 10.0.0.122 and 10.0.0.123 from the dynamic pool (range 10.0.0.114 10.0.0.250;) on danknasty. There are two ways to assign permanent IPs:

        Static DHCP Reservationconfigured in /etc/dhcpd.conf on danknasty (Recommended):
          Binds each camera's factory MAC address (ec:71:db:f1:25:5a and ec:71:db:6d:84:ce)synced to a fixed IPv4 address at the router level while leaving the cameras themselves in DHCP mode. Why this is better than on-camera static IPs: If the LAN subnet or gateway ever changes, a camera with a hardcoded static IP becomes unreachable until someone physically climbs up to the camera housing and holds the hardware reset button on the PoE pigtail for 10 seconds. With a DHCP reservation~/git/router_config/dhcpd.conf) on danknasty, IP assignment is centrally managed and versioned alongside pikvm, nodegrid, kikuo, and fireboardctl:
            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;
            }
          
          On-Camera Static IP via Baichuan cmd_id = 75 (SetLocalLink):
            The camera firmware stores its IPv4 configuration in <LocalLink> (cmd_id = 76 to read, cmd_id = 75 to write):
            <LocalLink version="1.1">
              <Dynamic>
                <Dhcp><enable>0</enable></Dhcp>
                <Ip>
                  <ip>10.0.0.122</ip>
                  <mask>255.255.255.0</mask>
                  <gateway>10.0.0.1</gateway>
                </Ip>
                <Dns>
                  <auto>0</auto>
                  <dns1>10.0.0.1</dns1>
                  <dns2>0.0.0.0</dns2>
                </Dns>
              </Dynamic>
            </LocalLink>
            
            Even if DHCP leases ever rotate before a reservation is added, cam.drheck.dev automatically discovers the new IP by matching ec:71:db:* in /proc/net/arp.

            2. Do the CamerasIPv6 Support IPv6?

            • Camera Hardware (RLC-811A Firmware v3.1.0.4695_2504301440): No native IPv6 support.stack
                on
              • Inspectionthe ofcamera ip -6 neigh show dev eth77 confirms that neither ec:71:db:f1:25:5a nor ec:71:db:6d:84:ce configures an IPv6 link-localSoC (fe80::/1010.0.0.0/24), SLAAC, or DHCPv6 address, and the Baichuan LocalLink (cmd_id = 76) schema only supports 32-bit IPv4 fields.
              only). Service Frontend (cam.drheck.dev): Full Dual-Stack & IPv6 Support.
                The cam container on host ul binds to dedicated ULA IPv6 address fd77:7777:5010:0:1337:f1ac:d00d:ca30 (port 8000) and is served publicly by Nginx over dual-stack IPv4 and IPv6 (support via Nginx -> 2603:3001:626:9de0:[fd77:7777:5010:0:1337:f1ac:d00d:aaaa). Host ul translates incoming IPv6 HTTPS requests to IPv4 Baichuan/RTSP camera traffic on 10.0.0.0/24ca30]:8000.

                AvailableComplete Camera SettingsControls & HowSettings to Adjust ThemMatrix

                All camera settings canare be adjustedavailable interactively in the DrHeck Camera Hub web UI (https://cam.drheck.dev/ — expand Camera Hardware Encoder, Bandwidth, Image & Protocol Settings on any camera card) or programmatically via POST /api/cameras/{ip}/control.:

                Category Setting Supported Range / Values FactoryDefault Defaulton 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 (plus Autofocus) Auto 295 (StartZoomFocus) Focus slider (action: "focus") LightingOptics & PTZ Floodlight3D /Click-to-Zoom Spotlight State(Set3DPos) 0posX, 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 1true (On) + baseline_zoom 0false (Off) 288445 (+ SetWhiteLed295) Spotlight:Auto-Zoom ON/OFFon Moving Objects (action: "spotlight"auto_zoom_config") Optics & PTZ Autofocus Lock false (Auto) or true (Locked) false (Auto) 224 / 225 (SetAutoFocus) Autofocus Lock (action: "autofocus") Lighting SpotlightFloodlight Manual Toggle & Brightness `state: true false1, brightness: 1... 100 (%)100` 85Off, 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 Light %289 slider/ 290 (FloodlightTask) Spotlight Automatic Mode / Triggers / Duration (action: "spotlight"floodlight_config") Audio / AlarmLighting 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 / Manual Off 276263 (AudioAlarmPlay) Siren (1x) button (action: "siren") Deterrents & Audio / Alarm Live Microphone Audio Stream 16 kHz AAC -> 64 kbps MP3 Enabled (<audio>1</audio>) 57 (SetEnc) + RTSP Audio: Muted / LIVE button (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 / Alarm440 (SetAudioNoise) Mic 3D Noise Reduction (action: "audio_noise") Deterrents & Audio Speaker Volume 0 .. 100 (%) 92 265 (SetAudioCfg) Speaker Volume slider (action: "volume") OSD OverlaysPrivacy ReolinkPrivacy Logo/ WatermarkSleep Mode 0false (Hidden)Awake) or 1true (Visible)Sleeping) 0false (DisabledAwake) by574 / cam575 (set_privacy_mode) 45Privacy Sleep (SetOsd) Reolink Logo Watermarkbutton (action: "osd", watermark: falseprivacy_mode") OSD OverlaysPrivacy CameraHardware NamePrivacy &Mask Timestamp(Shelter) 0false (Off) or 1true (On) 1false (On)Off) 4552 / 53 (SetOsdSetMask) OSDHardware CameraPrivacy Name / TimestampMask (action: "osd") Sub-Stream H.264 Bitrate (640x360) 64, 128, 160, 192, 256, 384, 512 kbps 256 kbps 57 (SetEnc) Sub-Stream Bitrate (action: "encoding") Sub-Stream H.264 Frame Rate 4, 7, 10, 15 fps 10 fps 57 (SetEnc) Sub-Stream Frame Rate (action: "encoding") Main-Stream H.265 4K Bitrate (3840x2160) 1024, 1536, 2048, 3072, 4096, 5120, 6144, 7168, 8192 kbps 6144 kbps 57 (SetEnc) Main-Stream Bitrate (action: "encoding") Main-Stream H.265 4K Frame Rate 2, 4, 6, 8, 10, 12, 15, 16, 18, 20, 22, 25 fps 25 fps 57 (SetEnc) Main-Stream Frame Rate (action: "encoding"privacy_mask") Image (ISP)& OSD Mounting / Orientation (mirror, flip) Normal, 180° Upside-Down, Flip, Mirror 0 / 0 (Normal) 25 (SetImage / SetIsp) Flip 180° button & Mounting / Orientation (action: "image", flip: true, mirror: true) Image (ISP) Brightness (bright) 0 .. 255 128Normal 25 (SetImage) BrightnessFlip 180° sliderbutton (action: "image") Image (ISP)& OSD ContrastReolink Logo Watermark false (Hidden) or true (Visible) false (Hidden) 45 (contrastSetOsd) 0Reolink ..Logo 255Watermark 128 25 (SetImage) Contrast slider (action: "image"osd") ImageTime (ISP)& System SaturationNTP Server & Clock Sync time.google.com:123 (saturationEDT/EST) 0 .. 255time.google.com 12838 / 39 (SetNtp) & 105 25Set time.google.com (& SetImage)Sync SaturationEDT Clock (action: "image"ntp", action: "sync_time") ImageTime (ISP)& System SharpnessReboot Camera Hardware reboot On-demand 23 (sharpenreboot) 0Reboot .. 255Camera 128 25 (SetImage) Sharpness slider (action: "image") Protocols Network Ports rtsp (554), onvif (8000), rtmp (1935), http (80), https (443) 9000 + 554 36 (SetNetPort) API (action: "port"reboot")
                REST API Examples for Adjusting Camera Settings
                # Toggle Spotlight ON at 75% brightness on 10.0.0.122
                curl -X POST http://[fd77:7777:5010:0:1337:f1ac:d00d:ca30]:8000/api/cameras/10.0.0.122/control \
                  -H "Content-Type: application/json" \
                  -d '{"action": "spotlight", "state": true, "brightness": 75}'
                
                # Set Optical Zoom to 14 (2.5X)
                curl -X POST http://[fd77:7777:5010:0:1337:f1ac:d00d:ca30]:8000/api/cameras/10.0.0.122/control \
                  -H "Content-Type: application/json" \
                  -d '{"action": "zoom", "value": 14}'
                
                # Reduce on-camera H.264 sub-stream encoder to 128 kbps @ 7 fps
                curl -X POST http://[fd77:7777:5010:0:1337:f1ac:d00d:ca30]:8000/api/cameras/10.0.0.122/control \
                  -H "Content-Type: application/json" \
                  -d '{"action": "encoding", "sub_bitrate": 128, "sub_fps": 7}'
                
                # Adjust ISP Image Brightness and Sharpness
                curl -X POST http://[fd77:7777:5010:0:1337:f1ac:d00d:ca30]:8000/api/cameras/10.0.0.122/control \
                  -H "Content-Type: application/json" \
                  -d '{"action": "image", "bright": 135, "sharpen": 140}'
                

                Authentik Access Control (camera_access Group)

                Access to https://cam.drheck.dev is restricted exclusively to members of the camera_access group in Authentik:

                  Authorized Members: luke, ikura, haruka Enforcement Layer 1 (Edge ForwardAuth PolicyBinding):
                    In Authentik, the Cameras application (slug = "cam") has an active PolicyBinding targeting group camera_access. Every HTTP request to https://cam.drheck.dev triggers an Nginx auth_request /outpost.goauthentik.io/auth/nginx subrequest. Unauthenticated users are redirected to https://auth.drheck.dev, and authenticated users who are not in camera_access are denied at the proxy edge. Enforcement Layer 2 (Application Defense-in-Depth):
                      Nginx forwards X-authentik-username and X-authentik-groups headers to the cam backend. check_camera_access_headers() in /data/docker/cam/app.py splits X-authentik-groups on | and verifies camera_access membership on every route (/, /tv, /cam-googletv.apk, /api/*), returning HTTP 403 Forbidden if missing.
                      Managing camera_access Group Membership via CLI
                      ssh ul 'docker exec -i authentik-server ak shell << "PY"
                      from authentik.core.models import Group, User
                      grp = Group.objects.get(name="camera_access")
                      print("Current members:", [u.username for u in grp.users.all()])
                      # To add or set members:
                      grp.users.set(User.objects.filter(username__in=["luke", "ikura", "haruka"]))
                      grp.save()
                      PY'
                      

                      Bandwidth Adjustments for Unreliable or Slow Internet

                      When viewing two cameras simultaneously over a slow, high-latency, or lossy internet connection (cellular tethering, hotel Wi-Fi, or rural WAN),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).

                      cam.drheck.dev provides two independent bandwidth controls:

                      1. Per-Viewer Stream Presets (Top Toolbar on cam.drheck.dev & /tv)

                      Changing the Bandwidth / Mode dropdown in the top bar adjusts server-side scaling, frame rate decimation, and JPEG compression for your browser session without affecting other viewers:

                      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

                      Tip for

                      Authentik HighAccess Packet Loss Links:

                       Continuous multipart MJPEG streams use a single long-lived HTTP TCP response. On connections with heavy packet loss where TCP head-of-line blocking stalls long streams, switch the dropdown to Unreliable WAN SnapshotControl (Everycamera_access 2s) or Minimal WAN Snapshot (Every 5s). Snapshot modes issue independent, stateless HTTP GET requests that recover immediately from dropped packets.

                      2. On-Camera Hardware H.264 Sub-Stream Bitrate Tuning

                      Inside each camera card's Camera Hardware Encoder, Bandwidth, ImageGroup) & Protocol Settings drawer, you can also lower the camera's internal H.264 hardware encoder (SetEnc cmd_id = 57) from 256 kbps @ 10 fps down to 64 kbps @ 4 fps (64, 128, 160, 192, 256, 384, 512 kbps).


                      Google TV /App

                      Android
                        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 (cam-googletv.apk)

                        A signed, sideloadable Android TV / Google TV application (DrHeck Cameras, package dev.drheck.cam) is built and hosted directly on cam.drheck.dev at:

                        :
                        • Built APK Location on ul (Not Served over HTTPS): /data/docker/cam/googletv_src/cam-googletv.apk
                        • 10-Foot TV Web Interface:Interface: https://cam.drheck.dev/tv
                        Source Directory on ul: /data/docker/cam/googletv_src/ (AndroidManifest.xml,authenticated MainActivity.smali,automatically res/drawable/tv_banner.png,via res/drawable/ic_launcher.png)

                        Features of the Google TV App

                          Native Google TV Home Screen Banner (LEANBACK_LAUNCHER): Declares android.intent.category.LEANBACK_LAUNCHER and a 320x180 android:banner resource so the app appears natively baked-in the Google TV Your Apps row. Wake-Lock (FLAG_KEEP_SCREEN_ON): Sets WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON (0x80) on the window so Google TV never dims or enters ambient screensaver mode while monitoring the cameras. Zero-Sign-In Baked-In Authentication (v2.0): Embeds a 256-bit pre-shared token (TV_AUTH_TOKEN) directly into the WebView CookieManager (cam_tv_token), User-Agent (CamTVToken/...), and request headers (X-Cam-Tv-Token), verified at both the Nginx edge and FastAPI backend (hmac.compare_digest) so the Android TV app never requires interactive sign-in. D-Pad Remote Navigation:
                            Left / Right / Up / Down: Highlight Camera 1 (10.0.0.122), Camera 2 (10.0.0.123), 2-Up Grid, Mode (cycles Standard 10fps -> Low-BW 5fps -> Ultra-Low 2fps -> HD 720p 10fps), or Spotlight Toggle. Center / OK (DPAD_CENTER / Enter): Toggle the selected camera between 2-Up Grid and Full-Screen view. Up / Down (while Full-Screen): Smoothly step the camera's 5X motorized optical zoom (+2 / -2). Back Button: Exits full-screen camera view back to the 2-Up Grid.

                            How to Sideload onto Google TV

                            Option A: Via ADB over Wi-Fi / Ethernet (Fastest from a Laptop/Desktop)

                              On your Google TV, open Settings -> System -> About and click Android TV OS build 7 times to enable Developer options. Open Settings -> System -> Developer options and enable USB debugging (or Wireless debugging). Note the Google TV's IP address (<googletv-ip>). Download and install the APK from your workstation:
                              scp ul:/data/docker/cam/googletv_src/cam-googletv.apk /tmp/cam-googletv.apk
                              adb connect <googletv-ip>:5555
                              adb install -r /tmp/cam-googletv.apk