- sky-cam.conf: CAMERAS now includes east, north, south with staggered
SCHEDULE_SEASONS times (01:00, 01:30, 02:00); fullday schedules and
tuning removed
- install.sh: fullday service/timer generation removed entirely
- fullday-video.sh + systemd units: deleted
- montage-mvt.sh: post-build technical checks (duration drift, video/audio
stream presence) added; notification now includes check results and the
exact verify-mvt.sh command to run
- verify-mvt.sh: new interactive CLI for montage review — shows checks,
plays video, deletes source JPEG folders on approval, or re-runs montage
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
capture-watchdog.sh: long-running script that checks the newest JPEG mtime
in each camera's output directory every CAPTURE_STALE_SECS/3 seconds (min 5s).
Sends a stall notification via notify.sh if no new frame has arrived within
CAPTURE_STALE_SECS. Sends a recovery notification once new frames resume.
Only alerts if the camera was previously working (avoids false positives on
first start or overnight before the first frame of the day).
sky-cam.conf: CAPTURE_STALE_SECS=30 added next to CAPTURE_INTERVAL with a
note that it should be at least 2x the interval.
install.sh: generates sky-cam-watchdog-<cam>.service for every camera that
has a RTSP URL configured. The watchdog service starts after and alongside
the capture service, restarts on failure, and is enabled/started with the
same loop as the capture service.
README.md: note about watchdog and journalctl command for its logs.
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
montage-mvt.sh, year-end-join.sh: CAM_NAME fallback referenced undefined
\$CAM_NAME — crashes under set -euo pipefail on manual runs without args.
Fixed to fall back to \$SUNRISE_CAM (same fix applied earlier to other scripts).
notify.sh: Mattermost notification guard only checked MM_NOTIFY_CHANNEL_ID,
not mattermost_url or access_token. If those are unset, curl would send a
malformed request silently. Added guards for all three required values.
install.sh: seasons/fullday service units had literal \n in After=/Wants=
lines because bash does not interpret \n in heredoc variable expansions.
Changed to \$'...' syntax so actual newlines are written, making valid
systemd unit files. Also: audio capture timer now uses \$SCHEDULE_SUNRISE
instead of hardcoded 03:00, keeping it in sync if the user changes the
schedule.
sunrise-audio-capture.sh: record_start_sec could theoretically go negative
(sunrise very early + large SUNRISE_TARGET_SECS). Added floor-at-zero guard.
daily_sunrise_video.sh: added comment explaining why audio_offset is always 0.
README.md: fix CAM_RTSP_sunrise example to CAM_RTSP_east.
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
sky-cam.conf now sources .env from the same directory at the bottom of the
file, so RTSP URLs, Mattermost tokens, and notification credentials can live
outside version control. Plaintext credential placeholders removed from conf.
install.sh generates .env.example on every run with the correct CAM_RTSP_*
variable names derived from the CAMERAS list, so users always know exactly
what to put in .env for their specific camera setup.
.gitignore: add .env and sunrise-sounds/ (downloaded audio library).
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
daily_sunrise_video.sh: derive CAM_NAME from $1 (defaulting to SUNRISE_CAM)
instead of an undefined variable; this was causing empty image/output paths.
install.sh: pass $SUNRISE_CAM as argument to daily_sunrise_video.sh so it
matches the pattern used by every other per-camera script.
sunrise2mm.py: use SUNRISE_CAM config key (not the undefined CAM_NAME) to
locate the output directory; fixes silent path mismatch on non-default names.
4-seasons.sh: remove stray `set -x` that was flooding systemd logs with
shell trace output.
README.md: correct Python dependencies from `ephem` to `suntime pytz` to
match what sunrise.py actually imports.
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
Removes dependency on MotionEye or any NVR software. Everything is now
CLI/ffmpeg configured entirely from sky-cam.conf.
capture.sh
Long-running systemd service (one per camera) that pulls frames from the
camera's RTSP stream at CAPTURE_INTERVAL seconds, writing HH-MM-SS.jpg
into BASE_DIR/<cam>/YYYY-MM-DD/. Restarts at midnight for the new date
directory; auto-reconnects on camera disconnect.
sunrise-audio-capture.sh
One-shot service triggered at 03:00. Waits until (sunrise minus
SUNRISE_PRE_MIN minus AUDIO_PRE_BUFFER_MIN), then records the RTSP audio
stream for the full sunrise window. Output deleted after mixing.
daily_sunrise_video.sh
Step 3 now mixes in sunrise-audio.m4a when AUDIO_ENABLED=true and the
file exists. Audio is centred on actual sunrise time at natural speed
while the video plays as the sped-up timelapse. Uses filter_complex
when audio is present (can't combine -vf with -filter_complex).
install.sh
Generates sky-cam-capture-<cam>.service for each camera with CAM_RTSP_<cam>
set, and sky-cam-audio-capture.{service,timer} when AUDIO_ENABLED=true.
sky-cam.conf
New settings: CAM_RTSP_<cam>, CAPTURE_INTERVAL, AUDIO_ENABLED,
AUDIO_PRE_BUFFER_MIN, CAPTURE_AUDIO_BITRATE.
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
daily_sunrise_video.sh:
- Fixed: was using undefined \$MOVIES_DIR (now \$BASE_DIR/movies)
- Fixed: sunrise_overlay.py was called but never existed — would fail daily
- Fixed: speed-adjust step had no explicit codec (-c:v libx264 missing)
- New: sunrise time overlaid as stacked vertical characters on the right
side using ffmpeg drawtext — no Python/Pillow dependency
- New: upload removed from script; now triggered by systemd OnSuccess=
- Combines speed-adjust and overlay into one ffmpeg pass (was two)
- SUNRISE_OVERLAY_OPACITY from conf controls transparency
install.sh:
- sky-cam-sunrise.service gains OnSuccess=sky-cam-sunrise-upload.service
so upload only runs when video creation succeeds, with separate log
- New sky-cam-sunrise-upload.service runs sunrise2mm.py
sunrise2mm.py: add shebang + chmod +x so systemd ExecStart= calls it directly
sky-cam.conf: add SUNRISE_OVERLAY_OPACITY=0.45
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
sky-cam.conf:
- CAMERAS array replaces single CAM_NAME; add a name, add its schedules,
re-run install.sh — no script editing needed
- SCHEDULE_SUNRISE, SCHEDULE_SEASONS_<cam>, SCHEDULE_FULLDAY_<cam> replace
hardcoded times in install.sh
- Notification options commented out (uncomment to enable)
- Lat/lon set to mid-Atlantic (25.0, -38.0) as neutral placeholder
install.sh:
- Loops over CAMERAS to generate per-camera sky-cam-seasons-<cam> and
sky-cam-fullday-<cam> timers with schedules from conf
- Sunrise timer remains a single sky-cam-sunrise unit (SUNRISE_CAM only)
fullday-video.sh, 4-seasons.sh, montage-mvt.sh, year-end-join.sh:
- Each accepts camera name as an argument (systemd passes it via ExecStart)
and falls back to conf default when run manually without an arg
- Camera name propagates through the full call chain:
4-seasons → montage-mvt → year-end-join
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
sky-cam.conf
- Add SCRIPT_DIR (install location) and CAM_NAME (camera/folder name)
- These are the only values that change when deploying to a new machine
install.sh (new)
- Sources sky-cam.conf, generates all systemd .service and .timer units
with correct ExecStart paths, then enables and starts the timers
- Run once after editing sky-cam.conf; run again if paths change
- Supports --system flag for system-wide install
All .sh scripts + sunrise2mm.py
- No hardcoded paths remain
- script_name=$(basename ...) derivation replaced by $CAM_NAME from conf
- sunrise_video.10s.sh now sources sky-cam.conf for BASE_DIR, CAM_NAME,
and SCRIPT_DIR (replaces all /home/motion/... references)
- sunrise2mm.py builds video path from BASE_DIR + CAM_NAME in conf
systemd/ template files kept as reference but no longer need editing
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