#!/bin/bash # daily_sunrise_video.sh — collect today's sunrise images, speed-adjust to # SUNRISE_TARGET_SECS, burn the local sunrise time vertically on the right # side, and write the final video. Upload is handled by a separate systemd # service (sky-cam-sunrise-upload) triggered via OnSuccess= so the two jobs # have independent log entries and failure states. set -euo pipefail SCRIPT_DIR="$(dirname "$(realpath "$0")")" source "$SCRIPT_DIR/sky-cam.conf" export TZ="$TIMEZONE" # ── Date / paths ────────────────────────────────────────────────────────────── 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" mkdir -p "$output_dir" # ── Sunrise time ────────────────────────────────────────────────────────────── sunrise_time=$(python3 "$SCRIPT_DIR/sunrise.py") if [[ -z "$sunrise_time" ]]; then echo "Error: Failed to retrieve sunrise time." exit 1 fi echo "Sunrise (UTC): $sunrise_time" sunrise_time_local=$(TZ="$TIMEZONE" date -d "$sunrise_time" +"%H-%M-%S") echo "Sunrise (local): $sunrise_time_local" # ── Capture window ──────────────────────────────────────────────────────────── time_to_seconds() { IFS='-' read -r h m s <<< "$1"; echo $((10#$h * 3600 + 10#$m * 60 + 10#$s)); } sunrise_sec=$(time_to_seconds "$sunrise_time_local") start_sec=$((sunrise_sec - SUNRISE_PRE_MIN * 60)) end_sec=$((sunrise_sec + SUNRISE_POST_MIN * 60)) echo "Window: $((start_sec/3600)):$(printf '%02d' $(((start_sec%3600)/60))) → $((end_sec/3600)):$(printf '%02d' $(((end_sec%3600)/60)))" # ── Collect images in window ────────────────────────────────────────────────── if [ ! -d "$image_dir" ]; then echo "Error: image directory not found: $image_dir" exit 1 fi temp_list=$(mktemp --suffix=.txt) trap 'rm -f "$temp_list" "$raw_video" 2>/dev/null || true' EXIT find "$image_dir" -type f -name "*.jpg" | sort | while read -r img; do img_sec=$(time_to_seconds "$(basename "$img" .jpg)") if [[ $img_sec -ge $start_sec && $img_sec -le $end_sec ]]; then echo "file '$img'" fi done > "$temp_list" num_images=$(wc -l < "$temp_list") if [[ $num_images -lt 1 ]]; then echo "No images found in sunrise window." exit 1 fi echo "Images in window: $num_images" # ── Font detection (same fallback chain as montage-mvt.sh) ─────────────────── FONT="" if command -v fc-match &>/dev/null; then FONT=$(fc-match "DejaVu Sans:style=Regular" --format="%{file}" 2>/dev/null || true) fi if [ -z "$FONT" ]; then for f in \ /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf \ /usr/share/fonts/dejavu/DejaVuSans.ttf \ /usr/share/fonts/TTF/DejaVuSans.ttf \ /usr/share/fonts/truetype/freefont/FreeSans.ttf; do [ -f "$f" ] && { FONT="$f"; break; } done fi # ── Step 1: Raw video from images ───────────────────────────────────────────── raw_video=$(mktemp --suffix=.mp4) echo "Step 1/2: encoding raw video..." ffmpeg -loglevel warning \ -f concat -safe 0 -i "$temp_list" \ -c:v libx264 -pix_fmt yuv420p -crf "$CRF_SUNRISE" -vsync 2 -an \ -y "$raw_video" raw_dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$raw_video") speed_factor=$(echo "scale=3; $raw_dur / $SUNRISE_TARGET_SECS" | bc) echo "Raw: ${raw_dur}s speed factor: ${speed_factor}x" # ── Step 2: Speed-adjust + sunrise time overlay ─────────────────────────────── # Time displayed as stacked characters down the right side (e.g. 0/7/:/2/3), # semi-transparent with a soft drop shadow so it reads on any background. SR_TIME=$(echo "$sunrise_time_local" | cut -d'-' -f1,2 | tr '-' ':') # Build "H\nH\n:\nM\nM" for vertical stacking in drawtext SR_VERT=$(echo "$SR_TIME" | awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++){printf "%s",$i; if(i