Per-camera capture interval; ambient recorder; fix 4-seasons one-frame bug
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
This commit is contained in:
Executable
+79
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
# ambient-record.sh <cam-name> — continuous ambient audio recorder.
|
||||
#
|
||||
# Records RTSP audio in AMBIENT_CHUNK_SECS chunks, saves to:
|
||||
# AMBIENT_DIR/<cam>/YYYY-MM-DD/HH-MM-SS.m4a
|
||||
#
|
||||
# Files are named by the recording start time so the collection is easy to
|
||||
# browse and pick from for white-noise / nature sound playback.
|
||||
#
|
||||
# Runs as a permanent systemd service (Type=simple) alongside capture.sh.
|
||||
# Reconnects automatically if the camera stream drops.
|
||||
# Applies rolling retention (AMBIENT_RETENTION_DAYS).
|
||||
#
|
||||
# Camera audio is typically 8 kHz mono (phone quality) — suitable for bird
|
||||
# song, rain, wind, and ambient nature sounds; check your camera's web
|
||||
# interface for a higher sample rate setting if available.
|
||||
|
||||
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
|
||||
|
||||
CHUNK="${AMBIENT_CHUNK_SECS:-1800}"
|
||||
BITRATE="${AMBIENT_BITRATE:-96k}"
|
||||
RETAIN="${AMBIENT_RETENTION_DAYS:-30}"
|
||||
SAVE_DIR="${AMBIENT_DIR:-$BASE_DIR/ambient}"
|
||||
|
||||
echo "Ambient recorder started: cam=$CAM chunk=${CHUNK}s bitrate=$BITRATE retain=${RETAIN}d"
|
||||
echo "Saving to: $SAVE_DIR/$CAM/"
|
||||
|
||||
while true; do
|
||||
today=$(date +%Y-%m-%d)
|
||||
dir="$SAVE_DIR/$CAM/$today"
|
||||
mkdir -p "$dir"
|
||||
|
||||
timestamp=$(date +%H-%M-%S)
|
||||
outfile="$dir/${timestamp}.m4a"
|
||||
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Recording → $outfile (${CHUNK}s)"
|
||||
|
||||
ffmpeg -loglevel warning \
|
||||
-rtsp_transport tcp \
|
||||
-i "$RTSP_URL" \
|
||||
-t "$CHUNK" \
|
||||
-vn \
|
||||
-c:a aac -b:a "$BITRATE" \
|
||||
-y "$outfile" || true
|
||||
|
||||
if [ ! -s "$outfile" ]; then
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$CAM] recording failed or empty — retrying in 30s"
|
||||
rm -f "$outfile"
|
||||
sleep 30
|
||||
continue
|
||||
fi
|
||||
|
||||
actual=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$outfile" 2>/dev/null || echo "?")
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Saved: $(basename "$outfile") (${actual}s)"
|
||||
|
||||
# Rolling retention
|
||||
if [ "${RETAIN}" -gt 0 ]; then
|
||||
deleted=$(find "$SAVE_DIR/$CAM" -name "*.m4a" -mtime +"$RETAIN" -print -delete 2>/dev/null | wc -l)
|
||||
[ "$deleted" -gt 0 ] && echo "Retention: deleted $deleted file(s) older than ${RETAIN}d"
|
||||
fi
|
||||
done
|
||||
Reference in New Issue
Block a user