season_info.py - Add ASTRO_YEAR: year of the Winter solstice that started the current cycle (Spring/Summer/Autumn 2026 → 2025; Winter Dec-2026 → 2026) 4-seasons.sh - Daily clip output path now includes ASTRO_YEAR: movies/$name/$ASTRO_YEAR/$SEASON/Mvt$N/ montage-mvt.sh (full rewrite) - Attribution is now a drawtext overlay (top 6 s of the video, fade in/out) instead of an appended black card — no frame-size matching needed, and year-end join requires no special handling - Output path mirrors the new year-based folder structure - Sends notification via notify.sh when done - Automatically triggers year-end-join.sh after Autumn Mvt 3 year-end-join.sh (new) - Concatenates all 12 movement montages for a given ASTRO_YEAR - Output: movies/$name/$ASTRO_YEAR/$name-$ASTRO_YEAR.mp4 - Sends notification when done notify.sh + notify_config.txt (new) - Generic best-effort notification helper: ntfy, email, Mattermost text post - All methods disabled by default; user fills in notify_config.txt sky-cam.crontab + systemd/ (new) - Crontab file: sunrise at 09:00, 4-seasons at 01:00, fullday at 02:00 - systemd .service + .timer units for all three daily jobs - montage/year-end triggered internally, not by cron https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
78 lines
2.9 KiB
Bash
Executable File
78 lines
2.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# year-end-join.sh — concatenate all 12 movement montages for one astronomical
|
|
# year into a single "Four Seasons" video.
|
|
#
|
|
# Called automatically by montage-mvt.sh after the last Autumn movement finishes.
|
|
# Can also be run manually: ./year-end-join.sh 2025
|
|
#
|
|
# The 12 individual movement videos already carry their own attribution overlay
|
|
# (first 6 seconds of each), so no extra card is appended here.
|
|
#
|
|
# Output: $base_dir/movies/$script_name/$ASTRO_YEAR/$script_name-$ASTRO_YEAR.mp4
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
|
|
|
|
ASTRO_YEAR="${1:-}"
|
|
if [ -z "$ASTRO_YEAR" ]; then
|
|
echo "Usage: $0 <ASTRO_YEAR> (e.g. $0 2025)"
|
|
exit 1
|
|
fi
|
|
|
|
base_dir="/home/motion/drives/local-2tb"
|
|
script_name=$(basename "$SCRIPT_DIR" | cut -d'-' -f1)
|
|
year_dir="$base_dir/movies/$script_name/$ASTRO_YEAR"
|
|
|
|
echo "Assembling Four Seasons $ASTRO_YEAR from $year_dir ..."
|
|
|
|
# ── Collect the 12 montage files in season/movement order ────────────────────
|
|
concat_list=$(mktemp --suffix=.txt)
|
|
trap 'rm -f "$concat_list"' EXIT
|
|
|
|
missing=0
|
|
for season in Winter Spring Summer Autumn; do
|
|
for mvt in 1 2 3; do
|
|
mvt_dir="$year_dir/$season/Mvt$mvt/montage"
|
|
# Pick the newest (or only) montage file for this movement
|
|
f=$(find "$mvt_dir" -maxdepth 1 -name "*-Montage.mp4" 2>/dev/null | sort | tail -1)
|
|
if [ -z "$f" ]; then
|
|
echo "WARNING: missing montage for $season Mvt$mvt ($mvt_dir)"
|
|
missing=$((missing + 1))
|
|
else
|
|
echo " $season Mvt$mvt → $(basename "$f")"
|
|
printf "file '%s'\n" "$f" >> "$concat_list"
|
|
fi
|
|
done
|
|
done
|
|
|
|
found=$(wc -l < "$concat_list")
|
|
echo "$found of 12 movements found ($missing missing)"
|
|
|
|
if [ "$found" -eq 0 ]; then
|
|
echo "ERROR: no montage files found — aborting."
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$missing" -gt 0 ]; then
|
|
echo "WARNING: joining with $missing movement(s) absent."
|
|
fi
|
|
|
|
# ── Join ──────────────────────────────────────────────────────────────────────
|
|
output_file="$year_dir/${script_name}-${ASTRO_YEAR}.mp4"
|
|
echo "Output: $output_file"
|
|
|
|
ffmpeg -loglevel warning \
|
|
-f concat -safe 0 -i "$concat_list" \
|
|
-c copy -y "$output_file"
|
|
|
|
total_dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$output_file")
|
|
total_min=$(echo "scale=1; $total_dur / 60" | bc)
|
|
echo "Done: $output_file (${total_min} min)"
|
|
|
|
# ── Notify ────────────────────────────────────────────────────────────────────
|
|
"$SCRIPT_DIR/notify.sh" \
|
|
"Four Seasons $ASTRO_YEAR complete" \
|
|
"${script_name}-${ASTRO_YEAR}.mp4 — ${total_min} minutes ($found movements)" \
|
|
|| true
|