One Tapo C310, an original Raspberry Pi, and a few lightweight scripts: this is how I built a headless timelapse system for our house-building project in Portugal, with automatic OneDrive uploads, email alerts, and publicly available source code.
I wanted to document the construction of our house from the beginning. A continuous video recording would have been excessive, and regularly collecting footage from a camera or swapping SD cards was not something I wanted to add to my to-do list.
I already had a TP-Link Tapo C310 overlooking the plot, along with several old Raspberry Pis gathering dust. Rather than buying new hardware, I decided to put one of them — an original Raspberry Pi 1 — back to work.
Its job would be simple: take a high-resolution photo every 20 minutes, upload it to Microsoft OneDrive, and alert me if something went wrong.
What started as a small weekend idea gradually became a more complete, self-monitoring system. I have now published the code so others can inspect the solution, learn from it, and adapt it to their own projects.
Source code and installation guide: github.com/mauro-gentz/tapo-timelapse
The setup at a glance
| Component | My setup |
|---|---|
| Camera | TP-Link Tapo C310, RTSP main stream (/stream1) |
| Image resolution | Up to 2304 × 1296 pixels (3 MP) |
| Computer | Raspberry Pi 1, running Raspberry Pi OS Lite (32-bit) |
| Capture schedule | Every 20 minutes, aligned to UTC |
| Images | 72 per complete UTC day, stored as PNG |
| Cloud backup | Microsoft OneDrive via rclone |
| Notifications | Authenticated SMTP email alerts |
| Maintenance | Automatic supported OS package updates and scheduled clean weekly reboot |
There is no desktop environment, no display, no keyboard, and no need for a Raspberry Pi camera module. The Tapo C310 is an existing network camera; the Pi simply retrieves a frame from its RTSP stream.
How it works
Tapo C310 — RTSP /stream1
|
v
Raspberry Pi 1 / FFmpeg
|
Save PNG locally
|
v
rclone -> OneDrive
(one image at a time)
Parallel checks:
* Retry outstanding uploads
* Audit expected images each day
* Send SMTP warnings and recovery notices
* Check SD-card space and service health
* Apply supported OS package updates
* Reboot cleanly once a week
The key design decision is sequential processing. On a Raspberry Pi 1, memory and CPU time are limited. Capturing a 3 MP frame and transferring another file at exactly the same time adds unnecessary load. The scripts coordinate access with a shared lock and perform cloud transfers one file at a time. A very slow transfer can still delay a scheduled capture, so this is a practical lightweight solution rather than a real-time system.
Why PNG — and what “best quality” really means
I configured the Tapo C310 to provide its highest-quality video stream, 2304 × 1296 pixels, and use FFmpeg to save a frame as a PNG image.
One important distinction: PNG is lossless, but the RTSP stream is already compressed video. Saving a decoded video frame as PNG avoids additional lossy JPEG compression; it does not recover details discarded by the camera’s H.264 encoder.
This is sufficient for documenting construction progress. If your camera reports a lower resolution, check its video-quality setting in the Tapo app before changing the scripts.
Installation: the code is on GitHub
The project is now maintained in one place rather than distributed as a collection of manually exchanged ZIP files:
Tapo Timelapse — GitHub repository
You will need Raspberry Pi OS Lite (32-bit), a working network connection to the camera, a Tapo camera account for RTSP access, a OneDrive account, and an authenticated SMTP service. Use a good power supply and preferably an endurance-rated SD card.
On the Raspberry Pi, log in as your normal user (not directly as root) and run:
git clone https://github.com/mauro-gentz/tapo-timelapse.git
cd tapo-timelapse
sudo bash install.sh
The installer sets up the scripts, dependencies, systemd services, timers, and monitoring. It is designed to preserve existing settings and photos when upgrading the same installation, but I recommend backing up an existing Pi before running any installer.
Configure the camera and capture interval in:
sudo nano /etc/tapo-timelapse.conf
For example, with placeholder credentials:
CAMERA_HOST='192.168.1.100'
CAMERA_USER='camera_account'
CAMERA_PASSWORD='REPLACE_ME'
CAMERA_STREAM='stream1'
IMAGE_FORMAT='png'
CAPTURE_INTERVAL_MINUTES='20'
RCLONE_REMOTE='onedrive'
RCLONE_ROOT='Timelapse/Grundstueck'
UPLOAD_AFTER_CAPTURE='yes'
LOCAL_RETENTION_DAYS='14'
The sample configuration in the repository uses 30-minute captures by default, while my deployment uses 20 minutes. Supported intervals include 5, 10, 15, 20, 30 and 60 minutes. The script derives the expected daily count automatically, and keeps track of interval changes so older days are checked against their original schedule.
For the full setup — including configuration, upgrades, and troubleshooting — see the installation guide on GitHub.
OneDrive without a desktop or manually copying tokens
I use rclone for cloud storage because it is lightweight and I already had good experiences with it.
Configure a remote named onedrive using rclone config, as the same Linux user that runs the timelapse services. Since the Raspberry Pi has no desktop browser, I authenticated using a local SSH port-forward from a Windows PC:
ssh -L 53682:127.0.0.1:53682 YOUR_PI_USER@YOUR_PI_ADDRESS
Run rclone config in that session, select browser-based authentication, and open the exact 127.0.0.1:53682 URL printed by rclone in your Windows browser. The SSH tunnel forwards the login callback to the Pi. This avoids pasting long OAuth tokens into an SSH terminal.
Once authenticated, test the connection:
rclone lsd onedrive:
Each image is uploaded shortly after it has been captured. If the connection fails, it stays on the SD card and the catch-up job retries it later. Successful transfers receive a small local .ok receipt, while the independent daily audit checks what is actually present in OneDrive. Local photos are retained for 14 days by default and are cleaned up only after cloud verification.
Email alerts: knowing when the system fails
A timelapse is only useful if I can trust the collection process. I therefore wanted problem notifications, not an email for every successful photo.
The project can report missing photographs, incomplete OneDrive days, camera and upload failures, low SD-card space, technical monitoring failures, and a reboot required by OS updates. Queued emails are retried when SMTP becomes available again. A boot notification helps confirm that the Pi has returned after a restart.
Configure your own SMTP server in the same private configuration file:
MONITOR_EMAIL_ENABLED='yes'
SMTP_HOST='smtp.example.com'
SMTP_PORT='587'
SMTP_SECURITY='starttls'
SMTP_USER=''
SMTP_PASSWORD='YOUR_APP_PASSWORD'
SMTP_FROM=''
SMTP_TO=''
EMAIL_ON_BOOT='yes'
HEALTH_FREE_SPACE_PERCENT='20'
Then verify the mail connection and check the scheduled jobs:
tapo-timelapse mail-test
tapo-timelapse status
systemctl list-timers --all 'tapo-*.timer'
The daily audit compares individual UTC capture slots, not merely the number of files. If the 14:20 frame is missing but all the other images exist, it can identify that specific gap.
There is one unavoidable limitation: a Pi without power, network connectivity, or a functioning operating system cannot send its own alert. To be notified while the Pi itself is completely offline, an external heartbeat service would be necessary.
Lessons learned from the first days
This project has already reminded me of a few old-fashioned infrastructure lessons:
- Old hardware rewards simplicity. A Raspberry Pi 1 can do this job, but sequential transfers and sensible timeouts matter.
- A running timer is not the same as a working process. During testing, a file-permissions issue caused the daily audit to fail even though the SMTP service was running. The issue was fixed, and the health monitoring was expanded.
- Logs matter. After one system hang, I discovered that the previous boot’s journal was not retained. Persistent, size-limited systemd logs now make future investigation possible.
- Never rely on hard power cycling as routine maintenance. The Pi is configured for supported unattended OS package updates and an orderly weekly reboot on Sunday at 04:10 UTC. Neither automatic OS major-version upgrades nor unattended updates of this GitHub project are enabled.
The scheduled weekly reboot and unattended updates were configured and tested, but long-term reliability still needs to be demonstrated over time. This is a hobby project running on one real installation, not a commercial monitoring appliance.
How much storage does it use?
At one image every 20 minutes, there are 72 images per day or 26,280 per 365-day year. If every image were 10 MB, that would be about 720 MB per day and 262.8 GB per year in OneDrive. Actual size depends on the scene, weather, and lighting.
With 14 days of local retention, the same worst-case estimate is approximately 10.1 GB of images on the Pi, plus the operating system and some headroom for failed uploads. A 32 GB SD card is workable for this configuration, but it is not an excuse to ignore free-space monitoring.
A transparent note about AI-generated code
I also want to be open about how this project was built. Most of the scripts, installer, documentation, and tests were generated with the assistance of OpenAI ChatGPT. I supplied the requirements, made the decisions about how the system should behave, deployed it on the Raspberry Pi, and tested and debugged it in the real environment. This is an example of what people sometimes call vibe coding.
That is not a guarantee of software quality. AI-generated code may contain bugs, insecure assumptions, or mistakes that tests fail to catch. The repository is public so the implementation can be inspected, but anyone considering using it should review the code, keep credentials out of Git, and test it on their own hardware.
The project on GitHub
If you are building a house, monitoring a garden, documenting a renovation, or simply looking for a useful second life for an old Raspberry Pi, perhaps this setup will give you a starting point.
Explore the source code, installation instructions, and development history:
github.com/mauro-gentz/tapo-timelapse
I plan to keep the technical documentation in the repository so that the blog tells the story, while GitHub holds the implementation and future changes.

Leave a Reply