+++ categories = ["software"] tags = ["docker"] date = 2024-04-18T17:00:33Z description = "" draft = false slug = "ipcam-timelapse" title = "📹 IP Camera Time-lapse in Frigate" author = "nicholas" +++ I have a container running `Frigate`, which captures and republishes a feed from my security camera overlooking the area beyond my deck. I will periodically capture a frame from this stream for some time, and compile the frames into time-lapses using `ffmpeg` {{< image src="images/ip-cam-mounted.JPG" caption="IP camera mounted" >}} {{< image src="images/ip-cam-view.JPG" caption="IP camera view of deck overlooking the neighborhood" >}} ## Docker Container - Frigate As I mention above, I am already using `Frigate` to manage my IP camera stream for things like object detection, recording, and other such functions that are common in video management systems. The software lacks built-in features relating to time-lapses, but this is easily implemented through other means. ## Docker Compose First, I include here the basic `docker-compose.yml` file that I use to get a `Frigate` container up and running. Not a lot of software configuration is defined here, this will mostly be done later in the frigate configuration file. ```yaml services: frigate: container_name: frigate privileged: true restart: unless-stopped image: ghcr.io/blakeblackshear/frigate:stable shm_size: "512mb" devices: - /dev/dri/renderD128 # for intel hwaccel volumes: - /etc/localtime:/etc/localtime:ro - ${HOST_PATH_CONFIG}:/config - ${HOST_PATH_MEDIA}:/media/frigate - type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear target: /tmp/cache tmpfs: size: 1000000000 ports: - "${PORT}:5000" - "8554:8554" # RTSP feeds - "8555:8555/tcp" # WebRTC over tcp - "8555:8555/udp" # WebRTC over udp environment: - FRIGATE_CAMERA_USER=${FRIGATE_CAMERA_USER} - FRIGATE_CAMERA_PASSWORD=${FRIGATE_CAMERA_PASSWORD} ``` ``` PORT= HOST_PATH_CONFIG= HOST_PATH_MEDIA= ``` This is my frigate configuration file config.yml. In this configuration, I am not recording or capturing snapshots of anything, which are major features of frigate. Instead I am using frigate to monitor the feed in real time and to periodically grab frames from the stream it publishes. In other words, it is superfluous to use frigate for the purpose of capturing frames. One could go straight to the source RTSP stream and circumvent the re-stream. But I do this anyway because sometimes I like to capture videos of squirrels and birds using frigate's object detection. ```yaml ui: live_mode: mse mqtt: enabled: false go2rtc: streams: deck: - rtsp://{FRIGATE_CAMERA_USER}:{FRIGATE_CAMERA_PASSWORD}@192.168.1.200:554//h265Preview_01_main birdseye: enabled: false mode: continuous cameras: deck: # <------ Name the camera objects: track: - person - animal ffmpeg: inputs: - path: rtsp://127.0.0.1:8554/deck roles: - record - detect hwaccel_args: preset-vaapi input_args: -tag:v hvc1 output_args: record: preset-record-generic-audio-copy record: enabled: false events: pre_capture: 2 post_capture: 2 objects: - animal snapshots: # <----- Enable snapshots enabled: false detect: enabled: false width: 3840 height: 2160 detectors: ov: type: openvino device: AUTO model: path: /openvino-model/ssdlite_mobilenet_v2.xml model: width: 300 height: 300 input_tensor: nhwc input_pixel_format: bgr labelmap_path: /openvino-model/coco_91cl_bkgr.txt labelmap: 15: animal 16: animal 17: animal ``` ```shell sudo docker compose up -d ``` # Time-lapse Parameters The goal is to compress a month (30 days) of time into a minute. ## Clip Duration The view from my deck is not so exciting, so I do not want time-lapse clip to last too long. I settled on 1 minute. ## Frame rate I want the video to be very smooth, so I chose 60 frames per second. This should be plenty. I can change my mind when I generate a video using ffmpeg's -framerate {framerate} option because I am storing each individual frame as a .png file. ## Interval The interval follows from the frame rate and clip duration. The interval is a function of clip duration and frame rate. The relationship between these variables can be expressed: duration = frames * framerate interval = duration / framerate # Capturing Frames from Frigate ```sh #!/bin/sh time=`date '+%Y_%m_%d__%H_%M_%S'`; StorageFileName=$time.png /usr/bin/ffmpeg -rtsp_transport tcp -i rtsp://:@/Preview__ -ss 1 -frames:v 1 -update 1 /$StorageFileName ``` Here we use ffmpeg to capture the frames and store them as png files according to the time it was captured. This script runs every 12 minutes via cron: ```sh crontab -e */12 * * * * ``` This is the command I use to generate a video. ```shell ffmpeg -framerate 60 -pattern_type glob -i '*.png' -c:v libx265 -crf 28 -preset ultrafast -s 2k 28_ultrafast.mp4 ``` {{< image src="images/timelapse.gif" caption="Timelapse" >}} {{< video src="videos/timelapse-multiday.mp4" width="100%" >}} {{< video src="videos/timelapse-deck-planter.mp4" width="100%" >}} ReoLink RLC-810WA