New AUDIO_DIR variable (like BASE_DIR/MOVIES_DIR) is the root for all
audio recordings. Set in .env to put audio on a separate drive.
Directory layout:
AUDIO_DIR/<cam>/YYYY-MM-DD/HH-MM-SS.m4a — ambient recordings
AUDIO_DIR/sunrise/<cam>/YYYY-MM-DD/sunrise-audio.m4a — sunrise clips
sky-cam.conf:
- Add AUDIO_DIR="${AUDIO_DIR:-$BASE_DIR/audio}" in storage section
- Remove AMBIENT_DIR (replaced by AUDIO_DIR)
- Add SUNRISE_AUDIO_RETENTION_DAYS=7 (sunrise clips kept separately from ambient)
- Add per-camera ambient retention examples:
AMBIENT_RETENTION_DAYS_south=60 (keep bird recordings longer)
ambient-record.sh:
- Use AUDIO_DIR instead of AMBIENT_DIR
- Per-camera retention: AMBIENT_RETENTION_DAYS_<cam> overrides global default
sunrise-audio-capture.sh:
- Save clips to AUDIO_DIR/sunrise/<cam>/<date>/sunrise-audio.m4a
- Rolling retention of sunrise clips (SUNRISE_AUDIO_RETENTION_DAYS)
daily_sunrise_video.sh:
- Look for cam_audio in new AUDIO_DIR/sunrise path first, fall back to
old BASE_DIR path so existing recordings keep working
install.sh:
- Pre-create AUDIO_DIR/<cam> and AUDIO_DIR/sunrise/<SUNRISE_CAM> dirs
- Add AUDIO_DIR to .env.example storage section
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
81 lines
2.5 KiB
Bash
Executable File
81 lines
2.5 KiB
Bash
Executable File
#!/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_var="AMBIENT_RETENTION_DAYS_${CAM}"
|
|
RETAIN="${!retain_var:-${AMBIENT_RETENTION_DAYS:-30}}"
|
|
SAVE_DIR="${AUDIO_DIR:-$BASE_DIR/audio}"
|
|
|
|
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
|