Commit Graph
187 Commits
Author SHA1 Message Date
Claude 65b8caf7f9 Reorder audio fallback chain: today → live RTSP → yesterday → library
Moves live RTSP capture to 2nd position so current ambient sound is
preferred over a day-old recording when today's scheduled capture is missing.

https://claude.ai/code/session_01DANuzLCLhhQ7Li12RTcswY
2026-04-30 11:53:57 +00:00
Claude c2d4d97361 Fix audio: live RTSP fallback + mix retry + journal in ntfy; overlay at 15%
- daily_sunrise_video.sh: add live RTSP capture as final fallback in production
  audio selection (fires when today, yesterday, and library all miss)
- On audio mix failure, retry once with a fresh live RTSP capture before
  giving up — handles corrupt/incompatible pre-recorded files
- When mix still fails after retry, append last 30 lines of
  sky-cam-audio-capture.service journal to the ntfy notification body
- Move sunrise-time text overlay from 5% to 15% above the bottom edge

https://claude.ai/code/session_01DANuzLCLhhQ7Li12RTcswY
2026-04-30 11:50:02 +00:00
Outis 03ebb53754 Add files via upload 2026-04-30 03:07:22 -04:00
Outis 69b9056276 Add files via upload 2026-04-30 02:37:25 -04:00
Outis 499bafdcc2 Merge pull request #55 from outis1one/claude/comment-sunrise-overlay-9LvlR
Trim weather-tag vocabulary to audio-relevant precipitation only
2026-04-29 14:58:11 -04:00
Claude 5810ab0194 Trim weather-tag vocabulary to audio-relevant precipitation only
Drops clear/cloudy/fog/windy and the wind-speed override — those
conditions sound the same on the recordings, so they don't earn a tag.
Also renames "rainshower" → "rainstorm" and rebalances the rain
mapping so 503/504/522 (extreme + heavy showers) get the storm tag.

Final vocabulary: thunderstorm, rain, rainstorm, snow, snowstorm.
Anything else falls through to the un-tagged filename.
2026-04-29 18:55:59 +00:00
Outis 5d00ac954f Merge pull request #54 from outis1one/claude/comment-sunrise-overlay-9LvlR
Claude/comment sunrise overlay 9 lvl r
2026-04-29 14:51:11 -04:00
Claude 9e1087f875 Tag ambient audio chunks with current OpenWeather conditions
Adds weather-tag.sh, a small failure-safe helper that queries OpenWeather's
free "Current weather" endpoint and prints one tag from a fixed vocabulary
(thunderstorm, rain, rainshower, snow, snowstorm, fog, windy, cloudy, clear)
or nothing on any failure.

ambient-record.sh calls it just before each 30-minute chunk so the filename
reflects conditions at the moment of capture, e.g.
  east-08-30-00-thunderstorm.m4a
  east-12-00-00-clear.m4a
A foggy dawn no longer mislabels the sunny afternoon files.

Off by default. Enable with WEATHER_ENABLED=true and an
OPENWEATHER_API_KEY entry in .env; missing key / API error / disabled
toggle all fall through to the un-tagged filename, never blocking the
recorder.
2026-04-29 18:40:27 +00:00
Claude 7c5a703222 Fix sky-cam-audio-capture.service spurious failure on no-op retention
The retention block ended with `[ test ] && echo`, which under `set -e`
returns exit 1 when `deleted` is 0 — the normal case on most days. As
the script's last command, that bash exit propagated to systemd, which
marked the unit failed and fired the OnFailure ntfy even though the
audio file was written successfully.

