Skip to content

UniFi Protect Time-Lapse Generator - Automated daily snapshot capture and time-lapse creation from UniFi Protect cameras

License

Notifications You must be signed in to change notification settings

dweekly/lawn-lapse

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

75 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Lawn Lapse Logo

🌱 Lawn Lapse

npm version CI License: MIT Node Version

Automated time-lapse generator for UniFi Protect cameras

Captures daily snapshots at your chosen time and creates beautiful time-lapse videos showing changes over days, months, or years.

🎬 Demo

Watch your lawn, garden, construction project, or any outdoor space transform over time with automatically generated time-lapse videos.

Lawn Lapse Demo

▢️ Watch the demo on YouTube - 109 days of lawn evolution captured with 24fps motion interpolation

✨ Features

  • πŸ“Έ Smart Setup - Auto-detects configuration and guides through setup on first run
  • πŸŽ₯ Multi-Camera Support - Track multiple cameras with isolated snapshots and timelapses
  • 🎬 Motion Interpolation - Cinematic 24fps with smooth frame blending for professional results
  • πŸ”„ Smart Historical Backfill - Automatically fetches historical footage until recordings run out
  • πŸ’Ύ Permanent Archive - Stores snapshots locally forever (beyond NVR retention limits)
  • πŸ” Simple Authentication - Uses username/password for easy setup
  • ⏰ Advanced Scheduling - Fixed times, intervals, or sunrise/sunset based captures
  • πŸ“Š Progress Tracking - Shows detailed progress during snapshot fetching
  • 🎯 Smart Defaults - Optimized settings out of the box (24fps with interpolation, best quality)

πŸ“‹ Prerequisites

  • Node.js 18+ (required for modern JavaScript features)
  • ffmpeg installed (brew install ffmpeg on macOS, apt install ffmpeg on Linux)
  • UniFi Protect system with at least one camera
  • Admin access to UniFi Protect

πŸš€ Quick Start

No installation needed! Just run:

npx lawn-lapse

That's it! The first time you run it, you'll be guided through an interactive setup that will:

  1. Connect to your UniFi Protect system
  2. Select your camera(s)
  3. Fetch historical snapshots (as far back as your NVR has them!)
  4. Generate your first time-lapse video

Want to install it? You can optionally install globally:

npm install -g lawn-lapse
lawn  # Now you can just type "lawn"!

For developers: Clone the repo and run npm install && npm start

🎯 Usage

Main Command

lawn [command]

When run without arguments:

  • First run: Automatically starts interactive setup
  • Subsequent runs: Captures snapshots and updates time-lapse

Commands

Command Description
lawn Run capture (auto-setup if first time)
lawn status Show configuration and statistics
lawn cron Set up or update automated daily captures
lawn version Show version number
lawn help Display help information

Verbose Mode

Add -v or --verbose flag for detailed output:

lawn -v  # Shows ffmpeg output and detailed logging

πŸ”§ Configuration

Interactive Setup

On first run, lawn will guide you through:

  1. UniFi Protect Connection

    • Host/IP address (defaults to 192.168.1.1)
    • Username (defaults to admin)
    • Password
  2. Camera Selection

    • Shows all available cameras with model info
    • Indicates offline cameras
    • Displays resolution capabilities
    • Multi-camera support: Select multiple cameras for parallel tracking
    • Each camera gets its own snapshot and timelapse directories
  3. Snapshot Settings

    • Capture time (24-hour format, defaults to 12:00)
    • Output directories auto-generated per camera (e.g., ./snapshots/front-yard/)
  4. Automation Setup

    • Optional cron job installation
    • Automatic daily captures at specified time for all cameras

Configuration File

Settings are stored in lawn.config.json:

{
  "version": 2,
  "unifi": {
    "host": "192.168.1.1",
    "username": "admin",
    "password": "your-password"
  },
  "schedule": {
    "timezone": "America/Los_Angeles",
    "mode": "fixed-time",
    "fixedTimes": ["12:00"]
  },
  "cameras": [
    {
      "id": "abc123",
      "name": "Front Yard",
      "snapshotDir": "./snapshots/front-yard",
      "timelapseDir": "./timelapses/front-yard",
      "video": { "fps": 24, "quality": 1, "interpolate": true }
    },
    {
      "id": "def456",
      "name": "Back Yard",
      "snapshotDir": "./snapshots/back-yard",
      "timelapseDir": "./timelapses/back-yard",
      "video": { "fps": 24, "quality": 1, "interpolate": true }
    }
  ]
}

⚠️ Security Note: Keep lawn.config.json secure and never commit it to version control

πŸ“Έ How It Works

Snapshot Collection

  1. Daily Capture: At your specified time, captures a frame from the camera
  2. Historical Backfill: On first run, walks backward through available UniFi recordings until no footage remains
  3. Smart Fetching: Only downloads missing snapshots, skips existing ones
  4. Progress Display: Shows [n/total] progress for each snapshot

