Scootercam

Scootercam’s Sunset System

There have been several iterations of this system but the idea hasn’t much changed – a camera swings towards the setting sun and captures images, then produces a timelapse video of the sunset. In this version an image is captures every five seconds from 20 minutes before until 20 minutes after sunset. The issue came when I added a second camera to the mix and expected a tiny Raspberry Pi to handle taking two images from two cameras at the exact same time, and doing that 600 times over. Things needed to stagger.ScooterCam Sunset System – Project Summary

Overview

A complete automated sunset timelapse capture, compilation, and upload system for dual IP cameras (Amcrest and Reolink) on Lake Michigan’s eastern shore. Built for Raspberry Pi 5 with SSD storage.

Workflow Timeline

15:00 - Sunset at 17:30
  |
16:00 - Cron job starts sunset_master.py
  |
17:10 - Capture window begins (sunset - 20 min)
  |     ├─ capture_amcrest.py starts
  |     └─ capture_reolink.py starts 2.5 seconds later
  |
  |     [Both cameras capture 1 image every 5 seconds]
  |     [~480 images per camera over 40 minutes]
  |
17:50 - Capture window ends (sunset + 20 min)
  |     └─ ~80 images per camera captured
  |
17:50 - Amcrest processing begins
  |     ├─ compile_video.py creates MP4
  |     ├─ Identifies poster image (closest to 17:30)
  |     └─ upload_ftp.py sends to server
  |
17:55 - 5-minute delay (stagger compilation)
  |
17:55 - Reolink processing begins
  |     ├─ compile_video.py creates MP4
  |     ├─ Identifies poster image
  |     └─ upload_ftp.py sends to server
  |
18:00 - Process complete

Component Details

1. sunset_calculator.py

Purpose: Calculate daily sunset times and capture windows

Features:

  • Uses Astral library for astronomical calculations
  • America/Detroit timezone aware
  • Configurable location coordinates
  • Provides 40-minute capture window (±20 min from civil sunset)

Key Functions:

  • get_sunset_times() – Returns today’s sunset and capture window
  • should_capture_now() – Checks if current time is in capture window

2. capture_amcrest.py & capture_reolink.py

Purpose: Download images from cameras during sunset window

Features:

  • Waits automatically until capture start time
  • Downloads snapshot every 30 seconds
  • Error handling with retries
  • Creates organized storage structure
  • Validates downloaded files
  • Logs success/failure of each capture

Output:

  • Images: /mnt/ssd/sunset_captures/YYYY-MM-DD/[camera]/camerane_YYYYMMDD_HHMMSS.jpg

3. compile_video.py

Purpose: Convert captured images into MP4 timelapse videos

Features:

  • Uses ffmpeg for video compilation
  • 30 fps output, H.264 codec
  • CRF 23 quality (configurable)
  • Identifies poster image (closest to actual sunset)
  • Creates both video and poster image
  • Error handling and validation

Output:

  • Video: sunset_[camera]_YYYY-MM-DD.mp4
  • Poster: sunset_[camera]_YYYY-MM-DD_poster.jpg

4. upload_ftp.py

Purpose: Upload compiled videos and posters to Glowhost

Features:

  • Secure FTP connection
  • Separate directories for videos (/sw) and images (/sr)
  • Connection testing mode (–test flag)
  • Retry logic for failed uploads
  • Upload progress reporting
  • Validates successful transfer

Configuration:

5. sunset_master.py

Purpose: Orchestrate the complete workflow

Features:

  • Coordinates all components
  • Runs both camera captures simultaneously
  • Staggers video compilation (5-min delay)
  • Comprehensive logging
  • Error tracking and reporting
  • Final summary of all operations

Workflow:

  1. Calculate sunset time
  2. Launch both capture scripts in parallel
  3. Wait for captures to complete
  4. Compile and upload Amcrest
  5. Wait 5 minutes
  6. Compile and upload Reolink
  7. Generate summary report

6. system_check.py

Purpose: Verify system configuration before first run

Checks:

  • System commands (ffmpeg, wget, python3)
  • Python packages (astral, pytz)
  • Required scripts present
  • Storage directories exist and writable
  • Camera connectivity
  • FTP connection
  • Sunset calculator functionality

7. setup.sh

Purpose: Automated installation script

Actions:

  • Installs system dependencies
  • Installs Python packages
  • Creates project directory
  • Sets up storage directories
  • Makes scripts executable
  • Optionally configures cron job
  • Runs system check

File Organization

Local Storage Structure

/mnt/ssd/
├── sunset_captures/
│   └── 2025-11-11/
│       ├── amcrest/
│       │   ├── amcrest_20251111_171000.jpg
│       │   ├── amcrest_20251111_171005.jpg
│       │   ├── amcrest_20251111_171010.jpg
│       │   └── ... (~480 images)
│       └── reolink/
│           ├── reolink_20251111_171002.jpg (staggered 2.5s)
│           ├── reolink_20251111_171007.jpg
│           └── ... (~480 images)
└── sunset_videos/
    └── 2025-11-11/
        ├── sunset_amcrest_2025-11-11.mp4
        ├── sunset_amcrest_2025-11-11_poster.jpg
        ├── sunset_reolink_2025-11-11.mp4
        └── sunset_reolink_2025-11-11_poster.jpg

Remote Storage Structure