Add `|| true` and an explicit `exit 0` so a no-op retention pass is
treated as success.
2026-04-29 18:33:03 +00:00
Claude cba5b5b1e8 Document drawtext overlay settings for easy customization
Adds a quick-edit cheatsheet covering font, color, size, position, and
shadow/border for the sunrise-time overlay so the layout can be tweaked
without grokking ffmpeg's drawtext syntax.
2026-04-29 18:20:20 +00:00
Outis 119d58ad4c Merge pull request #53 from outis1one/claude/sunrise-video-audio-overlay-N0I0I
Claude/sunrise video audio overlay n0 i0 i
2026-04-24 10:47:59 -04:00
Claude 93935876de sunrise: scale audio fades to 8.5% of target duration
Replaces the fixed 0.3s fade with SUNRISE_TARGET_SECS * 0.085, so a 10s
clip now fades 0.85s in and out.  The fade scales automatically if the
target duration is tuned later.
2026-04-24 12:27:52 +00:00
Claude 63b4d2e2d9 sunrise: quicker audio fades, raise overlay, yesterday-audio fallback
- Shorten audio fade in/out to 0.3s so they fit comfortably in the 10s clip.
- Lift the sunrise-time overlay by ~5% of frame height to clear the
  burnt-in timestamp on the source images.
- When today's sunrise recording is missing, fall back to yesterday's
  clip before reaching for the library fallback.
2026-04-24 12:15:07 +00:00
Outis 381e03453c Merge pull request #52 from outis1one/claude/fix-mvt-video-playback-NhFjs
4-seasons: add progress reporting during validation and encoding
2026-04-23 12:00:20 -04:00
Claude d776fad0cb 4-seasons: add progress reporting during validation and encoding
- Print "Validating N frames..." before the loop, including active
  filter thresholds when grey-checking is on
- Print "X / N frames checked..." every 500 frames so the user can
  see the loop is alive during the long ImageMagick pass
- Print "Validation done: N valid frames" after the loop
- Note "(may take several minutes)" on the Step 1 encode echo
- Show the speed factor and target together: "28.8x → 11.08s target"

https://claude.ai/code/session_01U29A8NpgJ41tboiggZNmk8
2026-04-23 14:21:50 +00:00
Outis d54716c054 Merge pull request #51 from outis1one/claude/fix-mvt-video-playback-NhFjs
4-seasons: fix silent exit in grey-frame filter (read + set -e)
2026-04-23 10:03:19 -04:00
Claude 307224fc26 4-seasons: fix silent exit in grey-frame filter (read + set -e)
When SEASONS_GREY_STDDEV_MIN is enabled, ImageMagick's convert outputs
the stddev/mean values without a trailing newline.  read exits 1 on EOF-
without-newline even when it successfully populated the variables.  With
set -euo pipefail this kills the script silently on the very first image
that enters the grey-filter code path — producing the observed symptom:
script stops after "Images found:" with no error and no video.

Fix: append || true so read's EOF exit code is absorbed.  The variables
are still set correctly; only the exit code changes.

https://claude.ai/code/session_01U29A8NpgJ41tboiggZNmk8
2026-04-23 14:02:24 +00:00
Outis a0e88cc528 Merge pull request #50 from outis1one/claude/fix-mvt-video-playback-NhFjs
4-seasons: fix silent exit on clean days (set -e + && gotcha)
2026-04-23 09:53:55 -04:00
Claude 4a14d539a4 4-seasons: fix silent exit on clean days (set -e + && gotcha)
When no corrupt or grey frames exist (bad=0, grey=0), the two
conditional-echo lines

  [ "$bad"  -gt 0 ] && echo "WARNING: ..."
  [ "$grey" -gt 0 ] && echo "INFO: ..."

exit with code 1 because [ 0 -gt 0 ] is false and && short-circuits.
With set -euo pipefail the script treats that 1 as an error and exits
immediately with no output — producing exactly the "ran without making
a video, no error, no notification" symptom on any normal day where all
frames are valid.

Fix: append || true to each line so the expression always exits 0.

