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
This commit is contained in:
Claude
2026-04-19 23:37:10 +00:00
parent a1b9ffa8ee
commit a1cf1304e4
8 changed files with 28 additions and 8 deletions
+5 -1
View File
@@ -26,7 +26,11 @@ yesterday=$(date --date="yesterday" +%Y-%m-%d)
echo "Processing: $yesterday"
# ── Season / movement info from astronomical calculation ──────────────────────
eval "$(python3 "$SCRIPT_DIR/season_info.py" "$yesterday")"
_season_info="$(python3 "$SCRIPT_DIR/season_info.py" "$yesterday")" || {
echo "Error: season_info.py failed — check Python dependencies (suntime pytz)"
exit 1
}
eval "$_season_info"
# Provides: SEASON MVT_NUM DAY_OF_MVT DAYS_IN_MVT MVT_START MVT_END
# IS_LAST_DAY ASTRO_YEAR
echo "Season=$SEASON Mvt=$MVT_NUM Year=$ASTRO_YEAR Day=$DAY_OF_MVT/$DAYS_IN_MVT LastDay=$IS_LAST_DAY"
+2 -1
View File
@@ -13,7 +13,8 @@ Automated sky / timelapse camera scripts that produce:
| Dependency | Notes |
|---|---|
| `ffmpeg` + `ffprobe` | Encoding, capture, audio recording, duration probing |
| `python3` | `ephem` package for sunrise calculation, `requests` for Mattermost upload |
| `python3` | `suntime pytz` for sunrise calculation, `requests` for Mattermost upload`pip3 install suntime pytz requests` |
| `fonts-dejavu` | DejaVu fonts for text overlays — `sudo apt install fonts-dejavu` |
| `bc` | Shell arithmetic (floating-point speed factors) |
| `fontconfig` (`fc-match`) | Font detection for overlays — optional, falls back to hardcoded paths |
| IP camera with RTSP stream | `capture.sh` pulls frames directly — no NVR software needed |
+6 -2
View File
@@ -20,7 +20,9 @@ mv "sky-cam-$BRANCH" "$TARGET"
echo ""
echo "Done. Next steps:"
echo " 1. pip3 install suntime pytz requests"
echo " 1. Install system packages (if not already present):"
echo " sudo apt install ffmpeg bc fonts-dejavu"
echo " pip3 install suntime pytz requests"
echo ""
echo " 2. Edit $TARGET/sky-cam.conf"
echo " — SCRIPT_DIR full path to the directory you'll run scripts from"
@@ -29,6 +31,8 @@ echo " — MUSIC_DIR path to your Vivaldi Four Seasons audio files"
echo " — CAMERAS list of camera names, e.g. (sunrise)"
echo " — SUNRISE_CAM which camera faces east (gets the sunrise video job)"
echo " — LATITUDE / LONGITUDE / TIMEZONE your location"
echo " — Mattermost credentials (mattermost_url, access_token, channel_id)"
echo ""
echo " 3. cd $TARGET && ./install.sh"
echo " This generates .env.example — copy it to .env and add credentials:"
echo " cp $TARGET/.env.example $TARGET/.env"
echo " \$EDITOR $TARGET/.env"
+1 -1
View File
@@ -17,7 +17,7 @@ SCRIPT_DIR="$(dirname "$(realpath "$0")")"
source "$SCRIPT_DIR/sky-cam.conf"
export TZ="$TIMEZONE"
CAM="${1:-$CAM_NAME}"
CAM="${1:-$SUNRISE_CAM}"
rtsp_var="CAM_RTSP_${CAM}"
RTSP_URL="${!rtsp_var:-}"
+1 -1
View File
@@ -24,7 +24,7 @@ current_date=$(date +%Y-%m-%d)
output_date=$(date +%Y-%m)
image_dir="$BASE_DIR/$CAM_NAME/$current_date"
output_dir="$BASE_DIR/movies/$CAM_NAME/$output_date/sunrise-only"
output_dir="$MOVIES_DIR/$CAM_NAME/$output_date/sunrise-only"
mkdir -p "$output_dir"
# ── Sunrise time ──────────────────────────────────────────────────────────────
+5 -1
View File
@@ -39,7 +39,11 @@ ATTR_FADE="$MONTAGE_ATTR_FADE"
# ── Season / movement info ────────────────────────────────────────────────────
DATE_ARG="${1:-}"
eval "$(python3 "$SCRIPT_DIR/season_info.py" ${DATE_ARG:+"$DATE_ARG"})"
_season_info="$(python3 "$SCRIPT_DIR/season_info.py" ${DATE_ARG:+"$DATE_ARG"})" || {
echo "Error: season_info.py failed — check Python dependencies (suntime pytz)"
exit 1
}
eval "$_season_info"
# Provides: SEASON MVT_NUM DAY_OF_MVT DAYS_IN_MVT MVT_START MVT_END
# IS_LAST_DAY ASTRO_YEAR
echo "Season=$SEASON Mvt=$MVT_NUM Year=$ASTRO_YEAR (ref: ${DATE_ARG:-today})"
+4
View File
@@ -18,6 +18,10 @@ def _read_conf(path):
conf = _read_conf(_here / 'sky-cam.conf')
for _key in ('LATITUDE', 'LONGITUDE', 'TIMEZONE'):
if _key not in conf:
raise SystemExit(f"sunrise.py: {_key} not set in sky-cam.conf")
latitude = float(conf['LATITUDE'])
longitude = float(conf['LONGITUDE'])
tz = pytz.timezone(conf['TIMEZONE'])
+4 -1
View File
@@ -28,8 +28,11 @@ def read_config(config_file_path):
exit(1)
return config
# Read configuration from the file
# Read configuration — sky-cam.conf first, then .env overrides (credentials)
config = read_config(config_file_path)
_env_path = str(_here / '.env')
if os.path.isfile(_env_path):
config.update(read_config(_env_path))
# Get the values from the configuration file
mattermost_url = config.get('mattermost_url')