๐Ÿฆ BirdWatchAI Manual Part 4 ยท Camera Hardware Community Feed
Part 4

Camera Hardware

Everything about the camera end of the system โ€” what works, how to wire it up, and where to point it. Most installs use an off-the-shelf RTSP camera (TP-Link Tapo is the most popular). The server edition also supports a wired Raspberry Pi Camera Module on the CSI ribbon cable.

RTSP cameras

RTSP (Real-Time Streaming Protocol) is a standard way for cameras to send live video over a network. BirdWatchAI connects to your camera with an RTSP address that looks like this:

rtsp://username:password@camera_ip:port/stream_path

For example: rtsp://birduser:secret123@192.168.1.105/stream1. The pieces are:

Common stream paths by brand:

BrandStream pathNotes
TP-Link Tapo/stream1 (HD) ยท /stream2 (SD)See Tapo section below for which to use on which model
Wyze (RTSP firmware)/liveRequires custom RTSP firmware flashed
Amcrest / Dahua/cam/realmonitor?channel=1&subtype=0
Reolink/h264Preview_01_main
Hikvision/Streaming/Channels/101
Test in VLC first If you have VLC Media Player, you can verify an RTSP URL works before using it here: Media โ†’ Open Network Stream (Ctrl+N), paste the URL, and click Play. If VLC shows live video, BirdWatchAI will connect too.

TP-Link Tapo step-by-step

Tapo cameras (C100/C110/C113/C120/C200/C210/C310/C320WS/C500/C510W/C520WS, etc.) are popular, affordable, and well supported. The most important thing to understand is the Camera Account.

The Camera Account is separate from your Tapo login RTSP requires a dedicated Camera Account that you create inside the Tapo app. This is not the same as your TP-Link / Tapo cloud login. Use a different username and password for it.

Create the Camera Account (for RTSP)

  1. Open the Tapo app and tap your camera to open Live View.
  2. Tap the โš™ gear (top right) โ†’ Advanced Settings โ†’ Camera Account.
  3. Tap Understand and Agree to Use.
  4. Set a username (6โ€“32 characters) and password (6โ€“32 characters), then Save. Use these in BirdWatchAI's RTSP fields.

Find the camera's IP address

Tapo app โ†’ โš™ gear โ†’ Device Info โ†’ IP Address (e.g. 192.168.1.105). Alternatively, check your router's connected-devices list for a name like TAPO_C120_XXXX.

Streams & quality โ€” which stream path to use

Tapo cameras expose two RTSP streams:

Which one to use depends on the model:

ModelRecommendedWhy
C113 (and similar mid-range) /stream2 720p; reliable, easy on Wi-Fi, plenty of detail for identification.
C120 and most lower-cost models /stream1 at 1080p Their /stream2 caps at 640ร—360, which loses too much detail for the AI to identify reliably.
Any Tapo at 2K main stream Avoid 2K saturates the camera's Wi-Fi uplink and causes H.264 corruption and instability. Drop to 1080p in the Tapo app first.

For the C120 and friends, set Tapo app โ†’ Camera Settings โ†’ Video Quality โ†’ 1080p, then use /stream1.

Quick reference

SettingValue
RTSP Port554
ONVIF Port (motion events)2020
Camera account username / password6โ€“32 characters each
Stream limits Tapo cameras allow only a limited number of simultaneous RTSP streams. If you also run TAPO Care cloud recording, microSD recording, and an NVR at the same time, RTSP may stop working โ€” disable one of them if you have connection trouble.

Optional: remote camera reboot (desktop only)

