Per-camera capture interval: CAPTURE_INTERVAL_<cam> in sky-cam.conf overrides the global value for a specific camera. capture.sh and 4-seasons.sh both respect it. Example: south at 30s saves storage; north at 5s gives smoother motion. 4-seasons.sh one-frame bug fix: Same root cause as the sunrise scripts — concat list had no 'duration' entries, collapsing all JPEG frames to timestamp 0. Fixed by writing 'duration INTERVAL' per frame. Added fps=25 to the speed-adjust step so the VFR source resamples to a standard frame rate. ambient-record.sh (new): Continuous AAC recorder for natural sounds (birds, rain, wind). Saves AMBIENT_CHUNK_SECS chunks to AMBIENT_DIR/<cam>/YYYY-MM-DD/HH-MM-SS.m4a. Reconnects automatically on stream failure. Rolling retention via AMBIENT_RETENTION_DAYS. Enabled by setting AMBIENT_ENABLED=true and listing cameras in AMBIENT_CAMS in sky-cam.conf, then re-running install.sh. https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
69 lines
2.1 KiB
Bash
Executable File
69 lines
2.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# capture.sh <cam-name> — continuous JPEG frame capture from a camera's RTSP
|
|
# stream. Replaces MotionEye or any NVR for sky-cam's timelapse pipeline.
|
|
# Pure ffmpeg — no NVR software required.
|
|
#
|
|
# Run as a long-running systemd service (Type=simple), one per camera.
|
|
# install.sh generates sky-cam-capture-<cam>.service automatically when
|
|
# CAM_RTSP_<cam> is set in sky-cam.conf.
|
|
#
|
|
# Writes: BASE_DIR/<cam>/YYYY-MM-DD/HH-MM-SS.jpg
|
|
# Restarts ffmpeg at midnight so images land in the correct date directory.
|
|
# On camera disconnect, waits 30 s then reconnects automatically.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
|
|
source "$SCRIPT_DIR/sky-cam.conf"
|
|
source "$SCRIPT_DIR/.env" 2>/dev/null || true
|
|
export TZ="$TIMEZONE"
|
|
|
|
CAM="${1:-}"
|
|
if [ -z "$CAM" ]; then
|
|
echo "Usage: $0 <camera-name>"
|
|
exit 1
|
|
fi
|
|
|
|
rtsp_var="CAM_RTSP_${CAM}"
|
|
RTSP_URL="${!rtsp_var:-}"
|
|
if [ -z "$RTSP_URL" ]; then
|
|
echo "ERROR: CAM_RTSP_${CAM} not set in .env"
|
|
exit 1
|
|
fi
|
|
|
|
interval_var="CAPTURE_INTERVAL_${CAM}"
|
|
INTERVAL="${!interval_var:-${CAPTURE_INTERVAL:-10}}"
|
|
echo "Starting capture: cam=$CAM interval=${INTERVAL}s"
|
|
|
|
while true; do
|
|
today=$(date +%Y-%m-%d)
|
|
dir="$BASE_DIR/$CAM/$today"
|
|
mkdir -p "$dir"
|
|
|
|
# Run until midnight + 5 s so the new day's directory is ready on restart
|
|
midnight=$(date -d "tomorrow 00:00:00" +%s)
|
|
now=$(date +%s)
|
|
duration=$(( midnight - now + 5 ))
|
|
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Capturing → $dir (rollover in ${duration}s)"
|
|
|
|
# -strftime 1 expands %H-%M-%S in the output path using the frame timestamp
|
|
ffmpeg -loglevel warning \
|
|
-rtsp_transport tcp \
|
|
-i "$RTSP_URL" \
|
|
-t "$duration" \
|
|
-vf "fps=1/${INTERVAL}" \
|
|
-f image2 \
|
|
-strftime 1 \
|
|
-q:v 2 \
|
|
"${dir}/%H-%M-%S.jpg" || true
|
|
|
|
# If ffmpeg exited before midnight the camera dropped — wait then retry
|
|
if [ "$(date +%s)" -lt "$midnight" ]; then
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$CAM] stream lost — retrying in 30s"
|
|
sleep 30
|
|
else
|
|
sleep 2 # brief pause at midnight before day rollover restart
|
|
fi
|
|
done
|