From c2d4d973619fffc290babe559b9970fc042f10b4 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 11:50:02 +0000 Subject: [PATCH 1/2] Fix audio: live RTSP fallback + mix retry + journal in ntfy; overlay at 15% MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - daily_sunrise_video.sh: add live RTSP capture as final fallback in production audio selection (fires when today, yesterday, and library all miss) - On audio mix failure, retry once with a fresh live RTSP capture before giving up — handles corrupt/incompatible pre-recorded files - When mix still fails after retry, append last 30 lines of sky-cam-audio-capture.service journal to the ntfy notification body - Move sunrise-time text overlay from 5% to 15% above the bottom edge https://claude.ai/code/session_01DANuzLCLhhQ7Li12RTcswY --- daily_sunrise_video.sh | 79 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 10 deletions(-) diff --git a/daily_sunrise_video.sh b/daily_sunrise_video.sh index 167b0aa..febe5d7 100755 --- a/daily_sunrise_video.sh +++ b/daily_sunrise_video.sh @@ -253,12 +253,12 @@ $TEST_MODE && echo "Speed-adjusted: ${sped_dur}s" # Top-left: x=18 y=18 # Top-right: x=w-tw-18 y=18 # Bottom-left: x=18 y=h-th-18-h*0.05 -# Bottom-right: x=w-tw-18 y=h-th-18-h*0.05 (current) +# Bottom-right: x=w-tw-18 y=h-th-18-h*0.15 (current) # Centered: x=(w-tw)/2 y=(h-th)/2 # Centered top: x=(w-tw)/2 y=24 # To nudge the current spot, change the "18" margins or the -# "h*0.05" lift (5% above the bottom edge — raise to 0.08 to -# clear a status bar, lower to 0.0 to sit flush at the bottom). +# "h*0.15" lift (15% above the bottom edge — lower to 0.05 to +# sit closer to the bottom, raise to 0.20 for more clearance). # # shadowcolor / shadowx / shadowy # A 1-pixel black drop-shadow @55% opacity for legibility against @@ -299,9 +299,9 @@ if [ "${SUNRISE_OVERLAY_ENABLED:-true}" = "true" ]; then DT="${DT}:fontsize=h/22:line_spacing=4" # Position — bottom-right corner. See the corner recipes in the comment - # block above. The "18" values are pixel margins; "h*0.05" lifts the box - # 5% of the height off the bottom so it doesn't kiss the frame edge. - DT="${DT}:x=w-tw-18:y=h-th-18-h*0.05" + # block above. The "18" values are pixel margins; "h*0.15" lifts the box + # 15% of the height off the bottom to clear the lower edge. + DT="${DT}:x=w-tw-18:y=h-th-18-h*0.15" # Drop-shadow for legibility. Set shadowx=shadowy=0 to disable, or swap # for :borderw=2:bordercolor=black@0.7 for a thicker outline. @@ -362,6 +362,28 @@ else fi fi fi + # Live RTSP as last resort — captures current ambient sound when no + # pre-recorded file is available from today, yesterday, or the library. + if [ -z "$audio_src" ]; then + _rtsp_var="CAM_RTSP_${CAM_NAME}" + _rtsp_url="${!_rtsp_var:-}" + if [ -n "$_rtsp_url" ]; then + temp_live_audio=$(mktemp --suffix=.m4a) + echo "Audio: no saved file found — capturing ${SUNRISE_TARGET_SECS}s live from RTSP..." + if ffmpeg -loglevel warning \ + -rtsp_transport tcp \ + -i "$_rtsp_url" \ + -t "$SUNRISE_TARGET_SECS" \ + -vn -c:a aac -b:a "${CAPTURE_AUDIO_BITRATE:-96k}" \ + -y "$temp_live_audio"; then + audio_src="$temp_live_audio" + echo "Audio: live RTSP captured OK" + else + rm -f "$temp_live_audio"; temp_live_audio="" + echo "Audio: live RTSP capture failed — continuing silent" + fi + fi + fi fi fi @@ -403,11 +425,48 @@ if [ -n "$audio_src" ]; then echo "Audio: mixed OK" else rm -f "$temp_audio"; temp_audio="" - echo "Audio mix failed — step 3b will be overlay-only" + # Retry once with a fresh live RTSP capture before giving up on audio + _mix_ok=false if ! $TEST_MODE; then - "$SCRIPT_DIR/notify.sh" "WARNING: sunrise audio mix failed $current_date" \ - "Audio could not be mixed — continuing with overlay only" || true - [ "$audio_src" = "${cam_audio:-}" ] && rm -f "${cam_audio:-}" + _rtsp_var="CAM_RTSP_${CAM_NAME}" + _rtsp_url="${!_rtsp_var:-}" + if [ -n "$_rtsp_url" ]; then + _live_retry=$(mktemp --suffix=.m4a) + echo "Audio mix failed — retrying with live RTSP capture..." + if ffmpeg -loglevel warning \ + -rtsp_transport tcp -i "$_rtsp_url" \ + -t "$SUNRISE_TARGET_SECS" -vn \ + -c:a aac -b:a "${CAPTURE_AUDIO_BITRATE:-96k}" \ + -y "$_live_retry"; then + temp_audio=$(mktemp --suffix=.mp4) + if ffmpeg -loglevel warning \ + -i "$sped_video" \ + -ss "$audio_offset" -t "$SUNRISE_TARGET_SECS" -i "$_live_retry" \ + -filter_complex "[1:a]afade=t=in:st=0:d=${fade_dur},afade=t=out:st=${fade_out}:d=${fade_dur}[aout]" \ + -map "0:v" -map "[aout]" \ + -c:v copy -c:a aac -b:a 128k \ + -y "$temp_audio"; then + work_video="$temp_audio" + has_audio=true + echo "Audio: live RTSP retry mix OK" + _mix_ok=true + else + rm -f "$temp_audio"; temp_audio="" + fi + fi + rm -f "$_live_retry" + fi + fi + if ! $_mix_ok; then + echo "Audio mix failed — step 3b will be overlay-only" + if ! $TEST_MODE; then + _jlog=$(journalctl --user -u sky-cam-audio-capture.service -n 30 --no-pager 2>/dev/null \ + || journalctl -u sky-cam-audio-capture.service -n 30 --no-pager 2>/dev/null \ + || echo "(journal unavailable)") + "$SCRIPT_DIR/notify.sh" "WARNING: sunrise audio mix failed $current_date" \ + "$(printf 'Audio could not be mixed — continuing with overlay only\n\naudio-capture log:\n%s' "$_jlog")" || true + [ "$audio_src" = "${cam_audio:-}" ] && rm -f "${cam_audio:-}" + fi fi fi fi From 65b8caf7f9a1da13c46bfb2aa68b174d06408f79 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 11:53:57 +0000 Subject: [PATCH 2/2] =?UTF-8?q?Reorder=20audio=20fallback=20chain:=20today?= =?UTF-8?q?=20=E2=86=92=20live=20RTSP=20=E2=86=92=20yesterday=20=E2=86=92?= =?UTF-8?q?=20library?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves live RTSP capture to 2nd position so current ambient sound is preferred over a day-old recording when today's scheduled capture is missing. https://claude.ai/code/session_01DANuzLCLhhQ7Li12RTcswY --- daily_sunrise_video.sh | 46 ++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/daily_sunrise_video.sh b/daily_sunrise_video.sh index febe5d7..4aaa283 100755 --- a/daily_sunrise_video.sh +++ b/daily_sunrise_video.sh @@ -343,33 +343,14 @@ else if [ -f "$cam_audio" ]; then audio_src="$cam_audio" echo "Audio: camera recording (centred on sunrise)" - else - # Yesterday fallback before library: keeps the clip on-site - yesterday_date=$(date -d "yesterday" +%Y-%m-%d) - yday_audio="${AUDIO_DIR:-$BASE_DIR/audio}/sunrise/$CAM_NAME/$yesterday_date/sunrise-audio.m4a" - [ ! -f "$yday_audio" ] && yday_audio="$BASE_DIR/$CAM_NAME/$yesterday_date/sunrise-audio.m4a" - if [ -f "$yday_audio" ]; then - audio_src="$yday_audio" - echo "Audio: yesterday's recording ($yesterday_date)" - else - library_dir="$SCRIPT_DIR/sunrise-sounds" - if [ -d "$library_dir" ]; then - random_file=$(find "$library_dir" -name "*.mp3" | shuf -n 1 2>/dev/null || true) - if [ -n "$random_file" ]; then - audio_src="$random_file" - echo "Audio: library fallback $(basename "$audio_src")" - fi - fi - fi fi - # Live RTSP as last resort — captures current ambient sound when no - # pre-recorded file is available from today, yesterday, or the library. + # 2nd fallback: live RTSP — captures current ambient sound right now if [ -z "$audio_src" ]; then _rtsp_var="CAM_RTSP_${CAM_NAME}" _rtsp_url="${!_rtsp_var:-}" if [ -n "$_rtsp_url" ]; then temp_live_audio=$(mktemp --suffix=.m4a) - echo "Audio: no saved file found — capturing ${SUNRISE_TARGET_SECS}s live from RTSP..." + echo "Audio: no saved file — capturing ${SUNRISE_TARGET_SECS}s live from RTSP..." if ffmpeg -loglevel warning \ -rtsp_transport tcp \ -i "$_rtsp_url" \ @@ -380,7 +361,28 @@ else echo "Audio: live RTSP captured OK" else rm -f "$temp_live_audio"; temp_live_audio="" - echo "Audio: live RTSP capture failed — continuing silent" + echo "Audio: live RTSP capture failed — trying yesterday" + fi + fi + fi + # 3rd fallback: yesterday's recording + if [ -z "$audio_src" ]; then + yesterday_date=$(date -d "yesterday" +%Y-%m-%d) + yday_audio="${AUDIO_DIR:-$BASE_DIR/audio}/sunrise/$CAM_NAME/$yesterday_date/sunrise-audio.m4a" + [ ! -f "$yday_audio" ] && yday_audio="$BASE_DIR/$CAM_NAME/$yesterday_date/sunrise-audio.m4a" + if [ -f "$yday_audio" ]; then + audio_src="$yday_audio" + echo "Audio: yesterday's recording ($yesterday_date)" + fi + fi + # 4th fallback: library + if [ -z "$audio_src" ]; then + library_dir="$SCRIPT_DIR/sunrise-sounds" + if [ -d "$library_dir" ]; then + random_file=$(find "$library_dir" -name "*.mp3" | shuf -n 1 2>/dev/null || true) + if [ -n "$random_file" ]; then + audio_src="$random_file" + echo "Audio: library fallback $(basename "$audio_src")" fi fi fi