5.4 KiB
+++ 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.
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=<port number>
HOST_PATH_CONFIG=<host path for config>
HOST_PATH_MEDIA=<host path for 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.
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
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
#!/bin/sh
time=`date '+%Y_%m_%d__%H_%M_%S'`;
StorageFileName=$time.png
/usr/bin/ffmpeg -rtsp_transport tcp -i rtsp://<username>:<password>@<IP address>/Preview_<channel number>_<stream type> -ss 1 -frames:v 1 -update 1 <path>/$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:
crontab -e
*/12 * * * * <path_to_timelapse.sh>
This is the command I use to generate a video.
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