https://claude.ai/code/session_01U29A8NpgJ41tboiggZNmk8
2026-04-23 13:52:29 +00:00
Outis a1e1713111 Enable audio capture and notifications in config 2026-04-23 09:46:13 -04:00
Outis 6e4fd951b8 Merge pull request #49 from outis1one/claude/fix-mvt-video-playback-NhFjs
4-seasons: fix VFR pause/jump in daily MVT clips
2026-04-23 09:44:48 -04:00
Outis 065700ea69 Add files via upload 2026-04-23 09:29:00 -04:00
Claude 2ba34cd5fe 4-seasons: fix VFR pause/jump in daily MVT clips
Without explicit duration in the concat file, ffmpeg assigns timestamps
from EXIF metadata or defaults — producing a variable frame-rate raw
video with uneven frame spacing.  Applying setpts without fps= then
preserved that unevenness into the final clip, causing the observed
pause-then-jump-minutes/hours behaviour.

Fix 1: write `duration 0.04` (1/25 s) for every JPEG in the concat
list, making the raw video a true 25 fps CFR stream.  The duplicate
final-entry is appended as required by the ffmpeg concat demuxer so the
last content frame keeps its full display duration.

Fix 2: add `fps=25` to the setpts filter in step 2, resampling to
standard 25 fps CFR regardless of the speed factor, which guarantees
smooth, uniform playback in the final clip.

https://claude.ai/code/session_01U29A8NpgJ41tboiggZNmk8
2026-04-23 12:22:00 +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 8a7739502c fix: daily_sunrise_video.sh exits non-zero, blocking OnSuccess= upload
Conditional expressions like `[ "$count" -gt 0 ] && echo ...` return 1
when count is 0 (nothing to delete). Under set -euo pipefail with no
explicit exit 0, that false becomes the script's exit code. systemd sees
failure, OnSuccess= for sunrise2mm.py never fires, and the Mattermost
upload is silently skipped every day.

Fix: add || true to all end-of-script conditional-echo statements and to
the cam_audio cleanup line, then add an explicit exit 0 so the success
path always exits cleanly.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-23 12:00:57 +00:00
Claude 98dcf23687 4-seasons: replace size-rejection with 1MB fast-skip for grey filter
File size can't reliably reject bad frames (200KB can be good or bad).
Remove SEASONS_MIN_FRAME_BYTES.  Instead, the grey/green uniform-colour
filter (SEASONS_GREY_STDDEV_MIN) now skips the expensive ImageMagick
check for files above SEASONS_LARGE_FRAME_BYTES (default 1 MB) since
those are always good.  Only sub-1MB files get the content check, making
the filter practical on days with 40k+ images.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-23 02:34:26 +00:00
Outis e819177493 Add files via upload 2026-04-22 22:24:28 -04:00
Claude a9faa63cd9 4-seasons: remove per-frame ffprobe validation — too slow at scale
43k images × ffprobe process launch = 30-90 min before encoding starts.
Every corrupt file seen in practice has been 0-byte (caught instantly by
[ ! -s ]).  Non-zero corrupt files are rare; if ffmpeg hits one the
existing drift warning flags the short output.  Removing ffprobe restores
the fast path: one stat() call per image.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-23 01:52:38 +00: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 283c36979a Merge pull request #46 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
4-seasons: add optional date argument
2026-04-22 16:42:55 -04:00
Claude d00d4bf15e 4-seasons: add optional date argument
Allows processing any past date instead of always yesterday:
  ./4-seasons.sh east 2026-04-19