The desktop app can power-cycle a frozen Tapo camera automatically (or on demand via the tray menu's ๐Ÿ”„ Restart Camera). This feature needs your TP-Link cloud account email and password, entered in Settings โ†’ Camera (RTSP) โ†’ TAPO Camera Reboot. These are your cloud-login credentials, distinct from the RTSP camera account.

Reserving the camera's IP in your router

Strongly recommended for every camera By default, your router hands out IP addresses dynamically (via DHCP), which means your camera's address can change after a power outage, a reboot, or simply over time. If the camera's IP changes, BirdWatchAI will no longer find it at the old address and the connection will fail until you update the IP by hand. A DHCP reservation tells the router to always give this particular camera the same IP address.

Every router brand has a slightly different menu, but the concept is identical everywhere:

  1. Open your router's admin page in a web browser (commonly 192.168.1.1 or 192.168.0.1 โ€” check the label on your router) and sign in.
  2. Find the DHCP settings. Depending on the brand this lives under a menu such as LAN, Network, DHCP Server, Address Reservation, or Connected Devices / Client List.
  3. Locate your camera in the list of connected devices (look for a name like TAPO_C120_XXXX, or match it by its MAC address โ€” a unique hardware ID printed on the camera and shown in the camera app under Device Info).
  4. Choose Reserve / Bind / Add Static Lease for that device, and either keep its current IP or assign one you'll remember.
  5. Save / apply. Then reboot the camera (or wait for its lease to renew) so it picks up the reserved address.
  6. Use that same reserved IP in BirdWatchAI's Camera IP Address field.
Where to find the exact steps for your router Search the web for "[your router brand/model] DHCP reservation" (for example, "Netgear Nighthawk address reservation" or "TP-Link bind IP to MAC"). The terminology differs by brand, but you're always doing the same thing: tying the camera's MAC address to a fixed IP. If you can't reserve in the router, an alternative is to set a static IP directly in the camera's own settings โ€” just make sure it's outside the router's automatic DHCP range to avoid conflicts.

Other camera brands

Any RTSP camera works. General tips:

Raspberry Pi camera (CSI ribbon, server only)

The server edition supports a wired Arducam / Raspberry Pi Camera Module attached over the CSI ribbon cable, as an alternative to RTSP. Capture goes through libcamera (the modern Pi camera stack), not legacy v4l2 โ€” so the container needs broader access to the Pi's hardware than a USB webcam would.

One-time setup

  1. Plug the ribbon cable in with the Pi powered off. Lift the CSI port's clip, slide the ribbon in (contacts toward the HDMI port on Pi 4 / 5), press the clip back down.
  2. Enable the camera interface on the Pi. On Pi OS Bookworm, sudo raspi-config โ†’ Interface Options โ†’ Camera โ†’ Yes โ†’ Finish โ†’ reboot. (No-op on most fresh installs: libcamera + v4l2 compat are enabled by default.)
  3. Verify the OS sees it. SSH in and run libcamera-hello --list-cameras โ€” you should see at least one camera listed (e.g. imx519 for an Arducam motorized-lens module, imx708 for the Camera Module 3, ov5647 for the original v1 module). If "No cameras available!", go back to the ribbon-cable seat โ€” that's the most common cause.
  4. Edit ~/birdwatch/docker-compose.yml to grant camera access. The file ships with a single commented-out line under the "Pi camera support" block: # privileged: true. Uncomment it (delete the leading # , keep the indentation matching the lines above it like restart: and ports:). That's the entire compose change.
  5. Recreate the container so the new mode takes effect:
    cd ~/birdwatch
    docker compose up -d --force-recreate birdwatch
  6. Switch the camera type in the dashboard. Open http://<your-host>:8080 โ†’ Settings โ†’ Camera โ†’ set Camera type to Pi camera โ†’ leave the device path at 0 (libcamera's camera index; the field also accepts /dev/video0 for compatibility) โ†’ click Test camera. A frame should come back within a few seconds. Save.
Why privileged mode and not selective device passthrough? libcamera reads the host's device tree at /proc/device-tree/model to confirm "this is a Raspberry Pi" before it'll initialize the camera stack. Docker mounts its own procfs over /proc after applying bind mounts, so a - /proc/device-tree:/proc/device-tree:ro mount gets shadowed and the platform check fails ("No cameras available!" inside the container even though all the video / media nodes are wired through). Granular device passthrough was the original approach and works on Bullseye but not Bookworm. Privileged mode grants the container the host's full device + sysfs view in one line โ€” the standard pattern for libcamera in Docker.

If Test camera errors out

The most useful diagnostic is, from the host shell:

docker exec birdwatch rpicam-hello --list-cameras

Run inside the container โ€” if it lists your sensor, the access path works and the issue is on the app side. If it says "No cameras available!" inside the container but works on the host, you likely missed step 4 (the privileged: true uncomment). Confirm with:

docker inspect birdwatch --format '{{.HostConfig.Privileged}}'

It should print true.

The existing motion + identify pipeline runs on the Pi camera feed the same as on RTSP โ€” frame-diff motion detection is the default trigger (Settings โ†’ Detection โ†’ Motion detection threshold). ONVIF doesn't apply to wired cameras.

Placement & lighting

The single biggest accuracy improvement you can make isn't a setting โ€” it's a better view of the bird.

The recommended camera For most installs the TP-Link Tapo C113 is the best bang for the buck (~$30 at the time of writing) โ€” 720p, great color, weather- resistant variants available, and the default /stream2 just works.