Created
March 11, 2026 17:26
-
-
Save HoughIO/7a29361a1a9c985a95ae49019dbda8c2 to your computer and use it in GitHub Desktop.
KittyCam Time-lapse
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Kevin & Todd Cam - Time-lapse Feature | |
| # Run on Pi | |
| echo "🎬 Installing time-lapse feature..." | |
| # Create directories | |
| sudo mkdir -p /opt/kittycam/snapshots | |
| sudo mkdir -p /opt/kittycam/timelapses | |
| sudo chown andy:andy /opt/kittycam/snapshots /opt/kittycam/timelapses | |
| # Snapshot capture script | |
| sudo tee /opt/kittycam/capture_snapshot.sh > /dev/null << 'EOF' | |
| #!/bin/bash | |
| # Capture a snapshot for time-lapse | |
| SNAP_DIR="/opt/kittycam/snapshots" | |
| DATE=$(date +%Y%m%d) | |
| TIME=$(date +%H%M%S) | |
| FILENAME="${SNAP_DIR}/${DATE}_${TIME}.jpg" | |
| # Grab frame from mjpg_streamer | |
| curl -s "http://127.0.0.1:8081/?action=snapshot" -o "$FILENAME" 2>/dev/null | |
| # Keep only last 2 days of snapshots (cleanup) | |
| find "$SNAP_DIR" -name "*.jpg" -mtime +2 -delete 2>/dev/null | |
| EOF | |
| sudo chmod +x /opt/kittycam/capture_snapshot.sh | |
| # Time-lapse generator script | |
| sudo tee /opt/kittycam/generate_timelapse.sh > /dev/null << 'EOF' | |
| #!/bin/bash | |
| # Generate daily time-lapse from yesterday's snapshots | |
| SNAP_DIR="/opt/kittycam/snapshots" | |
| TL_DIR="/opt/kittycam/timelapses" | |
| YESTERDAY=$(date -d "yesterday" +%Y%m%d) | |
| OUTPUT="${TL_DIR}/timelapse_${YESTERDAY}.mp4" | |
| # Check if we have snapshots from yesterday | |
| SNAP_COUNT=$(ls -1 ${SNAP_DIR}/${YESTERDAY}_*.jpg 2>/dev/null | wc -l) | |
| if [ "$SNAP_COUNT" -lt 10 ]; then | |
| echo "Not enough snapshots for yesterday ($SNAP_COUNT found)" | |
| exit 0 | |
| fi | |
| echo "Generating time-lapse from $SNAP_COUNT snapshots..." | |
| # Create file list | |
| LISTFILE=$(mktemp) | |
| ls -1 ${SNAP_DIR}/${YESTERDAY}_*.jpg | sort | while read f; do | |
| echo "file '$f'" >> "$LISTFILE" | |
| done | |
| # Generate time-lapse (10 fps, good quality but small) | |
| ffmpeg -y -f concat -safe 0 -i "$LISTFILE" \ | |
| -vf "scale=720:-2" \ | |
| -c:v libx264 -preset fast -crf 28 \ | |
| -movflags +faststart \ | |
| "$OUTPUT" 2>/dev/null | |
| rm -f "$LISTFILE" | |
| # Keep only last 14 days of time-lapses | |
| find "$TL_DIR" -name "timelapse_*.mp4" -mtime +14 -delete 2>/dev/null | |
| if [ -f "$OUTPUT" ]; then | |
| echo "Created: $OUTPUT" | |
| else | |
| echo "Failed to create time-lapse" | |
| fi | |
| EOF | |
| sudo chmod +x /opt/kittycam/generate_timelapse.sh | |
| # Add cron jobs | |
| (crontab -l 2>/dev/null | grep -v capture_snapshot | grep -v generate_timelapse | |
| echo "*/10 * * * * /opt/kittycam/capture_snapshot.sh" | |
| echo "0 4 * * * /opt/kittycam/generate_timelapse.sh >> /var/log/kittycam_timelapse.log 2>&1" | |
| ) | crontab - | |
| # Update nginx config to serve timelapses | |
| sudo tee /etc/nginx/sites-enabled/kittycam > /dev/null << 'NGINXEOF' | |
| server { | |
| listen 8080; | |
| server_name _; | |
| root /opt/kittycam/web; | |
| index index.html; | |
| proxy_buffering off; | |
| proxy_request_buffering off; | |
| location = /auth { | |
| if ($arg_key != "7jYVuk7F3cv0djjAQeNqURK8") { return 403; } | |
| return 200; | |
| } | |
| location /stream { | |
| proxy_pass http://127.0.0.1:8081/; | |
| proxy_http_version 1.1; | |
| proxy_set_header Connection ""; | |
| proxy_buffering off; | |
| proxy_cache off; | |
| proxy_read_timeout 3600s; | |
| proxy_send_timeout 3600s; | |
| chunked_transfer_encoding off; | |
| add_header Cache-Control "no-cache, no-store, must-revalidate"; | |
| add_header Pragma "no-cache"; | |
| } | |
| location = /api/events { | |
| alias /opt/kittycam/events.json; | |
| default_type application/json; | |
| add_header Cache-Control "no-cache"; | |
| } | |
| location /api/gacha/ { | |
| proxy_pass http://127.0.0.1:8082; | |
| proxy_http_version 1.1; | |
| proxy_set_header Host $host; | |
| add_header Cache-Control "no-cache"; | |
| } | |
| location = /api/log-view { | |
| proxy_pass http://127.0.0.1:8082; | |
| proxy_http_version 1.1; | |
| proxy_set_header Host $host; | |
| } | |
| location = /api/views/today { | |
| proxy_pass http://127.0.0.1:8082; | |
| proxy_http_version 1.1; | |
| proxy_set_header Host $host; | |
| } | |
| location /clips/ { | |
| alias /opt/kittycam/clips/; | |
| autoindex on; | |
| autoindex_format json; | |
| add_header Cache-Control "no-cache"; | |
| } | |
| location /timelapses/ { | |
| alias /opt/kittycam/timelapses/; | |
| autoindex on; | |
| autoindex_format json; | |
| add_header Cache-Control "no-cache"; | |
| } | |
| location /static/ { | |
| alias /opt/kittycam/web/static/; | |
| add_header Cache-Control "public, max-age=31536000"; | |
| } | |
| location ~* (sw\.js|manifest\.json)$ { | |
| add_header Cache-Control "no-cache, no-store, must-revalidate"; | |
| } | |
| location / { | |
| try_files $uri $uri/ =404; | |
| add_header Cache-Control "no-cache"; | |
| } | |
| } | |
| NGINXEOF | |
| sudo nginx -t && sudo systemctl reload nginx | |
| # Take first snapshot now | |
| /opt/kittycam/capture_snapshot.sh | |
| echo "✅ Time-lapse installed!" | |
| echo "" | |
| echo "• Snapshots every 10 min: /opt/kittycam/snapshots/" | |
| echo "• Daily time-lapse at 4am: /opt/kittycam/timelapses/" | |
| echo "• Accessible at: /timelapses/" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment