Skip to content

Instantly share code, notes, and snippets.

@HoughIO
Created March 11, 2026 17:26
Show Gist options
  • Select an option

  • Save HoughIO/7a29361a1a9c985a95ae49019dbda8c2 to your computer and use it in GitHub Desktop.

Select an option

Save HoughIO/7a29361a1a9c985a95ae49019dbda8c2 to your computer and use it in GitHub Desktop.
KittyCam Time-lapse
#!/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