scootercam.net/
├── sw/ (videos)
│   ├── sunset_amcrest_2025-11-11.mp4
│   └── sunset_reolink_2025-11-11.mp4
└── sr/ (images)
    ├── sunset_amcrest_2025-11-11_poster.jpg
    └── sunset_reolink_2025-11-11_poster.jpg

Technical Specifications

Video Settings

  • Codec: H.264 (libx264)
  • Frame Rate: 30 fps
  • Quality: CRF 23
  • Preset: medium
  • Pixel Format: yuv420p (universal compatibility)
  • Typical Size: 10-50 MB per video

Image Capture

  • Interval: 5 seconds
  • Duration: 40 minutes
  • Images per camera: ~480 (8 images per minute × 40 minutes)
  • Format: JPEG
  • Source Resolution: Native camera resolution
  • Stagger: Reolink starts 2.5 seconds after Amcrest to avoid simultaneous network load

Network Requirements

  • Local Network: Access to 192.168.1.x cameras
  • Internet: FTP upload to scootercam.net
  • Bandwidth: ~50-100 MB upload per day

Storage Requirements

  • Daily Capture: ~800 MB – 1.2 GB (images + videos)
    • ~480 images per camera at ~500 KB each = ~240 MB per camera
    • Videos after compression: ~50-100 MB per camera
  • Monthly: ~25-35 GB
  • Recommended: 128+ GB SSD
  • Retention: Configure cleanup as needed

Dependencies

System Packages

  • python3 (3.9+)
  • ffmpeg
  • wget
  • ftp (optional, for manual testing)

Python Packages

  • astral==3.2 (astronomical calculations)
  • pytz==2024.1 (timezone support)

Automation

Cron Configuration

cron

# Daily execution at 4:00 PM
0 16 * * * cd /home/pi/scootercam-sunset && /usr/bin/python3 sunset_master.py >> /var/log/scootercam-sunset.log 2>&1

Log Management

  • Location: /var/log/scootercam-sunset.log
  • Rotation: Implement logrotate if desired
  • Monitoring: Use tail -f for real-time viewing

Maintenance

Daily

  • System runs automatically via cron
  • Check logs for errors if needed

Weekly

  • Review log files
  • Verify uploads to server
  • Check storage space

Monthly

  • Clean up old captures
  • Verify camera connectivity
  • Review system performance

Seasonal

  • Update coordinates if needed
  • Adjust for significant camera repositioning
  • Test system before DST changes (auto-adjusts)

Error Handling

Capture Failures

  • Individual image failures logged but don’t stop process
  • Retries on timeout (3 attempts)
  • Continues even if some images fail

Compilation Failures

  • Logged with detailed error messages
  • Doesn’t stop other camera’s processing
  • Can be re-run manually for specific dates

Upload Failures

  • Logged with connection details
  • Can be re-uploaded manually
  • FTP test mode available for diagnostics

Recovery

All components support manual execution:

  • Capture: Can be re-run for current day
  • Compile: Can be run for any past date with images
  • Upload: Can be run for any past date with videos

Performance Considerations

Resource Usage

  • CPU: Moderate during compilation
  • RAM: Low (<500 MB)
  • Disk I/O: Moderate during capture
  • Network: Low (periodic small uploads)

Optimization

  • 5-minute stagger prevents resource contention
  • Parallel captures maximize efficiency
  • H.264 preset ‘medium’ balances speed/quality

Scalability

  • Can add more cameras by duplicating capture scripts
  • Stagger compilation by additional 5-minute intervals
  • Storage scales linearly with retention period

Security Considerations

Credentials

  • Camera passwords in scripts (local system only)
  • FTP credentials in scripts (consider encryption for production)
  • File permissions set appropriately

Network

  • Cameras on local network only
  • FTP upload over internet (consider FTPS)
  • No incoming connections required

Recommendations

  • Keep Pi system updated
  • Use strong camera passwords
  • Consider VPN for remote access
  • Regular backup of scripts

Future Enhancements

Potential Features

  • Web interface for monitoring
  • SMS/email notifications on failures
  • Cloud storage integration
  • Machine learning sunset quality prediction
  • Multi-day compilation
  • Weather data overlay
  • Social media auto-posting

System Improvements

  • Database logging
  • Grafana dashboard
  • Automated cleanup policies
  • Redundant storage
  • FTPS support
  • Configuration file (vs. hardcoded)

Documentation Files

  1. README.md – Complete system documentation
  2. INSTALL.md – Installation instructions
  3. QUICK_REFERENCE.md – Command reference
  4. PROJECT_SUMMARY.md – This file
  5. requirements.txt – Python dependencies

Support and Troubleshooting

System Check

bash

python3 system_check.py

Manual Testing

bash

# Test camera
python3 capture_amcrest.py

# Test compilation
python3 compile_video.py amcrest

# Test upload
python3 upload_ftp.py --test

Logs

bash

tail -f /var/log/scootercam-sunset.log

Project Stats

  • Scripts: 7 Python files
  • Total Lines: ~1,500
  • Documentation: 5 markdown files
  • Setup Time: ~15 minutes
  • Daily Runtime: ~60 minutes
  • Storage per Day: ~200 MB

Built for Scootercam.net – Capturing Lake Michigan sunsets since 2016 🌅

Scootercam