Skip to main content

Frigate & Google Coral and Proxmox VM

Bought items:

image.png

Good Youtube Tutorial: https://www.youtube.com/watch?v=zKk9dnAp8FM

In Proxmox Node:

lsusb

root@orange:/etc/pve/lxc# lsusb
Bus 008 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 007 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 003: ID 18d1:9302 Google Inc. 
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 8087:0029 Intel Corp. AX200 Bluetooth
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Setup Ubuntu VM and Add USB device:

image.png

Restart VM

run lsusb to see if the vm has the USB

image.png

Install Docker and Portainer

Add this Docker Compose to install frigate

version: "3.9"
services:
  frigate:
    
    container_name: frigate
    privileged: true # this may not be necessary for all setups
    restart: unless-stopped
    stop_grace_period: 30s # allow enough time to shut down the various services
    image: ghcr.io/blakeblackshear/frigate:stable
    shm_size: "512mb" # update for your cameras based on calculation above
    devices:
      - /dev/bus/usb:/dev/bus/usb # Passes the USB Coral, needs to be modified for other versions
      - /dev/apex_0:/dev/apex_0 # Passes a PCIe Coral, follow driver instructions here https://coral.ai/docs/m2/get-started/#2a-on-linux
      #- /dev/video11:/dev/video11 # For Raspberry Pi 4B
      #- /dev/dri/renderD128:/dev/dri/renderD128 # For intel hwaccel, needs to be updated for your hardware
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /mnt/portainer2/frigate/config:/config
      - /mnt/portainer2/frigate/storage:/media/frigate
      - type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear
        target: /tmp/cache
        tmpfs:
          size: 1000000000
    ports:
      - "8971:8971"
      - "5000:5000" # Internal unauthenticated access. Expose carefully.
      - "8554:8554" # RTSP feeds
      - "8555:8555/tcp" # WebRTC over tcp
      - "8555:8555/udp" # WebRTC over udp
    environment:
      FRIGATE_RTSP_PASSWORD: "strong@pwd"

go to path VM IP:5000 to view the Frigate UI Configuration Editor

image.png

Twist your config like mine:

make sure to change username , password and ip address. Below is the 3 tapo c110 configuration url address

mqtt:
  enabled: false

cameras:
  tapo_username001: # <------ Name the camera
    enabled: true
    ffmpeg:
      inputs:
        - path: rtsp://tapo_username001:yourpassw@192.168.1.xxx:554/stream1 # <----- The stream you want to use for detection
          roles:
            - detect
            - record
    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      width: 2304
      height: 1296
      fps: 5
    motion:
      threshold: 30
      contour_area: 28
      improve_contrast: true
    record:
      enabled: true
      retain:
        days: 30
        mode: motion
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 30
  tapo_username002: # <------ Name the camera
    enabled: true
    ffmpeg:
      inputs:
        - path: rtsp://tapo_username002:yourpassw@192.168.1.xxx:554/stream1 # <----- The stream you want to use for detection
          roles:
            - detect
            - record
    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      width: 2304
      height: 1296
      fps: 5
    motion:
      threshold: 30
      contour_area: 28
      improve_contrast: true
    record:
      enabled: true
      retain:
        days: 30
        mode: motion
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 30
  tapo_username003: # <------ Name the camera
    enabled: true
    ffmpeg:
      inputs:
        - path: rtsp://tapo_username003:yourpassw@192.168.1.xxx:554/stream1 # <----- The stream you want to use for detection
          roles:
            - detect
            - record
    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      width: 2304
      height: 1296
      fps: 5
    motion:
      threshold: 30
      contour_area: 28
      improve_contrast: true
    record:
      enabled: true
      retain:
        days: 30
        mode: motion
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 30


record:
  enabled: true
  retain:
    days: 30
    mode: active_objects
  alerts:
    retain:
      days: 30
      mode: motion
  detections:
    retain:
      days: 30
      mode: motion

detectors:
  coral:
    type: edgetpu
    device: usb

objects:
  track:
    - person
    - face
    - printer
    - toy
    - filament
    - print_bed
    - extruder
    - tool
    - wrench
    - screw
    - spaghetti
    - failed_print


