ip cameras
Service Summary: The DrHeck Camera Hub (https://cam.drheck.dev) provides automatic LAN discovery, low-latency live streaming, optical zoom/spotlight/siren hardware controls, 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
Two Reolink RLC-811A (P430) 4K 8MP PoE Spotlight IP cameras are connected to the 10.0.0.0/24 LAN on interface eth77 of host ul:
| Property | Camera 1 (RLC-811A (122)) |
Camera 2 (RLC-811A (123)) |
|---|---|---|
| IPv4 Address | 10.0.0.122 |
10.0.0.123 |
| 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) |
5X Motorized (ZoomPos 0..28, FocusPos 0..238) |
| Illumination | IR Night Vision + 450 lm Warm Floodlight (1..100%) |
IR Night Vision + 450 lm Warm Floodlight (1..100%) |
| Audio | Two-Way Audio (16 kHz AAC) + Integrated Siren |
Two-Way Audio (16 kHz AAC) + Integrated Siren |
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, 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 + AAC audio. |
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:
- Binary Framing Header: Every Baichuan packet begins with a 20-byte or 24-byte little-endian binary header starting with magic bytes
0xf0debc0a, followed bycmd_id(uint32), payload length (uint32),channel_id(uint8), status code (200OK,400Bad Request), and payload offset. - Modern Nonce Authentication (
cmd_id = 1):- The client sends an initial unauthenticated
cmd_id = 1request. - The camera replies with an XML
<Encryption>challenge containing a random<nonce>. - The client computes uppercase MD5 digests of
username + nonceandpassword + 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.
- The client sends an initial unauthenticated
- Key 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 enablesrtsp(554/tcp),onvif(8000/tcp),rtmp(1935/tcp),http(80/tcp), andhttps(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 (main4K orsub640x360) 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 (bitRatein kbps) formainStreamandsubStream.cmd_id = 26/25(GetImage/SetImage): Reads and updates ISP sensor parameters (bright,contrast,saturation,hue,sharpen,DayNight,nr3d).cmd_id = 264/265(GetAudioCfg/SetAudioCfg): Reads and updates speaker volume (0..100).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 (<OsdChannelName><enable>0|1</enable></OsdChannelName>), and timestamp overlay (<OsdDatetime><enable>0|1</enable></OsdDatetime>).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): Moves the 5X motorized varifocal lens to an exact zoom step (ZoomPos 0..28) or focus step (FocusPos 0..238).cmd_id = 276(AudioAlarmPlay): Triggers the built-in audible security siren.
3. RTSP Stream Endpoints (554/tcp)
Once rtspEnable = 1 is set via Baichuan cmd_id = 36, each camera serves two RTSP streams:
- Sub Stream (Low-Latency H.264):
Encoded as H.264 High Profile (rtsp://admin:<password>@10.0.0.122:554/h264Preview_01_sub rtsp://admin:<password>@10.0.0.123:554/h264Preview_01_subyuv420p,640x360, default10 fpsat256 kbps, GOP =4) with16 kHzmono AAC audio. - Main Stream (4K UHD H.265/HEVC):
Encoded as HEVC / H.265 (rtsp://admin:<password>@10.0.0.122:554/h265Preview_01_main rtsp://admin:<password>@10.0.0.123:554/h265Preview_01_mainyuvj420p,3840x2160, default25 fpsat6144 kbps, GOP =2) with16 kHzmono 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 | /data/docker/cam/data/cameras.json |
| Container Name | cam (cam-hub:latest, Python 3.12 + FastAPI + reolink-aio + 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, WebSocket + streaming support) |
| 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) |
How cam.drheck.dev Communicates With the Cameras
- Zero-Config Discovery (
discover_cameras):- Reads the host kernel ARP table (
/proc/net/arpmounted read-only at/host_proc_arp). - Filters for Reolink IEEE MAC OUI prefixes (
ec:71:dband9c:8e:cd) and probes TCP ports9000and554across10.0.0.0/24(excluding infrastructure router/switch IPs). - Connects to each discovered Reolink camera on
9000/tcp, queries hardware metadata (cmd_id = 80), network ports (cmd_id = 37), encoder settings (cmd_id = 56), ISP image settings (cmd_id = 26), and audio volume (cmd_id = 264). - If
rtsp(554/tcp) is disabled on a newly plugged-in camera,inspect_reolink_cameraautomatically sendsSetNetPort(rtspEnable=1)(cmd_id = 36) so live streaming works immediately without requiring the proprietary Reolink desktop/mobile client.
- Reads the host kernel ARP table (
- Hybrid Instant-Snapshot + FFmpeg MJPEG Streaming (
mjpeg_stream_generator):- Standard web browsers cannot natively decode raw RTSP or H.265 streams inside
<img>tags, and waiting for an RTSP H.264 IDR keyframe (GOP = 4) introduces a1–2 secondblank delay on initial load. - Furthermore,
RLC-811Asub-streams output limited-rangeyuv420p(progressive)frames; FFmpeg 7.1'smjpegencoder rejects non-full-range YUV unless explicit color-range conversion (format=yuvj420p) and-strict unofficialare specified. - To solve both problems,
/api/cameras/{ip}/mjpegexecutes a two-stage pipeline:- Stage 1 (
<150 msFirst Frame): Immediately fetches a single JPEG snapshot via Baichuancmd_id = 182and yields it as the first--framepart so the browser displays an image immediately. - Stage 2 (Continuous Live Transcode): Spawns
ffmpegover 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 back to streaming Baichuan JPEG snapshots at the requested interval.
- Stage 1 (
- Standard web browsers cannot natively decode raw RTSP or H.265 streams inside
- Integer State Normalization for Spotlight Control:
- Reolink's Baichuan
SetWhiteLed(cmd_id = 288) XML parser requires<status>1</status>or<status>0</status>and rejects Python boolean strings (<status>True</status>) with status code400.app.pynormalizesstatevianormalize_floodlight_state(req.state)to integer1or0.
- Reolink's Baichuan
Static IPs vs. DHCP Reservations & IPv6 Support
1. Should the Cameras Be Configured for Static IPs?
Yes — pinning the cameras' IPv4 addresses via static DHCP reservations 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 Reservation in
/etc/dhcpd.confondanknasty(Recommended):- Binds each camera's factory MAC address (
ec:71:db:f1:25:5aandec:71:db:6d:84:ce) 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 on
danknasty, IP assignment is centrally managed and versioned alongsidepikvm,nodegrid,kikuo, andfireboardctl:host cam1 { hardware ethernet ec:71:db:f1:25:5a; fixed-address 10.0.0.122; } host cam2 { hardware ethernet ec:71:db:6d:84:ce; fixed-address 10.0.0.123; }
- Binds each camera's factory MAC address (
- On-Camera Static IP via Baichuan
cmd_id = 75(SetLocalLink):- The camera firmware stores its IPv4 configuration in
<LocalLink>(cmd_id = 76to read,cmd_id = 75to 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.devautomatically discovers the new IP by matchingec:71:db:*in/proc/net/arp.
- The camera firmware stores its IPv4 configuration in
2. Do the Cameras Support IPv6?
- Camera Hardware (
RLC-811AFirmwarev3.1.0.4695_2504301440): No native IPv6 support.- Inspection of
ip -6 neigh show dev eth77confirms that neitherec:71:db:f1:25:5anorec:71:db:6d:84:ceconfigures an IPv6 link-local (fe80::/10), SLAAC, or DHCPv6 address, and the BaichuanLocalLink(cmd_id = 76) schema only supports 32-bit IPv4 fields.
- Inspection of
- Service Frontend (
cam.drheck.dev): Full Dual-Stack & IPv6 Support.- The
camcontainer on hostulbinds to dedicated ULA IPv6 addressfd77:7777:5010:0:1337:f1ac:d00d:ca30(port8000) and is served publicly by Nginx over dual-stack IPv4 and IPv6 (2603:3001:626:9de0:1337:f1ac:d00d:aaaa). Hostultranslates incoming IPv6 HTTPS requests to IPv4 Baichuan/RTSP camera traffic on10.0.0.0/24.
- The
Available Camera Settings & How to Adjust Them
All camera settings can be adjusted 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 | Factory Default | Baichuan cmd_id |
Web UI / API Action |
|---|---|---|---|---|---|
| Optics | Optical Zoom (ZoomPos) |
0 .. 28 (1X .. 5X optical) |
0 |
295 (StartZoomFocus) |
Zoom slider (action: "zoom") |
| Optics | Optical Focus (FocusPos) |
0 .. 238 (plus Autofocus) |
Auto | 295 (StartZoomFocus) |
Focus slider (action: "focus") |
| Lighting | Floodlight / Spotlight State | 0 (Off) or 1 (On) |
0 (Off) |
288 (SetWhiteLed) |
Spotlight: ON/OFF (action: "spotlight") |
| Lighting | Spotlight Brightness | 1 .. 100 (%) |
85 |
288 (SetWhiteLed) |
Light % slider (action: "spotlight") |
| Audio / Alarm | Security Siren | Trigger 1x / Manual | Off | 276 (AudioAlarmPlay) |
Siren (1x) button (action: "siren") |
| Audio / Alarm | Live Microphone Audio | 16 kHz AAC -> 64 kbps MP3 |
Enabled (<audio>1</audio>) |
57 (SetEnc) + RTSP |
Audio: Muted / LIVE button (GET /api/cameras/{ip}/audio.mp3) |
| Audio / Alarm | Speaker Volume | 0 .. 100 (%) |
92 |
265 (SetAudioCfg) |
Speaker Volume slider (action: "volume") |
| OSD Overlays | Reolink Logo Watermark | 0 (Hidden) or 1 (Visible) |
0 (Disabled by cam) |
45 (SetOsd) |
Reolink Logo Watermark (action: "osd", watermark: false) |
| OSD Overlays | Camera Name & Timestamp | 0 (Off) or 1 (On) |
1 (On) |
45 (SetOsd) |
OSD Camera Name / Timestamp (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") |
| Image (ISP) | 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 |
128 |
25 (SetImage) |
Brightness slider (action: "image") |
| Image (ISP) | Contrast (contrast) |
0 .. 255 |
128 |
25 (SetImage) |
Contrast slider (action: "image") |
| Image (ISP) | Saturation (saturation) |
0 .. 255 |
128 |
25 (SetImage) |
Saturation (action: "image") |
| Image (ISP) | Sharpness (sharpen) |
0 .. 255 |
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") |
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:
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), 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 High 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 Snapshot (Every 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, Image & 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 / Android 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:
- Download URL:
https://cam.drheck.dev/cam-googletv.apk - 10-Foot TV Web Interface:
https://cam.drheck.dev/tv - Source Directory on
ul:/data/docker/cam/googletv_src/(AndroidManifest.xml,MainActivity.smali,res/drawable/tv_banner.png,res/drawable/ic_launcher.png)
Features of the Google TV App
- Native Google TV Home Screen Banner (
LEANBACK_LAUNCHER): Declaresandroid.intent.category.LEANBACK_LAUNCHERand a320x180android:bannerresource so the app appears natively in the Google TV Your Apps row. - Wake-Lock (
FLAG_KEEP_SCREEN_ON): SetsWindowManager.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 WebViewCookieManager(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(cyclesStandard 10fps->Low-BW 5fps->Ultra-Low 2fps->HD 720p 10fps), orSpotlight Toggle. - Center / OK (
DPAD_CENTER/Enter): Toggle the selected camera between2-Up GridandFull-Screenview. - Up / Down (while Full-Screen): Smoothly step the camera's
5Xmotorized optical zoom (+2/-2). - Back Button: Exits full-screen camera view back to the
2-Up Grid.
- Left / Right / Up / Down: Highlight Camera 1 (
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:
curl -L -o /tmp/cam-googletv.apk https://cam.drheck.dev/cam-googletv.apk adb connect <googletv-ip>:5555 adb install -r /tmp/cam-googletv.apk
Option B: Directly on the Google TV (Using the "Downloader" App)
- Install Downloader by AFTVnews from the Google Play Store on your Google TV.
- In Settings -> Security & Restrictions (or Apps -> Special app access -> Install unknown apps), allow Downloader to install unknown apps.
- Open Downloader, enter
https://cam.drheck.dev, sign in with your Authentik account (luke,ikura, orharuka), and click the Google TV App (.apk) button in the top-right toolbar to download and installcam-googletv.apk.