# =============================================================================
# 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
#   # one sky-cam-seasons-<cam>.timer per camera, e.g.:
#   systemctl --user enable --now sky-cam-seasons-east.timer
#
# 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 <cam>     — daily at SCHEDULE_SEASONS_<cam> (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
#
#
#    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-<cam>.timer (SCHEDULE_SEASONS_<cam>)
#    → if renamed: update install.sh (write_service call ~line 85)
#                  then re-run install.sh
#    calls → season_info.py, montage-mvt.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 ──────────────────────────────────────────────────────────
# Auto-detected from where this file lives — override only if you move the
# scripts to a different location after install.
SCRIPT_DIR="${SCRIPT_DIR:-$(dirname "$(realpath "${BASH_SOURCE[0]}")")}"

# ── Storage ───────────────────────────────────────────────────────────────────
# BASE_DIR: root folder where camera images are stored.
#   Structure created automatically: BASE_DIR/<cam>/YYYY-MM-DD/HH-MM-SS.jpg
# Defaults to a 'data' subfolder next to the scripts; override to point at
# an external drive or network mount (recommended for production).
BASE_DIR="${BASE_DIR:-$SCRIPT_DIR/data}"
MOVIES_DIR="${MOVIES_DIR:-$BASE_DIR/movies}"  # override if videos live on a different drive
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=(east north south)         # add west here + uncomment its schedule below when ready
SUNRISE_CAM=east                   # which camera faces east (gets the sunrise video job)

# ── Schedules ─────────────────────────────────────────────────────────────────
# All times are HH:MM:SS (24-hour local time).
# install.sh reads these and generates one systemd timer per camera per job.
#
# SCHEDULE_SUNRISE
#   When to START the sunrise video job.  The script wakes up, calculates
#   today's sunrise time, then WAITS internally until the capture window is
#   fully finished before touching any images.  Set this early enough to
#   cover your earliest possible sunrise minus SUNRISE_PRE_MIN — 03:00 works
#   year-round for most locations.  The video is ready a few minutes after the
#   capture window closes, not at this start time.
#
# SCHEDULE_SEASONS_<cam>  (one per camera in CAMERAS)
#   When to run the Four Seasons daily clip job.  Processes YESTERDAY'S images
#   (not today's) — always runs after midnight.  On the last day of a season
#   movement this automatically triggers the movement montage build.
#   Space multiple cameras at least 30 min apart to avoid disk contention.
#
SCHEDULE_SUNRISE=03:00:00

# Four Seasons daily clip — one per camera, staggered 30 min apart.
# Processes yesterday's images; on the last day of a movement auto-triggers
# montage-mvt.sh.  Space cameras at least 30 min apart to avoid disk contention.
SCHEDULE_SEASONS_east=01:00:00
SCHEDULE_SEASONS_north=01:30:00
SCHEDULE_SEASONS_south=02:00:00
# To add west: uncomment below, add west to CAMERAS above, add CAM_RTSP_west to .env
#SCHEDULE_SEASONS_west=02:30:00

# ── Sunrise video tuning ──────────────────────────────────────────────────────
# Capture window around sunrise:
#   Images from (sunrise - SUNRISE_PRE_MIN) to (sunrise + SUNRISE_POST_MIN)
#   are included in the clip.  Larger windows give more context; they are all
#   speed-adjusted to fit SUNRISE_TARGET_SECS regardless of window size.
SUNRISE_PRE_MIN=70         # minutes before sunrise to start capturing
SUNRISE_POST_MIN=10        # minutes after sunrise to stop capturing
# Target length of the final sunrise video (seconds).
SUNRISE_TARGET_SECS=10
# Burn the local sunrise time vertically on the right side of the video.
# Set false to skip the overlay entirely (cleaner look, faster encoding).
SUNRISE_OVERLAY_ENABLED=true
# Opacity of the sunrise-time text (0.0 = invisible, 1.0 = fully opaque).
SUNRISE_OVERLAY_OPACITY=0.45
# Delete daily sunrise videos older than this many days (rolling window).
# Set 0 to keep forever.
SUNRISE_RETENTION_DAYS=10