version: 0.15-1
camera_groups:
  SonA1:
    order: 1
    icon: LuFingerprint
    cameras:
      - tapo_username001
      - tapo_username002
      - tapo_username003

Click save and restart button

Tips:

Make sure to disable detection on your tapo settings, disable the local recording ( we don't need to use sd card for storage )

Go to the UI > Settings > Motion Tuner to update the Threshold and Contour Area to match your needs.

If you have google coral, it should have red label around the images.

image.png

Well done.


PCI Devices mapping in Proxmox


if you restart your VM or Host, the usb address id could change so that you need to map your host usb into your vm usb. Here is a quick run:

Remove your PCI Device in your VM Hardware setting.

SSH into your host pc which has the coral usb plugged in, mine is Orange 

lsusb -t


/:  Bus 08.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
/:  Bus 07.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
/:  Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
    |__ Port 2: Dev 3, If 0, Class=Vendor Specific Class, Driver=usbfs, 5000M << this is the one
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/5p, 480M
    |__ Port 5: Dev 2, If 0, Class=Wireless, Driver=btusb, 12M
    |__ Port 5: Dev 2, If 1, Class=Wireless, Driver=btusb, 12M

Bus 02, Port 2 → Driver=xhci_hcd → PCIe USB controller 

/sys/devices/pci0000:00/0000:00:08.1/0000:c5:00.3/usb2

PCI address: 0000:c5:00.3

Go to Data Center > Resource Mappings > Under PCI Devices Panel , click Add > Choose Mapping on Node: Orange

Scroll down and pick the id like the above, which is 0000:c5:00.3

give it a short Name: coralusb

click Create

image.png

Now go back to your VM and add your pci device into your vm hardware setting:

image.png

Pick your mapped device:

image.png


Done. Restart the VM.

Update on 29 May 2025, here is my frigate yaml configuration for both google coral and beelink ser7 gpu. This include go2rtc which will stream one connection to the camera and stream out to everything else.

mqtt:
  enabled: false
go2rtc:
  webrtc:
    candidates:
      - 192.168.1.114:8555
      - portainer2.kyluat.lan:8555
      - frigate:8555
  streams:
    son_user001:
      - rtsp://user001:{FRIGATE_RTSP_PASSWORD}@192.168.1.100:554/stream2
      - tapo://{FRIGATE_TAPO_PASSWORD}@192.168.1.100
      - ffmpeg:son_user001#audio=opus
    son_user001_record:
      - ffmpeg:rtsp://user001:{FRIGATE_RTSP_PASSWORD}@192.168.1.100:554/stream2#video=copy
      - tapo://{FRIGATE_TAPO_PASSWORD}@192.168.1.100

    # son_user001_sub:
    #   - rtsp://user001:{{FRIGATE_RTSP_PASSWORD}}@192.168.1.100:554/stream2?timeout=92&rtsp_transport=tcp#video=copy
    #   - ffmpeg:son_user001#audio=opus
    son_user002:
      - rtsp://user002:{FRIGATE_RTSP_PASSWORD}@192.168.1.101:554/stream2
      - tapo://{FRIGATE_TAPO_PASSWORD}@192.168.1.101
      - ffmpeg:son_user002#audio=opus
    son_user002_record:
      - ffmpeg:rtsp://user002:{FRIGATE_RTSP_PASSWORD}@192.168.1.101:554/stream2#video=copy
      - tapo://{FRIGATE_TAPO_PASSWORD}@192.168.1.101
    # son_user002_sub:
    #   - rtsp://user002:{{FRIGATE_RTSP_PASSWORD}}@192.168.1.101:554/stream2?timeout=92&rtsp_transport=tcp#video=copy
    #   - ffmpeg:son_user002_sub#audio=opus
    son_user003:
      - rtsp://user003:{FRIGATE_RTSP_PASSWORD}@192.168.1.102:554/stream2
      - tapo://{FRIGATE_TAPO_PASSWORD}@192.168.1.102
      - ffmpeg:son_user003#audio=opus
    son_user003_record:
      - ffmpeg:rtsp://user003:{FRIGATE_RTSP_PASSWORD}@192.168.1.102:554/stream2#video=copy
      - tapo://{FRIGATE_TAPO_PASSWORD}@192.168.1.102
      
    # son_user003_sub:
    #   - rtsp://user003:{{FRIGATE_RTSP_PASSWORD}}@192.168.1.102:554/stream2?timeout=92&rtsp_transport=tcp#video=copy
    #   - ffmpeg:son_user003_sub#audio=opus
    # son_user004:
    #   - rtsp://admin:{FRIGATE_TAPO_PASSWORD}@192.168.1.190:554/cam/realmonitor?channel=1&subtype=0#video=copy
    son_user004:
      - rtsp://admin:{FRIGATE_TAPO_PASSWORD}@192.168.1.190:554/cam/realmonitor?channel=1&subtype=1#video=copy
      - ffmpeg:son_user004_sub#audio=opus
    # son_user005:
    #   - rtsp://admin:{FRIGATE_TAPO_PASSWORD}@192.168.1.181:554/cam/realmonitor?channel=1&subtype=0#video=copy
    son_user005:
      - rtsp://admin:{FRIGATE_TAPO_PASSWORD}@192.168.1.181:554/cam/realmonitor?channel=1&subtype=1#video=copy
      - ffmpeg:son_user005_sub#audio=opus
    # son_user006:
    #   - rtsp://admin:{FRIGATE_TAPO_PASSWORD}@192.168.1.182:554/cam/realmonitor?channel=1&subtype=0#video=copy # L2C67C0F
    son_user006:
      - rtsp://admin:{FRIGATE_TAPO_PASSWORD}@192.168.1.182:554/cam/realmonitor?channel=1&subtype=1#video=copy # L2C67C0F
      - ffmpeg:son_user006_sub#audio=opus

cameras:
  son_user004: # <------ Name the camera
    enabled: true
    ffmpeg:
      output_args:
        record: preset-record-generic-audio-aac
      inputs:
        - path: rtsp://127.0.0.1:8554/son_user004 # <----- The stream you want to use for detection
          input_args: preset-rtsp-restream
          roles:
            - record
        # - path: rtsp://127.0.0.1:8554/son_user004_sub # <----- The stream you want to use for detection
        #   input_args: preset-rtsp-restream
        #   roles:
            - detect
            - audio

    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      fps: 5
    motion:
      threshold: 80
      contour_area: 100
      improve_contrast: false
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 90
    zones:
      person_zone:
        coordinates: 0.997,0.902,0.255,0.746,0.322,0.009,0.77,0.004,0.68,0.191,0.996,0.071
        loitering_time: 0
    birdseye:
      order: 1
    review:
      detections:
        required_zones: person_zone
      alerts:
        required_zones: person_zone
    objects: {}
  son_user005: # <------ Name the camera
    enabled: true
    ffmpeg:
      output_args:
        record: preset-record-generic-audio-aac
      inputs:
        - path: rtsp://127.0.0.1:8554/son_user005 # <----- The stream you want to use for detection
          input_args: preset-rtsp-restream
          roles:
            - record
        # - path: rtsp://127.0.0.1:8554/son_user005_sub # <----- The stream you want to use for detection
        #   input_args: preset-rtsp-restream
        #   roles:
            - detect
            - audio
    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      fps: 5
    motion:
      threshold: 34
      contour_area: 43
      improve_contrast: false
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 90
    zones:
      person_zone:
        coordinates: 0.229,0.03,0.217,1,0.415,0.991,0.96,0.957,0.982,0.004
        loitering_time: 0
        inertia: 3
    birdseye:
      order: 1
    review:
      alerts:
        required_zones: person_zone
      detections:
        required_zones: person_zone
    objects: {}
  son_user006: # <------ Name the camera
    enabled: true
    ffmpeg:
      output_args:
        record: preset-record-generic-audio-aac
      inputs:
        - path: rtsp://127.0.0.1:8554/son_user006 # <----- The stream you want to use for detection
          input_args: preset-rtsp-restream
          roles:
            - record
        # - path: rtsp://127.0.0.1:8554/son_user006_sub # <----- The stream you want to use for detection
        #   input_args: preset-rtsp-restream
        #   roles:
            - detect
            - audio

    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      fps: 5
    motion:
      threshold: 80
      contour_area: 100
      improve_contrast: true
      mask: 0.614,0.276,0.605,0.598,0.726,0.617,0.724,0.28
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 90
    zones:
      person_zone:
        coordinates: 0.099,0.257,0.1,0.997,1,1,1,0.29
        loitering_time: 0
    birdseye:
      order: 1
    review:
      alerts:
        required_zones: person_zone
      detections:
        required_zones: person_zone
    objects:
      mask: 0.727,0.219,0.725,0.392,0.914,0.41,0.896,0.207
  son_user001: # <------ Name the camera
    enabled: true
    ffmpeg:
      output_args:
        record: preset-record-generic-audio-aac
      inputs:
        - path: rtsp://127.0.0.1:8554/son_user001_record # <----- The stream you want to use for record
          input_args: preset-rtsp-restream
          roles:
            - record
        - path: rtsp://127.0.0.1:8554/son_user001 # <----- The stream you want to use for detect
          input_args: preset-rtsp-restream
          roles:
            - detect
            - audio
    record:
      enabled: true
      retain:
        days: 90       # Keep recordings for 7 days (adjust as needed)
        mode: all     # Options: motion | active_objects | all
    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      fps: 5
    motion:
      threshold: 80
      contour_area: 100
      improve_contrast: true
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 90
    zones:
      plate:
        coordinates: 
          0.269,0,0.276,0.29,0,0.568,0.145,1,0.404,1,0.896,1,1,0.583,0.943,0.413,0.803,0.297,0.795,0
        loitering_time: 0
        inertia: 3
    birdseye:
      order: 1
    review:
      detections:
        required_zones: plate
      alerts:
        required_zones: plate
    objects: {}
  son_user002: # <------ Name the camera
    enabled: true
    ffmpeg:
      output_args:
        record: preset-record-generic-audio-aac
      inputs:
        - path: rtsp://127.0.0.1:8554/son_user002_record # <----- The stream you want to use for detection
          input_args: preset-rtsp-restream
          roles:
            - record
        - path: rtsp://127.0.0.1:8554/son_user002 # <----- The stream you want to use for detection
          input_args: preset-rtsp-restream
          roles:
            - detect
            - audio
    record:
      enabled: true
      retain:
        days: 90       # Keep recordings for 7 days (adjust as needed)
        mode: all     # Options: motion | active_objects | all
    detect:
      enabled: true # <---- disable detection until you have a working camera feed
      fps: 5
    motion:
      threshold: 80
      contour_area: 100
      improve_contrast: false
      mask:
        - 0,0,0.442,0,0.463,0.456,0.165,0.544,0,0.84
        - 0.667,0,0.675,0.274,0.999,0.399,0.998,0
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 90
    zones:
      plate:
        coordinates: 
          0.163,0.551,0.462,0.458,0.444,0.003,0.664,0,0.674,0.276,0.998,0.399,1,0.996,0,0.996,0.001,0.851
        loitering_time: 0
    birdseye:
      order: 2
    review:
      detections:
        required_zones: plate
      alerts:
        required_zones: plate
    objects: {}
  son_user003: # <------ Name the camera
    enabled: true
    ffmpeg:
      output_args:
        record: preset-record-generic-audio-aac
      inputs:
        - path: rtsp://127.0.0.1:8554/son_user003_record # <----- The stream you want to use for detection
          input_args: preset-rtsp-restream
          roles:
            - record
        - path: rtsp://127.0.0.1:8554/son_user003 # <----- The stream you want to use for detection
          input_args: preset-rtsp-restream
          roles:
            - detect
            - audio
    record:
      enabled: true
      retain:
        days: 90       # Keep recordings for 7 days (adjust as needed)
        mode: all     # Options: motion | active_objects | all
    detect:
      #enabled: false # <---- disable detection until you have a working camera feed
      fps: 5
    motion:
      threshold: 30
      contour_area: 10
      improve_contrast: true
      mask: 0.362,0.172,0.359,0.421,0.457,0.421,0.459,0.222
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 30
    zones:
      person_zone:
        coordinates: 
          0.467,0.087,0.606,0.078,0.613,0.332,0.89,0.109,1,0.106,0.999,0.997,0.001,0.999,0.005,0.047,0.23,0.117,0.337,0.599,0.457,0.421
        loitering_time: 0
        objects: person
        inertia: 3
    birdseye:
      order: 3
    review:
      alerts:
        required_zones: person_zone
      detections:
        required_zones: person_zone
    objects:
      mask: 0.472,0.542,0.48,0.013,0.541,0.013,0.524,0.52
record:
  enabled: true
  export:
    timelapse_args: -vf setpts=PTS/60 -r 25
  sync_recordings: true
  retain:
    days: 90
    mode: all
  alerts:
    retain:
      days: 90
      mode: motion
  detections:
    retain:
      days: 90
      mode: motion

detectors:
  coral:
    type: edgetpu
    device: usb

objects:
  track:
    - person
    - cat
    - dog

audio:
  enabled: false
  listen:
    - bark
    - fire_alarm
    - scream
    - speech
    - yell
    - dog
    - footsteps
    - laughter
    - pets
    - cat
    - meow
    - electric_piano
    - piano
    - telephone
    - television




birdseye:
  enabled: true
  width: 1280
  height: 720
  mode: continuous
  inactivity_threshold: 15
  layout:
    max_cameras: 6
    scaling_factor: 1.0




ffmpeg:
  hwaccel_args: preset-vaapi
  output_args:
    record: preset-record-generic-audio-aac



version: 0.16-0
camera_groups:
  SonA1:
    order: 1
    icon: LuFingerprint
    cameras:
      - son_user001
      - son_user002
      - son_user003
      - son_user004
      - son_user005
      - son_user006
  Bird:
    order: 2
    icon: LuBird
    cameras: birdseye
semantic_search:
  enabled: true
  reindex: false
  model_size: large
detect:
  enabled: true
face_recognition:
  enabled: true
  model_size: large
lpr:
  enabled: true
classification:
  bird:
    enabled: true
Firewall and Allow Ports for Dahua Cam:

When you first init setup your dahua cam, don't use pi hole dns, use 1.1.1.1 dns instead.

1.device that integrates only the P2P function.

To use UDP hole punch technology for remote access, the firewall output of the device must allow the following ports:


● UDP ports: 0-65535

● TCP ports: 9116, 9118, 12366, 12367

● Dahua servers use dynamic IP addresses, their domain names and functions are:

Domain Name Function
easy4ipcloud.com Device login and registration
easy4ip.com Device login and registration



2.Device supporting P2P and Cloud Business

To use UDP hole punch technology for remote access and normal operation of video surveillance services, the firewall output of the device must allow the following ports:


● UDP ports: 0-65535

● TCP ports: 443, 9112, 9113, 9116, 9118, 10000, 12367, 15100, 15101, 15301, 15600, 15900, 16759

● Dahua servers use dynamic IP addresses, their domain names and functions are:


Domain Name Function
easy4ipcloud.com Device login and registration
easy4ip.com Device login and registration
dms.easy4ipcloud.com Device login and registration
paas-dms-edge-fk.easy4ipcloud.com Device login and registration
smartdeviceproxy-edge-fk.easy4ipcloud.com Device login and registration
devaccess.easyipcloud.com Device login and registration
dus.easy4ipcloud.com Cloud upgrade of device firmware
aktualisieren.easy4ip.com Cloud upgrade of device firmware
update.easyviewercloud.com Cloud upgrade of device firmware
vrs.easy4ipcloud.com Upload device images and videos
pps.easy4ipcloud.com Upload device messages
das.easy4ipcloud.com Upload device messages
das-fk.easy4ipcloud.com Upload device messages
devicelogserver-fk.easy4ipcloud.com Uploading device log