Useful for backfilling days with existing images.
Systemd (no date arg) continues to default to yesterday.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 20:41:45 +00:00
Outis 55681abc9f Merge pull request #45 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
4-seasons: restore original concat approach — no duration per frame
2026-04-22 14:38:17 -04:00
Claude d0399fb72d 4-seasons: restore original concat approach — no duration per frame
duration=INTERVAL in the concat file made a 0.1fps raw video, which
x264 couldn't speed up 4000x cleanly and produced 20s of the last
frame instead.  The original script used plain 'file path' entries
with no duration, letting ffmpeg default to 25fps internally.  The
speed_factor calculation against raw_duration compensates correctly
either way, but only the standard-fps raw video survives the extreme
setpts transform.  Also removed the coverage_pct check which was
based on images*INTERVAL and became meaningless without duration.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 18:29:58 +00:00
Outis 334e8b85e7 Merge pull request #44 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
ClDemoe/seasonal sunrise montage nn268
2026-04-22 13:00:45 -04:00
Claude 32bd64459e 4-seasons: exit cleanly when all frames fail validation
Accessing ${images[-1]} on an empty array under set -u causes a bash
error.  Guard with an explicit check so a fully-corrupt image directory
exits with a clear message instead of a cryptic crash.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 16:58:16 +00:00
Claude 8b79261b81 4-seasons: remove fps=25 from speed-adjust — keep all source frames
fps=25 caused ffmpeg to discard 15 of every 16 source frames, making
the final clip jump by ~2.5 minutes per frame.  The original script
had no fps filter, so all source frames were preserved.  Without it,
the setpts speed-adjust keeps every frame; the effective framerate in
the output rises proportionally (e.g. ~400fps for a full day at 10s
intervals into an 11s clip), which is fine for H.264 and all
downstream montage steps.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 16:32:47 +00:00
Outis c92626e9df Merge pull request #43 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
ClDemoe/seasonal sunrise montage nn268
2026-04-22 12:23:24 -04:00
Claude 9d34240ac0 sky-cam.conf: comment out grey filter — must be explicitly enabled
The SEASONS_GREY_STDDEV_MIN and SEASONS_GREY_DARK_FLOOR settings are
now commented out so the filter is fully inert by default and requires
a deliberate edit to activate.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 16:22:25 +00:00
Claude ec8eb7aebf 4-seasons: protect night frames from grey filter with brightness floor
A stddev-only filter would wrongly drop near-black night frames.
Now only skips a frame when BOTH stddev < GREY_MIN AND mean brightness
> GREY_DARK_FLOOR (default 30/255).  Night frames are dark so they
always pass; bad-signal grey frames are mid-bright so they are caught.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 16:17:22 +00:00
Outis 3ed9f76f2e Merge pull request #42 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
4-seasons: validate JPEGs with ffprobe, add optional grey-frame filter
2026-04-22 12:10:47 -04:00
Claude 4aeee6b3d5 4-seasons: validate JPEGs with ffprobe, add optional grey-frame filter
The previous size check caught empty files but not corrupt JPEGs with
a partial header (common first frame after a camera reconnect).
Replace with ffprobe codec detection — if ffprobe can't identify a
video stream in the file it's skipped with a clear "corrupt" message.

Also adds SEASONS_GREY_STDDEV_MIN (default 0 = off): when enabled,
frames with near-zero pixel standard deviation (uniform grey = bad
RTSP signal) are silently dropped before encoding.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 16:07:29 +00:00
Outis 029840cbe0 Merge pull request #41 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
4-seasons: skip empty/unreadable frames, warn on low day coverage
2026-04-22 11:54:41 -04:00
Claude 292824b48d 4-seasons: skip empty/unreadable frames, warn on low day coverage
Corrupt or 0-byte JPEGs (e.g. first frame after a camera reconnect)
caused ffmpeg concat to silently truncate the output, missing all
images after the bad file.  Now filters those out before building the
concat list and logs a warning + notification when raw video covers
less than 50% of the expected image count.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 15:51:59 +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
Outis 4e50bfd3b3 Merge pull request #40 from outis1one/clDemoe/seasonal-sunrise-montage-nn268
Fix Python config parser swallowing inline comments as part of values
2026-04-22 11:05:21 -04:00
Claude 45af48e46d Fix Python config parser swallowing inline comments as part of values
read_config / _read_conf now strips trailing inline shell comments
(whitespace + # + anything) before processing the value.  Without this,
a line like:

  SUNRISE_CAM=east                   # which camera faces east

produced SUNRISE_CAM = 'east                   # which camera faces east',
causing sunrise2mm.py to build a path with the comment embedded in it.

The regex \s+#.*$ requires at least one whitespace before # so passwords
or URLs containing # (e.g. %23 URL-encoded) are unaffected.

https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
2026-04-22 15:01:53 +00:00