24 Commits
Author SHA1 Message Date
Claude 54f342224a docs: update test_last_full_moon.py README entry for full pipeline
Clarifies the script runs the complete production path including east
verification, and is equivalent to moon-phase-monthly.sh --phase full
--no-upload with a fixed output path.

https://claude.ai/code/session_01JieSeNQZ3X6fhsb11YyJrK
2026-05-02 12:53:25 +00:00
Claude d8bf01f86f docs: update test_last_full_moon.py entry to match full image pipeline
Describes all six steps the script now performs: full moon lookup,
moon stats, sun events regression check, NASA fetch, composite render,
and output path.

https://claude.ai/code/session_01JieSeNQZ3X6fhsb11YyJrK
2026-05-02 12:52:21 +00:00
Claude 4f61589ca6 docs: document test_last_full_moon.py in README
Added to the Moon jobs section of Manual operations with a brief
description of what the script checks and when it's useful.

https://claude.ai/code/session_01JieSeNQZ3X6fhsb11YyJrK
2026-05-02 12:48:50 +00:00
Claude 28c3c1dc63 Switch monthly phase close-ups to NASA SVS Dial-a-Moon at fullscreen
The previous east-flavored composite (tight-crop east region + lunar
texture overlay) was honest but visually limited: 38-px source moon, no
real terminator shadows on quarters, and a faint upscaled-halo
background that was less compelling than just a clean lunar render.

New flow:
- East stays the witness (verifies the moon was visible during the
  collection window) and supplies the timestamp.
- moon_dialamoon.py fetches the NASA SVS Dial-a-Moon render for that
  exact UTC hour. Free, public-domain, real-physics: correct phase,
  libration, and crater shadows for any timestamp.
- moon_composite.render_phase_closeup() places that render at ~92% of
  frame height on a 1920x1080 black background -- the long-telephoto
  look the user asked for.
- One API call per phase event (~36/year), cached forever in
  moon-ref/dialamoon/.

Quarter moons now show real 3D crater shadows along the terminator,
which the prior algorithmic phase-shadow couldn't simulate from a
full-moon reference.

Adds MOON_REQUIRE_EAST_VERIFY=true|false toggle so the user can choose
"only post when east saw it" (default, current behavior) vs "post every
cycle regardless of weather over east."

Drops the install-time lunar reference download (no longer needed) and
the now-unused per-phase phase-shadow path stays in moon_composite.py
for reference / future reuse.

https://claude.ai/code/session_015PBVDESC3KLMbq1LpA6qLn
2026-05-01 11:54:46 +00:00
Claude 5fb7ff09a3 Add nightly moon-track timelapse and monthly moon-phase composites
Two new jobs operate on the SUNRISE_CAM, sharing three Python helpers
(moon_phase, moon_detect, moon_composite) and one cached lunar texture:

- moon-track.sh: nightly batch detects the moon in each east frame,
  crops a 480x480 box around it, stitches into an mp4 that holds the
  moon roughly centred while clouds and stars drift past.

- moon-phase-monthly.sh: daily check that runs whichever phase composite
  is due that day. Handles full moon (posts D+3), first quarter (D+2,
  best-effort due to daytime-only geometry from east), and third quarter
  (D+2). Picks the frame closest in time to the exact phase moment that
  meets quality / altitude / illumination thresholds, then composites
  the cached lunar texture into it -- sky/halo/parallactic-angle/timing
  real from east, surface detail borrowed from the reference image.

Honest-by-design: a 38-px white blob from a wide-field IP camera cannot
be enhanced into crater detail by software. The composite makes the
borrowing explicit and constrains everything else (when, where, sky,
orientation) to match what east actually saw.

install.sh now downloads the skyfield ephemeris (de421.bsp) and the
default lunar reference (Wikipedia CC BY-SA full-moon photo) on first
run. Both can be overridden via .env.

https://claude.ai/code/session_015PBVDESC3KLMbq1LpA6qLn
2026-04-30 11:40:11 +00:00
Outis bd2ade49fc Merge pull request #48 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
ClDemoe/seasonal sunrise montage nn268
2026-04-23 08:03:12 -04:00
Claude 3f5b89e5da README: document backfilling multiple dates with 4-seasons.sh loop
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 22:31:06 +00:00
Outis fb1ed4a5fa Merge pull request #47 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
README: add git workflow section — install, pull, overwrite local cha…
2026-04-22 16:58:10 -04:00
Claude be784a9452 README: add git workflow section — install, pull, overwrite local changes
Covers: installing git, first clone, pulling updates, stash vs reset
--hard, checking diffs, switching branches, and a note that .env is
never touched by git pulls.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 20:55:20 +00:00
Outis 9b01e4323f Update README with XDG_RUNTIME_DIR export instructions
Added instructions to set XDG_RUNTIME_DIR in ~/.bashrc
2026-04-22 11:33:09 -04:00
Outis 9126e62a92 Update README.md 2026-04-22 11:32:39 -04:00
Outis 1f9f001755 Update README with environment variable setup 2026-04-22 11:30:37 -04:00
Claude c4fb086f1d Fix bugs found in post-refactor audit
- verify-mvt.sh: remove dead first _info= line (used MVT_START before
  defined); fix JPEG size loop to accumulate bytes correctly and display
  human-readable total; show size in delete confirmation
