# ============================================================================= # sky-cam.conf — master configuration for all sky-cam scripts # ============================================================================= # # This is the ONLY file you need to edit. After editing, run: # # ./install.sh # installs systemd timers (no root needed) # ./install.sh --system # system-wide install (requires sudo) # # Re-run install.sh any time this file changes. # # ----------------------------------------------------------------------------- # MANUAL SYSTEMD SETUP (if you prefer not to use install.sh) # ----------------------------------------------------------------------------- # After editing this file, generate the unit files: # # mkdir -p ~/.config/systemd/user # cp systemd/*.service systemd/*.timer ~/.config/systemd/user/ # # Then edit ExecStart= in each .service file to match your SCRIPT_DIR, then: # # systemctl --user daemon-reload # systemctl --user enable --now sky-cam-sunrise.timer # systemctl --user enable --now sky-cam-seasons-sunrise.timer # systemctl --user enable --now sky-cam-fullday-sunrise.timer # # one sky-cam-seasons-.timer and sky-cam-fullday-.timer per camera # # Check status: # systemctl --user list-timers 'sky-cam-*' # journalctl --user -u sky-cam-seasons-sunrise.service -f # # System-wide (replace --user with no flag, prepend sudo): # sudo cp systemd/*.service systemd/*.timer /etc/systemd/system/ # sudo systemctl daemon-reload && sudo systemctl enable --now sky-cam-*.timer # # ----------------------------------------------------------------------------- # SCRIPT MAP — what each file does and when it runs # ----------------------------------------------------------------------------- # # You run / schedule: # daily_sunrise_video.sh — daily at SCHEDULE_SUNRISE (via systemd, SUNRISE_CAM only) # grabs images around sunrise, makes a short video, # uploads it to Mattermost # # 4-seasons.sh — daily at SCHEDULE_SEASONS_ (via systemd, per camera) # makes yesterday's daily clip sized to its share # of the matching Vivaldi movement's music duration; # on the last day of a movement, auto-triggers # montage-mvt.sh # # fullday-video.sh — daily at SCHEDULE_FULLDAY_ (via systemd, per camera) # full-day timelapse at fixed fps; deletes videos # older than RETENTION_DAYS automatically # # install.sh — run once at setup, and again if this file changes # generates and installs systemd units from conf # # stitch-cameras.py — run manually when needed # stitches north + sunrise into a panorama # usage: python3 stitch-cameras.py north.jpg sunrise.jpg prefix [focal] # # Auto-triggered (do not run directly): # montage-mvt.sh — called by 4-seasons.sh on last day of each movement # concatenates all daily clips for the movement, # speed-adjusts to match music, overlays attribution, # sends completion notification; on last Autumn # movement also triggers year-end-join.sh # # year-end-join.sh — called by montage-mvt.sh at end of Autumn Mvt 3 # concatenates all 12 movement montages into one # Four Seasons year video, sends notification # # Helpers (called by the scripts above, not run directly): # notify.sh — sends notifications via ntfy / email / Mattermost # season_info.py — outputs astronomical season/movement/year for a date # sunrise.py — outputs today's sunrise time (used by daily_sunrise_video) # sunrise2mm.py — uploads the sunrise video to Mattermost # sunrise_overlay.py — burns a timestamp overlay onto the sunrise video # # ----------------------------------------------------------------------------- # FILE DEPENDENCIES — who calls whom, and what to update if you rename a file # ----------------------------------------------------------------------------- # # sky-cam.conf (this file) # ← sourced by every .sh script; read by sunrise.py, sunrise2mm.py # → if renamed: update the 'source' line at the top of ALL scripts # (don't rename it — just edit it in place) # # install.sh # ← run manually; reads this conf # → if renamed: update the note at the top of this conf file only # generates → systemd unit files (sky-cam-*.service / .timer) # and sky-cam-notify-failure@.service # # daily_sunrise_video.sh # ← called by systemd sky-cam-sunrise.timer (SCHEDULE_SUNRISE) # → if renamed: update install.sh (write_service call ~line 70) # then re-run install.sh to regenerate the unit # calls → sunrise.py, sunrise_overlay.py, sunrise2mm.py # # 4-seasons.sh # ← called by systemd sky-cam-seasons-.timer (SCHEDULE_SEASONS_) # → if renamed: update install.sh (write_service call ~line 85) # then re-run install.sh # calls → season_info.py, montage-mvt.sh # # fullday-video.sh # ← called by systemd sky-cam-fullday-.timer (SCHEDULE_FULLDAY_) # → if renamed: update install.sh (write_service call ~line 93) # then re-run install.sh # # montage-mvt.sh # ← called by 4-seasons.sh on the last day of each movement # → if renamed: update 4-seasons.sh (the exec line near the bottom) # calls → season_info.py, notify.sh, year-end-join.sh # # year-end-join.sh # ← called by montage-mvt.sh at end of Autumn Mvt 3 # → if renamed: update montage-mvt.sh (the exec line at the bottom) # calls → notify.sh # # notify.sh # ← called by montage-mvt.sh, year-end-join.sh # also referenced in install.sh for the OnFailure= failure template # → if renamed: update montage-mvt.sh, year-end-join.sh, install.sh # # season_info.py # ← called by 4-seasons.sh and montage-mvt.sh # → if renamed: update 4-seasons.sh and montage-mvt.sh (the eval lines) # # sunrise.py # ← called by daily_sunrise_video.sh # → if renamed: update daily_sunrise_video.sh # # sunrise_overlay.py # ← called by daily_sunrise_video.sh # → if renamed: update daily_sunrise_video.sh # # sunrise2mm.py # ← called by daily_sunrise_video.sh # → if renamed: update daily_sunrise_video.sh # # stitch-cameras.py # ← run manually only; no script calls it # → safe to rename with no other changes needed # # ============================================================================= # ── Install location ────────────────────────────────────────────────────────── # Full path to the directory containing this file and all the scripts. SCRIPT_DIR=/home/motion/drives/local-2tb/sunrise-scripts # ── Storage ─────────────────────────────────────────────────────────────────── BASE_DIR=/home/motion/drives/local-2tb MUSIC_DIR=/home/motion/drives/local-2tb/music/4 Seasons # ── Location & timezone ─────────────────────────────────────────────────────── # Used by sunrise.py to calculate sunrise time each day. # # To find your coordinates: # Google Maps — right-click your location → the first item shown is "lat, lon" # Or: maps.google.com, drop a pin, coordinates appear in the URL and sidebar # # TIMEZONE must be a valid IANA name. Look yours up at: # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones # (use the value in the "TZ identifier" column, e.g. America/Chicago) # LATITUDE=25.0000 LONGITUDE=-38.0000 TIMEZONE=America/New_York # ── Cameras ─────────────────────────────────────────────────────────────────── # List every camera name here (space-separated inside the parentheses). # Each name becomes a subfolder under BASE_DIR (images) and BASE_DIR/movies. # To add a camera: add its name here, add its schedules below, re-run install.sh. # CAMERAS=(sunrise) # e.g. CAMERAS=(sunrise north west) SUNRISE_CAM=sunrise # which camera faces east (gets the sunrise video job) # ── Schedules ───────────────────────────────────────────────────────────────── # SCHEDULE_SUNRISE when to run daily_sunrise_video.sh (SUNRISE_CAM only) # SCHEDULE_SEASONS_ when to run 4-seasons.sh for each camera # SCHEDULE_FULLDAY_ when to run fullday-video.sh for each camera # # Times are HH:MM:SS (24-hour). Space cameras at least 30 min apart. # install.sh reads these and generates one systemd timer per camera per job. # SCHEDULE_SUNRISE=09:00:00 SCHEDULE_SEASONS_sunrise=01:00:00 SCHEDULE_FULLDAY_sunrise=02:00:00 # Uncomment and fill in for each camera you add to CAMERAS above: #SCHEDULE_SEASONS_north=01:30:00 #SCHEDULE_FULLDAY_north=02:30:00 # #SCHEDULE_SEASONS_west=02:00:00 #SCHEDULE_FULLDAY_west=03:00:00 # ── Sunrise video tuning ────────────────────────────────────────────────────── # How many minutes before/after sunrise to include in the daily clip. SUNRISE_PRE_MIN=70 SUNRISE_POST_MIN=10 # Target duration (seconds) for the speed-adjusted sunrise video. SUNRISE_TARGET_SECS=10 # ── Full-day timelapse tuning ───────────────────────────────────────────────── FULLDAY_FPS=5 # frame rate of the timelapse video RETENTION_DAYS=10 # delete full-day videos older than this many days # ── Mattermost — daily sunrise upload ───────────────────────────────────────── mattermost_url=https://your-mattermost-server.example.com access_token=your-access-token-here channel_id=your-daily-upload-channel-id-here # ── Notifications — montage / year-end complete + any job failure ───────────── # Notifications fire when a movement montage or the year video finishes, # and via systemd OnFailure= if any daily job fails. # Uncomment and configure one or more methods to enable. # ntfy — push notifications, zero signup for self-hosted or free cloud tier: # Self-hosted: https://docs.ntfy.sh/install/ # Cloud: pick any topic name at ntfy.sh (no account needed) #NTFY_ENABLED=true #NTFY_URL=https://ntfy.sh/your-topic-here # Email — requires the 'mail' command (package: mailutils or s-nail). # Configure outbound SMTP via /etc/ssmtp/ssmtp.conf or msmtp. #EMAIL_ENABLED=true #EMAIL_TO=you@example.com #EMAIL_FROM=skycam@localhost # Mattermost text post — reuses mattermost_url and access_token above. # Can be the same daily channel or a separate admin/private channel. #MM_NOTIFY_ENABLED=true #MM_NOTIFY_CHANNEL_ID=your-notify-channel-id-here