# ── Video encoding quality ────────────────────────────────────────────────────
# FFmpeg CRF: lower = higher quality / larger files.  Typical range 18–30.
#   18 ≈ visually lossless     23 = ffmpeg default     28 = smaller/lower
# H.265 (libx265) CRF is not directly comparable — H.265 CRF 22 ≈ H.264 CRF 26
# in visual quality but ~40-50% smaller file.  Final montages use H.265;
# intermediates (deleted after use) stay H.264.
#
# ENCODE_PRESET: slow = better compression, same CRF quality, ~2× encode time.
# Use 'medium' on slower machines, 'slow' or 'slower' on fast ones.
# All encodes run at night so 'slow' is the right default.
#
CRF_SUNRISE=28           # daily_sunrise_video.sh   — daily Mattermost upload (H.264)
CRF_SEASONS_RAW=28       # 4-seasons.sh             — raw concat before speed-adjust (H.264)
CRF_SEASONS_FINAL=26     # 4-seasons.sh             — final daily clip (goes into montage) (H.264)
CRF_MONTAGE=28           # montage-mvt.sh           — intermediate concat + sped steps (H.264)
CRF_MONTAGE_FINAL=22     # montage-mvt.sh           — final archive montage (H.265)
ENCODE_PRESET=slow       # ffmpeg preset for all encodes (slow/medium/fast)
AUDIO_BITRATE=192k       # montage-mvt.sh           — music track on movement montages

# ── Montage attribution overlay ───────────────────────────────────────────────
# A translucent bar across the top of each movement montage, naming the
# music source ("The Four Seasons — Antonio Vivaldi ...").
# Appears for MONTAGE_ATTR_DUR seconds from the start, with ATTR_FADE-second
# fade in and fade out.  FADE_DUR controls the video/audio fade in/out at
# the very start and very end of the montage.
#
MONTAGE_FADE_DUR=2.0   # video + audio fade in/out (seconds)
MONTAGE_ATTR_DUR=6     # attribution overlay total duration (seconds)
MONTAGE_ATTR_FADE=1    # attribution fade-in and fade-out length (seconds)

# ── Direct RTSP capture (replaces MotionEye / any NVR) ────────────────────────
# capture.sh pulls frames directly from each camera's RTSP stream.
# No NVR software required — just ffmpeg and the camera's stream URL.
#
# Per-camera RTSP URL: CAM_RTSP_<cam>=rtsp://user:pass@host:port/path
# Find the URL in your camera's web UI (usually under Network → Video → RTSP)
# or check your camera's manual.
#
# CAM_RTSP_<cam> goes in .env (see bottom of this file), not here.

# Seconds between captured frames (applies to all cameras).
# Lower = smoother timelapse + larger storage footprint:
#   10 s →  8,640 frames/day ~2.5 GB/day     (default, good balance)
#    5 s → 17,280 frames/day ~5 GB/day        (smoother motion)
#    2 s → 43,200 frames/day ~12 GB/day       (very smooth, high storage)
# CAPTURE_STALE_SECS should always be at least 2× CAPTURE_INTERVAL.
CAPTURE_INTERVAL=10

# Seconds without a new frame before the watchdog sends a stall notification.
# A recovery notification fires automatically when capture resumes.
CAPTURE_STALE_SECS=30

# ── Sunrise audio capture ──────────────────────────────────────────────────────
# Records the camera's RTSP audio stream during the sunrise window so that
# daily_sunrise_video.sh can mix in natural ambient sound (birds, rain, wind)
# at real speed, while the video plays as the sped-up timelapse.
# The audio file is deleted automatically after it is mixed into the video.
#
AUDIO_ENABLED=false           # set true if your camera has a working mic
CAPTURE_AUDIO_BITRATE=96k     # bitrate for the sunrise audio recording
# Audio is recorded for exactly SUNRISE_TARGET_SECS, centred on actual sunrise:
# floor(TARGET/2) seconds before, ceil(TARGET/2) after (odd second → post-sunrise).

# ── Mattermost — daily sunrise upload ─────────────────────────────────────────
# mattermost_url, access_token, channel_id go in .env (see bottom of this file).

# ── 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

# ── Credentials (.env override) ───────────────────────────────────────────────
# Sensitive values (RTSP URLs with passwords, API tokens) can be kept out of
# this file — and out of git — by placing them in a .env file in the same
# directory.  install.sh generates .env.example showing exactly which variables
# to define for your camera list.
#
# To use:
#   cp .env.example .env
#   $EDITOR .env          ← fill in real values
#   (never commit .env)
#
_conf_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
[ -f "$_conf_dir/.env" ] && source "$_conf_dir/.env"
unset _conf_dir
