Record time-lapse video with Picamera2

Ats
4 min readMar 17, 2024

When I implemented the codes for recording time-lapse video on Raspberry Pi, It took a few hours from me to understand. This is the learnings from it.

Photo by David Becker on Unsplash

First of all

These are my development environments

Hardware

Software

Background

I develop a camera to record time-lapse video with Raspberry Pi for my job. However, It was implemented before I joined the team and I hadn’t touched the codes related to the recording. Then I came to want to know how it works suddenly. So I opened the code lines and Picamera2 documents but it was not as easy as I thought.

What I did

Firstly, I went to the Picamera2 GitHub repository and checked the document. Then I found the example codes for the time-lapse video.

I start from the bottom line. This part is very important for Picamera2.

# Create the output mp4 video
merge = subprocess.Popen([
"mkvmerge", "-o", "timelapse.mkv",
"--timestamps", "0:timestamps.txt",
"test.h264"
])
merge.wait()

I thought it was just converting from h264 file to mp4 file as the comment says. So I removed this part after testing the example because I usually use ffmpeg tool to manipulate videos. Then I was getting more and more confused about how it makes the video time-lapse.

I removed the part, ran it, and converted the test.h264 to mp4 with the following command.

ffmpeg -i test.h264 -c copy video.mp4

It was also a time-lapse video. Then I changed the speed argument for TimelapseOutput because it looked related to the time-lapse speed. However, the time-lapse speed didn’t change even though I extremely changed the value, and it was the same as the video which I took right after I removed the part. As I was feeling weird, I changed the framerate argument and then the time-lapse speed was changed. It was weird to me because the frame rate is a different concept from the time-lapse speed.

Then I thought I had done something wrong with framerate or ffmpeg and googled ffmpeg document for framerate . I found -r option for ffmpeg which I hadn’t known before and found the following sentence in the description.

As an input option, ignore any timestamps stored in the file and instead generate timestamps assuming constant frame rate fps.

So I assumed Picamera didn’t update the timestamps even if the framerate was changed. Then I checked the log from ffmpeg when I converted a video which I recorded with framterate 1 from h264 to mp4 and got the following logs.

Input #0, h264, from 'test.h264':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p(progressive), 1920x1080, 30 fps, 30 tbr, 1200k tbn, 60 tbc
Output #0, mp4, to 'video.mp4':
Metadata:
encoder : Lavf58.45.100
Stream #0:0: Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080, q=2-31, 30 fps, 30 tbr, 1200k tbn, 1200k tbc

As I assumed, ffmpeg recognized the frame rate was still 30. Also, I converted the video with the-r option of ffmpeg . It finally became a non-time lapse video with a low frame rate.

So I checked the File class of Picamera2 and also found there weren’t any code lines to update timestamps according to the frame rate.

Picamera2 seems to take video with 30 fps by default and doesn’t do anything to the timestamps even though the frame rate is changed. As a result, the video becomes a timelapse video when it is converted without any options. Then as I already wrote at the beginning, the first video which I recorded with the example codes was converted with the custom timestamps in the following part.

# Create the output mp4 video
merge = subprocess.Popen([
"mkvmerge", "-o", "timelapse.mkv",
"--timestamps", "0:timestamps.txt",
"test.h264"
])
merge.wait()

It looked pretty straightforward at a glance but it took a few hours to understand how it works properly.

That’s it!

--

--

Ats

I like building something tangible like touch, gesture, and voice. Ruby on Rails / React Native / Yocto / Raspberry Pi / Interaction Design / CIID IDP alumni