Time-lapse Generation

  1. Auto-detection: Finds the highest resolution from your snapshots
  2. Smart Scaling: Maintains aspect ratio while maximizing quality
  3. Optimized Encoding: Uses H.264 with slow preset for best compression
  4. Configurable FPS: Default 24fps with motion interpolation for cinematic smooth playback

File Organization

lawn-lapse/
β”œβ”€β”€ snapshots/              # Per-camera snapshot directories
β”‚   β”œβ”€β”€ front-yard/
β”‚   β”‚   β”œβ”€β”€ 2024-01-01_1200.jpg
β”‚   β”‚   β”œβ”€β”€ 2024-01-02_1200.jpg
β”‚   β”‚   └── ...
β”‚   └── back-yard/
β”‚       β”œβ”€β”€ 2024-01-01_1200.jpg
β”‚       └── ...
β”œβ”€β”€ timelapses/             # Per-camera timelapse directories
β”‚   β”œβ”€β”€ front-yard/
β”‚   β”‚   └── timelapse_12h00_2024-01-01_to_2024-03-15.mp4
β”‚   └── back-yard/
β”‚       └── timelapse_12h00_2024-01-01_to_2024-03-15.mp4
β”œβ”€β”€ lawn.config.json        # Project configuration
└── logs/lawn-lapse.log     # Cron job logs

πŸ” Monitoring

Check Status

lawn status

Shows:

  • Total snapshots collected
  • Date range of footage
  • Gap detection in sequence
  • Time-lapse videos generated
  • Cron job status
  • Last capture time

Example Output

πŸŽ₯ Lawn Lapse Status Report
============================================================

πŸ“· Cameras (2 configured):
============================================================

πŸ“Ή Front Yard (abc123)
------------------------------------------------------------
  Snapshots: ./snapshots/front-yard
  Timelapses: ./timelapses/front-yard

  πŸ“Έ Snapshots: 45 at 12:00
     Range: 2024-01-01 to 2024-02-14
     βœ“ No gaps

  🎬 Time-lapses: 1 video(s)
     Latest: timelapse_12h00_2024-01-01_to_2024-02-14.mp4 (8.3MB)
     Covers: 45 days (2024-01-01 to 2024-02-14)

πŸ“Ή Back Yard (def456)
------------------------------------------------------------
  Snapshots: ./snapshots/back-yard
  Timelapses: ./timelapses/back-yard

  πŸ“Έ Snapshots: 42 at 12:00
     Range: 2024-01-04 to 2024-02-14
     βœ“ No gaps

  🎬 Time-lapses: 1 video(s)
     Latest: timelapse_12h00_2024-01-04_to_2024-02-14.mp4 (7.1MB)
     Covers: 42 days (2024-01-04 to 2024-02-14)

⏰ Cron Job:
  βœ“ Active: Daily at 12:00

πŸ” Authentication:
  βœ“ Credentials configured
  Username: admin

============================================================
πŸ“Š Summary:
  βœ“ System operational: 2 camera(s), 87 total snapshot(s), 2 time-lapse(s)

πŸ›  Troubleshooting

Common Issues

Problem Solution
"No cameras found" Ensure UniFi Protect is accessible and user has admin privileges
"Authentication failed" Check username/password, ensure 2FA is disabled for API access
Timeout errors Reduce video duration or check network connectivity
Missing snapshots Verify camera was online and recording at capture time
Cron not running Check cron service is enabled: sudo launchctl load -w /System/Library/LaunchDaemons/com.vix.cron.plist

Debug Mode

Run with verbose flag for detailed debugging:

lawn -v

Manual Capture

Force an immediate capture regardless of schedule:

npm exec lawn

🀝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Development Setup

# Clone repository
git clone https://github.com/dweekly/lawn-lapse.git
cd lawn-lapse

# Install dependencies
npm install

# Run in development
node lawn-lapse.js -v

# Format code
npm run format

# Lint code
npm run lint

πŸ“ API Documentation

Main Functions

The project exports several key functions for programmatic use:

import { runSetup, runCapture } from "./lawn-lapse.js";

// Run interactive setup
await runSetup();

// Capture snapshots and generate time-lapse
await runCapture();

See API.md for detailed documentation.

πŸ”’ Security

  • Credentials are stored locally in lawn.config.json
  • Never commit lawn.config.json to version control
  • Uses UniFi Protect's official API library
  • No external services or telemetry
  • All data stays on your local machine

πŸ“œ License

MIT License - see LICENSE file for details

πŸ™ Acknowledgments

  • Built with unifi-protect library
  • Inspired by traditional time-lapse photography techniques
  • Thanks to the UniFi Protect community

πŸ“§ Support


Made with ❀️ for the UniFi Protect community

About

UniFi Protect Time-Lapse Generator - Automated daily snapshot capture and time-lapse creation from UniFi Protect cameras

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •