A Docker-based timelapse camera system that automatically captures hourly frames from multiple IP cameras and provides a web interface for viewing the collected images.
- Automated Frame Collection: Captures frames from multiple cameras every hour
- Web Interface: Browse and view collected frames through a user-friendly filebrowser
- Basic Authentication: Secure access to the web interface with password protection
- Multi-Camera Support: Configure up to 20 cameras simultaneously
- Organized Storage: Frames are automatically organized by camera IP and timestamp
- Docker-Based: Easy deployment with Docker Compose
The system consists of three main components:
- Collector: Python service that fetches frames from cameras on an hourly basis
- File Browser: Web interface for browsing and viewing saved frames
- Endpoint: Caddy reverse proxy with basic authentication
- Docker and Docker Compose installed
- Network access to IP cameras
- Cameras must support HTTP snapshot API
-
Clone this repository:
git clone https://github.com/kaunofakultetas/timelapse-collector.git cd timelapse-collector -
Copy the sample configuration:
cp docker-compose.yml.sample docker-compose.yml
-
Edit
docker-compose.ymland configure:- Camera IPs and credentials in the
timelapse-collectorenvironment section - Basic auth username and password hash in the
timelapse-endpointenvironment section
- Camera IPs and credentials in the
-
Generate a password hash for basic authentication:
docker run --rm caddy:2.10.2-alpine caddy hash-password --plaintext 'YourPassword'Important: When adding the hash to
docker-compose.yml, escape all$symbols by doubling them ($$):- BASIC_AUTH_HASH=$$2a$$12$$yourHashHere -
Run the deployment script:
./runUpdateThisStack.sh
-
Access the web interface at port 80.
Configure cameras in the timelapse-collector service environment variables:
environment:
# Camera 1
- CAMERA_TYPE_0=HIKVISION
- CAMERA_IP_0=192.168.1.100
- CAMERA_USERPASS_0=admin:password
# Camera 2
- CAMERA_TYPE_1=HIKVISION
- CAMERA_IP_1=192.168.1.101
- CAMERA_USERPASS_1=admin:password- Use sequential numbering starting from 0 (e.g.,
_0,_1,_2, etc.) - Maximum 20 cameras supported
- Currently only HIKVISION camera type is supported
Configure access credentials in the timelapse-endpoint service:
environment:
# username:password
- BASIC_AUTH_USER=admin
- BASIC_AUTH_HASH=$$2a$$12$$YourBcryptHashHereGenerate new password hashes using:
docker run --rm caddy:2.10.2-alpine caddy hash-password --plaintext 'YourPassword'- Frame Collection: The collector service runs continuously and checks every second if a new hour has begun
- Hourly Capture: At the start of each hour, it attempts to fetch a snapshot from each configured camera
- Storage: Frames are saved in
SAVED_FRAMES/<camera-ip>/YYYY-MM-DD HHMM.jpgformat - Web Access: The file browser serves these frames through a web interface protected by Caddy's basic authentication
.
├── collector/
│ ├── Dockerfile
│ └── main.py # Camera frame collection logic
├── endpoint/
│ └── Caddyfile # Reverse proxy configuration
├── filebrowser/
│ ├── Dockerfile
│ ├── filebrowser.json
│ └── branding/ # Custom branding files
├── SAVED_FRAMES/ # Collected frames (created automatically)
├── docker-compose.yml # Main configuration (not in repo)
├── docker-compose.yml.sample # Sample configuration
└── runUpdateThisStack.sh # Deployment script
# All services
sudo docker-compose logs -f
# Specific service
sudo docker-compose logs -f timelapse-collector
sudo docker-compose logs -f timelapse-filebrowser
sudo docker-compose logs -f timelapse-endpoint./runUpdateThisStack.shsudo docker-compose down- Verify camera IP addresses are correct
- Check network connectivity to cameras
- Verify camera credentials
- Ensure cameras support HTTP snapshot API at
/Streaming/channels/101/picture
- Verify the password hash is correctly escaped with
$$in docker-compose.yml - Regenerate the hash if needed
- Check Caddy logs:
docker-compose logs timelapse-endpoint
- Check collector logs for errors:
docker-compose logs timelapse-collector - Verify cameras are accessible from the collector container
- Ensure sufficient disk space in
SAVED_FRAMESdirectory