- montage-mvt.sh: grep -c uses || echo 0 instead of || true to be
  unambiguous about the no-match value under set -e
- capture.sh, capture-watchdog.sh: require camera name arg, remove
  silent SUNRISE_CAM fallback
- migrate-seasons.sh: require --cam arg, error if missing
- README.md, sky-cam.conf: remove stale fullday-video.sh references;
  README pipeline diagram updated to show verify-mvt.sh

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-20 16:34:05 +00:00
Claude 8c752fc165 Require camera name explicitly across all seasons scripts
No script defaults to SUNRISE_CAM (east) for the seasons pipeline.
Every direction is treated equally — camera name is a required arg,
not an optional override.

- 4-seasons.sh: $1 required, exits with usage if missing
- montage-mvt.sh: arg order changed to <cam> [date]; $1 required
- year-end-join.sh: $2 (cam) required
- verify-mvt.sh: $4 (cam) required
- migrate-seasons.sh: example commands updated to new arg order
- README.md: montage-mvt.sh examples updated

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-20 16:28:15 +00:00
Claude 3265ed80fd Add per-camera capture watchdog with stall and recovery notifications
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
2026-04-20 01:13:49 +00:00
Claude 8b9ad74c58 Fix six bugs found in final audit
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
2026-04-20 01:01:25 +00:00
Claude 64cec6b769 Rename default camera from 'sunrise' to 'east' for compass consistency
Cameras are now named by direction (east, north, south, west) throughout
config defaults, examples, and documentation. The config key SUNRISE_CAM
is unchanged — it still means 'which camera faces east and gets the sunrise
job'. Only the camera instance name value changes from 'sunrise' to 'east'.

sky-cam.conf: CAMERAS=(east), SUNRISE_CAM=east, SCHEDULE_*_east,
example comments updated to show all four compass points.
README.md: all command examples updated (4-seasons.sh east, journalctl
sky-cam-capture-east, etc.) — phenomenon references ('sunrise window',
'sunrise time') left unchanged.
bootstrap.sh: example updated to show compass directions.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-20 00:53:58 +00:00
Claude 9ea03d2249 Replace \$EDITOR with nano in README and bootstrap instructions
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-20 00:46:39 +00:00
Claude 4d5da05bc9 README: full rewrite — dependencies first, accurate quick start, current behavior
- Step 1 is now dependency installation (apt + pip3) before anything else
- SCRIPT_DIR removed from config table (auto-detected)
- RTSP/Mattermost credentials moved to .env section (step 4)
- install.sh now shown as generating .env.example before credentials are filled in
- Schedule settings explained: SEASONS/FULLDAY process yesterday; SUNRISE waits internally
- How it works: audio capture described as SUNRISE_TARGET_SECS centred on sunrise
- daily_sunrise_video.sh pipeline updated: steps 3a/3b shown separately
- Resilience section replaced with four-tier audio/overlay matrix table
- Camera audio section updated: exact duration, centred split, odd-second rule
- Manual operations: examples use explicit camera name argument

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-20 00:36:58 +00:00
Claude a1cf1304e4 Fix first-run blockers: MOVIES_DIR path, CAM_NAME, .env for Python, eval safety
daily_sunrise_video.sh: use \$MOVIES_DIR instead of \$BASE_DIR/movies so the
override in sky-cam.conf is respected when videos live on a separate drive.

capture.sh: default camera name falls back to \$SUNRISE_CAM (not the
undefined \$CAM_NAME) when no argument is passed.

sunrise2mm.py: also loads .env after sky-cam.conf so Mattermost credentials
moved to .env are actually visible to the upload script.

sunrise.py: raise a clear error message when LATITUDE/LONGITUDE/TIMEZONE
are missing from sky-cam.conf instead of an opaque KeyError.

4-seasons.sh, montage-mvt.sh: capture season_info.py output before eval so
a Python failure exits cleanly with a diagnostic message rather than
silently continuing with undefined variables.

bootstrap.sh: add system package install step (ffmpeg bc fonts-dejavu) and
show the .env setup step after install.sh generates .env.example.

README.md: correct Python package names and add fonts-dejavu dependency.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-19 23:37:10 +00:00
Claude 66fe1f46ca Fix CAM_NAME bug, set -x noise, wrong Python package in README
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
2026-04-19 21:56:33 +00:00
Claude 15b7970dfa README: document audio fallback library and download-sunrise-sounds.py usage
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-19 21:22:23 +00:00
Claude 9fe0051f70 Add pure-ffmpeg RTSP capture and camera audio for sunrise videos
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
2026-04-19 20:59:40 +00:00
Claude 6629f91219 Add README with quick-start, architecture overview, and operations guide
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-19 19:35:07 +00:00