A Docker-based service that records time-lapse videos directly from RTSP streams using ffmpeg. Records continuously and compiles frames into daily video files automatically. Optimized for minimal storage space - records 24 hours into ~50-100 MB video files.
- 🎥 Direct video recording - No frame storage overhead
- � Automatic daily videos - Creates video files for each time period
- 💾 98% space savings - 5 GB/day → 50-100 MB/day
- 🔄 Continuous operation - Records 24/7 without manual intervention
- 🐳 Fully containerized with Docker
- 📺 Uses ffmpeg for excellent UDP/RTSP stream handling
- 🔧 Configurable FPS, quality, and video duration
- ☁️ TrueNAS Scale compatible
- 🔄 Migration tool included for existing frames
Edit docker-compose.yml and set your RTSP stream URL:
- RTSP_URL=rtsp://your-camera-ip:554/streamdocker-compose up -ddocker-compose logs -f timelapse-captureVideos will be saved in the ./videos directory with timestamps:
- Format:
timelapse_YYYYMMDD_HHMMSS.mp4 - Example:
timelapse_20251104_000000.mp4 - Each file represents the configured duration (default: 24 hours)
First Run: If you have old PNG/JPG frames in the directory, they will be automatically migrated to video format and then deleted.
All settings can be configured via environment variables in docker-compose.yml:
| Variable | Default | Description |
|---|---|---|
RTSP_URL |
rtsp://example.com/stream |
Your RTSP stream URL |
CYCLE_TIME |
60 |
Seconds between each frame capture |
VIDEO_FPS |
24 |
Frames per second in output video |
VIDEO_QUALITY |
23 |
CRF quality (18-28, lower=better, 23=default) |
VIDEO_DURATION_HOURS |
24 |
Real-time hours per video file |
KEEP_TEMP_FRAMES |
false |
Keep temporary frames after video creation |
OUTPUT_DIR |
/videos |
Output directory (inside container) |
Note: Actual sleep time = CYCLE_TIME - PRELOAD_TIME (automatically calculated)
With default settings (60-second cycle, 24 fps output):
- 24 hours real-time = 1,440 frames captured
- Output video = 60 seconds (1,440 frames ÷ 24 fps)
- File size = ~50-100 MB (compressed H.264)
To adjust the time compression, modify CYCLE_TIME:
- 30 seconds → 2,880 frames/day → 2 minutes of video
- 120 seconds → 720 frames/day → 30 seconds of video
Example: For 1 day = 2 minutes of video at 24fps:
- Set
CYCLE_TIME=30(captures 2,880 frames per day) - Output: 2,880 frames ÷ 24 fps = 120 seconds (2 minutes)
- Create a custom app in TrueNAS Scale
- Clone this repository to a dataset
- Navigate to the directory in the TrueNAS shell
- Run:
docker-compose up -d
-
Build the image:
docker build -t your-registry/timelapse-capture:latest . -
Push to your registry:
docker push your-registry/timelapse-capture:latest
-
Deploy in TrueNAS Scale:
- Use the "Launch Docker Image" option
- Set image:
your-registry/timelapse-capture:latest - Configure environment variables
- Mount host path for videos:
/mnt/your-pool/videos→/videos
Good news! Migration is now automatic!
When you deploy the new version:
- Service detects existing PNG/JPG frames
- Automatically converts them to videos
- Deletes old frames after successful conversion
- Starts normal video recording
Control migration behavior with environment variables:
environment:
- AUTO_MIGRATE=true # Auto-detect and migrate old frames
- DELETE_OLD_FRAMES=true # Delete PNGs after migrationIf you prefer manual control, disable auto-migration:
- AUTO_MIGRATE=falseThen run migration separately:
docker-compose -f docker-compose.migrate.yml upSee MIGRATION.md for detailed manual migration instructions.
Old System (PNG frames):
- 1,440 frames/day × 3-5 MB = ~5-7 GB per day
- 30 days = 150-210 GB 😱
New System (MP4 videos):
- 1 video/day × 50-100 MB = ~50-100 MB per day
- 30 days = 1.5-3 GB ✨
- 98% space savings!
- Go to Apps → Available Applications
- Click Launch Docker Image
- Configure:
- Image Repository: Build and push your image first
- Environment Variables: Set RTSP_URL, etc.
- Storage: Add host path volume (
/mnt/your-pool/screenshots→/screenshots) - Restart Policy: Unless Stopped
Edit app.py line 47 and change:
'-rtsp_transport', 'tcp', # Use TCP for RTSPto:
'-rtsp_transport', 'udp', # Use UDP for RTSPIf your camera is on the same network as the Docker host, uncomment in docker-compose.yml:
network_mode: hostFor unstable connections, increase the frame capture interval:
- CYCLE_TIME=120 # 2 minutes between frames (slower, more stable)For better quality videos:
- VIDEO_QUALITY=20 # Lower = better (18-28 range)
- VIDEO_FPS=30 # Smoother playbackCreate shorter video files:
- VIDEO_DURATION_HOURS=12 # 12-hour videos instead of 24-hourVideos are automatically created! The system continuously records and compiles frames into video files.
To combine multiple daily videos into one:
# Navigate to videos directory
cd videos
# Create a file list
ls timelapse_*.mp4 | sed 's/^/file /' > filelist.txt
# Combine videos
ffmpeg -f concat -safe 0 -i filelist.txt -c copy combined_timelapse.mp4
# Or re-encode with custom settings
ffmpeg -f concat -safe 0 -i filelist.txt \
-c:v libx264 -crf 23 -preset medium combined_timelapse.mp4To adjust playback speed:
# Speed up 2x
ffmpeg -i timelapse_20251104_000000.mp4 -filter:v "setpts=0.5*PTS" output_2x.mp4
# Slow down 0.5x
ffmpeg -i timelapse_20251104_000000.mp4 -filter:v "setpts=2*PTS" output_half.mp4- Check logs:
docker-compose logs -f - Verify RTSP URL is correct
- Test stream with ffmpeg:
ffmpeg -i rtsp://your-url -frames:v 1 test.jpg - Ensure sufficient disk space
- Check temp_frames directory for accumulated frames
- Increase
VIDEO_QUALITYto 20 or lower (better quality, larger files) - Reduce
CYCLE_TIMEfor more frames (smoother video) - Increase
VIDEO_FPSto 30 for smoother playback
- Increase
CYCLE_TIMEfor fewer frames - Decrease
VIDEO_QUALITYto 25-28 (smaller files) - Set up auto-deletion of old videos (use cron or TrueNAS tasks)
- Check available memory
- Reduce
FRAMES_PER_VIDEOif running out of memory during compilation - Check logs for specific errors
# Build the image
docker build -t timelapse-capture .
# Run manually
docker run -d \
-e RTSP_URL=rtsp://your-camera/stream \
-v $(pwd)/screenshots:/screenshots \
timelapse-captureMIT License - Feel free to modify and use as needed.
Pull requests are welcome! For major changes, please open an issue first.