How Helen Gets Made A making-of, not the live show Watch her live

Frigate · cameras · the setup we actually use

Frigate camera setup: get one honest stream per job into Frigate

A camera is a job in the room. Getting its picture into Frigate is four things: a login, an address, two stream paths, and a name that says the job.

One camera, start to finish. The full config with all eleven cameras is the next page.

Helen, a dilute tortoiseshell calico, at the water bowl on the camera Frigate knows as cat_water_bowl
cat_water_bowl. One camera, one job, one name in three places: Frigate, the public proxy, the Shorts pipeline.

Ours are TP-Link Tapo C120 and C210 units on Wi-Fi. Nothing below is specific to Tapo beyond the menu names; anything that serves RTSP goes in the same way, and the two things most likely to go wrong (a camera whose address changes, and a camera block whose stream paths still point at the previous camera) have nothing to do with the maker. When you want the whole file rather than one camera's worth, it is on the annotated config page. If you are still choosing cameras, which cameras work with Frigate comes first, and the cameras page explains why we have five jobs and not one wide shot.

The rule

One camera per job, named by the job. Water watches the fountain. Food watches the bowl. Treat watches the dispenser. Court watches the whole floor from above. Face is close enough to be a portrait. In Frigate those are cat_water_bowl, cat_food_bowl, cat_treat_dispenser, cat_scratching_pad and helen_food_face. Two more watch the bed and the playroom. The name follows the camera into everything downstream: the public proxy's allowlist, the pipeline's station map, the file names of the clips. Pick it once, before you save.

The camera side, before Frigate

Three things on the camera, none of them in Frigate.

A camera account. Tapo cameras do not let you use your cloud login for RTSP. In the Tapo app: the camera → Advanced → Camera Account. Set a username and a password. That pair is what goes into every RTSP URL; it is <CAMERA_USER> and <CAMERA_PASSWORD> throughout this site. We use the same pair on every camera, kept in a password manager. TP-Link's RTSP/ONVIF FAQ walks through it with screenshots.

A reserved address. On the router, give the camera's MAC a DHCP reservation so 192.168.1.<N> is always the same camera. A camera that changes address is a camera Frigate silently stops recording. Network hygiene has the table we keep.

The two paths. Every Tapo camera serves two RTSP streams on port 554: /stream1 is the main stream (2560×1440 on the C120, 2304×1296 on the C210) and /stream2 is the sub-stream at 640×360. Both carry H.264 video and a small PCMA/8000 audio track. Both are always on; you do not enable them.

Why two streams

Frigate does two different things with a camera, and they want different pictures. Detection looks at a small frame a couple of times a second and asks "is there a cat in it?" — 640×360 at 2 fps is more than enough for an animal that lingers at a bowl, and it keeps the decode cost and the detector cost tiny. Recording keeps the full-resolution main stream untouched, because the clip is what gets cut into a Short later. So: stream2 gets the detect role, stream1 gets the record role. Detecting on the main stream is the usual reason a Frigate box runs hot.

Why go2rtc in the middle

Frigate ships with go2rtc, a restreamer. Instead of Frigate pulling from the camera directly, go2rtc pulls each stream from the camera once and republishes it on rtsp://127.0.0.1:8554/<name>. Then anything that wants the picture takes it from go2rtc: Frigate's detect process, Frigate's record process, the ffmpeg that pushes the 24/7 YouTube stream, all without a second connection to the camera. Cheap Wi-Fi cameras get unhappy with more than one or two RTSP clients; with go2rtc they only ever see one.

The convention we use: <name> for the main stream, <name>_sub for the sub-stream. That is what the camera block below points at.

One camera, the whole block
go2rtc:
  streams:
    cat_water_bowl:
      - rtsp://<CAMERA_USER>:<CAMERA_PASSWORD>@192.168.1.<N>:554/stream1
    cat_water_bowl_sub:
      - rtsp://<CAMERA_USER>:<CAMERA_PASSWORD>@192.168.1.<N>:554/stream2

cameras:
  cat_water_bowl:
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cat_water_bowl_sub
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cat_water_bowl
          roles:
            - record
    detect:
      width: 640
      height: 360
      fps: 2
      enabled: true
    audio:
      enabled: false
    objects:
      track:
        - cat
        - person

person is on a cat cam's track list because the Shorts pipeline refuses to publish a visit with a person in frame, and it can only refuse what Frigate detected. The config page explains the thresholds.

The naming and allowlist idea

The house has three more cameras — front door, back yard, carport — that are in Frigate for the ordinary reason people have cameras. They are configured differently: they pull from the camera directly with no go2rtc entry, because nothing but Frigate needs them; they have detect: enabled: false; and their names never appear in the public proxy's allowlist. A camera that is not in go2rtc cannot be restreamed, and a camera not in the allowlist cannot be seen from the website. How the four public cameras get out safely is its own page.

  1. Decide the job, then mount the camera. If you cannot say the job in one word, do not add the camera yet. Mount at the animal's height for bowls, overhead for the whole room. The cameras page shows ours.
  2. Create the camera account in the maker's app. Tapo: Advanced → Camera Account. Write the username and password into your password manager as the camera login. Do not reuse your Tapo cloud password.
  3. Reserve the address on the router. Find the camera's MAC in the app or the router's client list, add a DHCP reservation, and reboot the camera so it picks it up.
  4. Open both streams in VLC or ffprobe. rtsp://user:pass@192.168.1.N:554/stream1 and /stream2. If VLC will not play them, Frigate will not either; fix that first. Note the sub-stream resolution — 640×360 on Tapo.
  5. Add both to go2rtc. Two entries under go2rtc: streams:, named <name> and <name>_sub. Save the config and let Frigate restart go2rtc.
  6. Add the camera block. Copy the block above. Change the name in five places: both go2rtc keys, the camera key, and the two path: lines under inputs that point at them. Miss the paths and the new camera silently watches cat_water_bowl's streams. Sub for detect, main for record, 640×360 at 2 fps. Track cat and person.
  7. Restart Frigate and run the checks. Five things, in order: a picture in the maker's app, ffprobe on the RTSP URL, the camera listed in /api/stats, camera_fps close to what you set, skipped_fps at 0.0.

The checks, as commands

Before you trust a camera
# 1. the camera answers on RTSP at all (from any machine on the LAN)
ffprobe -rtsp_transport tcp "rtsp://<CAMERA_USER>:<CAMERA_PASSWORD>@192.168.1.<N>:554/stream2"
#   look for: Video: h264 ... 640x360   and   Audio: pcm_alaw, 8000 Hz

# 2. go2rtc has it (after a config reload)
curl -s http://127.0.0.1:5000/api/go2rtc/streams | python -c "import sys,json; print(list(json.load(sys.stdin)))"

# 3. Frigate is keeping up
curl -s http://127.0.0.1:5000/api/stats | python -c "import sys,json; c=json.load(sys.stdin)['cameras']['cat_water_bowl']; print(c['camera_fps'], c['skipped_fps'], c['detection_fps'])"
#   2.1 0.0 2.0

Frigate's own camera-specific docs list quirks for other makers (Reolink, Amcrest, Dahua, Hikvision); Tapo needs nothing special beyond the camera account. If a camera shows camera_fps 0.0 with everything else alive, it is the camera or the Wi-Fi, not Frigate: one of ours (a house camera) was doing exactly that when this page was written.