diff --git a/4-seasons.sh b/4-seasons.sh index b53df3b..58595a0 100755 --- a/4-seasons.sh +++ b/4-seasons.sh @@ -79,7 +79,7 @@ done > "$temp_file" echo "Step 1/2: encoding raw video..." ffmpeg -loglevel warning \ -f concat -safe 0 -i "$temp_file" \ - -c:v libx264 -pix_fmt yuv420p -crf 28 -vsync 2 -an \ + -c:v libx264 -pix_fmt yuv420p -crf "$CRF_SEASONS_RAW" -vsync 2 -an \ -y "$temp_video" raw_duration=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$temp_video") @@ -93,7 +93,7 @@ final_file="$output_dir/${yesterday}_Mvt${MVT_NUM}-Day${DAY_OF_MVT}of${DAYS_IN_M ffmpeg -loglevel warning \ -i "$temp_video" \ -vf "setpts=PTS/$speed_factor" \ - -c:v libx264 -pix_fmt yuv420p -crf 26 \ + -c:v libx264 -pix_fmt yuv420p -crf "$CRF_SEASONS_FINAL" \ -t "$target_per_clip" -an \ -y "$final_file" diff --git a/daily_sunrise_video.sh b/daily_sunrise_video.sh index da5bf51..8289109 100644 --- a/daily_sunrise_video.sh +++ b/daily_sunrise_video.sh @@ -100,7 +100,7 @@ first_movie="$output_dir/$current_date-sunrise-day.mp4" # Create the first movie at the default frame rate (no speed adjustments) echo "Creating video at default frame rate..." -ffmpeg -f concat -safe 0 -i "$temp_file" -c:v libx264 -pix_fmt yuv420p -crf 28 -vsync 2 -y "$first_movie" +ffmpeg -f concat -safe 0 -i "$temp_file" -c:v libx264 -pix_fmt yuv420p -crf "$CRF_SUNRISE" -vsync 2 -y "$first_movie" # Check the duration of the created video video_duration=$(ffmpeg -i "$first_movie" 2>&1 | grep "Duration" | cut -d ' ' -f 4 | sed s/,//) diff --git a/fullday-video.sh b/fullday-video.sh index a627b5e..c2df80a 100755 --- a/fullday-video.sh +++ b/fullday-video.sh @@ -63,7 +63,7 @@ echo "Creating: $output_file" ffmpeg -loglevel warning \ -f concat -safe 0 -i "$temp_list" \ - -c:v libx264 -pix_fmt yuv420p -crf 28 \ + -c:v libx264 -pix_fmt yuv420p -crf "$CRF_FULLDAY" \ -an -y "$output_file" actual_dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$output_file") diff --git a/montage-mvt.sh b/montage-mvt.sh index dfcd52a..c22d6dc 100755 --- a/montage-mvt.sh +++ b/montage-mvt.sh @@ -31,9 +31,11 @@ base_dir="$BASE_DIR" music_base_dir="$MUSIC_DIR" [ ! -d "$music_base_dir" ] && music_base_dir="$SCRIPT_DIR/music" -FADE_DUR=2.0 # video + audio fade in/out (seconds) -ATTR_DUR=6 # attribution overlay duration (seconds from start) -ATTR_FADE=1 # attribution fade in / fade out duration +# Fade/overlay durations come from sky-cam.conf (MONTAGE_FADE_DUR, +# MONTAGE_ATTR_DUR, MONTAGE_ATTR_FADE). Alias for shorter local use. +FADE_DUR="$MONTAGE_FADE_DUR" +ATTR_DUR="$MONTAGE_ATTR_DUR" +ATTR_FADE="$MONTAGE_ATTR_FADE" # ── Season / movement info ──────────────────────────────────────────────────── DATE_ARG="${1:-}" @@ -100,7 +102,7 @@ ffmpeg -loglevel warning \ -f concat -safe 0 -i "$concat_list" \ -vf "scale=${VIDEO_W}:${VIDEO_H}:force_original_aspect_ratio=decrease,\ pad=${VIDEO_W}:${VIDEO_H}:(ow-iw)/2:(oh-ih)/2,setsar=1" \ - -c:v libx264 -pix_fmt yuv420p -crf 26 -an \ + -c:v libx264 -pix_fmt yuv420p -crf "$CRF_MONTAGE" -an \ -y "$temp_concat" # ── Step 2: Speed-adjust to match music duration exactly ────────────────────── @@ -112,7 +114,7 @@ temp_sped=$(mktemp --suffix=.mp4); TMPFILES+=("$temp_sped") ffmpeg -loglevel warning \ -i "$temp_concat" \ -vf "setpts=PTS/$speed_factor" \ - -c:v libx264 -pix_fmt yuv420p -crf 26 -an \ + -c:v libx264 -pix_fmt yuv420p -crf "$CRF_MONTAGE" -an \ -t "$music_duration" -y "$temp_sped" rm "$temp_concat" @@ -156,7 +158,7 @@ ffmpeg -loglevel warning \ "[0:v]fade=t=in:st=0:d=${FADE_DUR},fade=t=out:st=${fade_out_start}:d=${FADE_DUR},${DT}[vout];\ [1:a]afade=t=in:st=0:d=${FADE_DUR},afade=t=out:st=${fade_out_start}:d=${FADE_DUR}[aout]" \ -map "[vout]" -map "[aout]" \ - -c:v libx264 -pix_fmt yuv420p -c:a aac -b:a 192k \ + -c:v libx264 -pix_fmt yuv420p -c:a aac -b:a "$AUDIO_BITRATE" \ -t "$music_duration" -y "$output_file" rm "$temp_sped" diff --git a/sky-cam.conf b/sky-cam.conf index 2046e92..9d0f3e2 100644 --- a/sky-cam.conf +++ b/sky-cam.conf @@ -209,6 +209,32 @@ SUNRISE_TARGET_SECS=10 FULLDAY_FPS=5 # frame rate of the timelapse video RETENTION_DAYS=10 # delete full-day videos older than this many days +# ── Video encoding quality ──────────────────────────────────────────────────── +# FFmpeg CRF: lower = higher quality / larger files. Typical range 18–30. +# 18 ≈ visually lossless 23 = ffmpeg default 28 = smaller/lower +# Different scripts use different defaults by design — intermediate/draft +# encodings use a higher CRF (smaller files, quality less critical), while +# final "polished" outputs use a lower CRF for better quality. +# Each is independent — changing one does NOT change the others. +# +CRF_SUNRISE=28 # daily_sunrise_video.sh — daily Mattermost upload +CRF_FULLDAY=28 # fullday-video.sh — full-day timelapse +CRF_SEASONS_RAW=28 # 4-seasons.sh — raw concat before speed-adjust +CRF_SEASONS_FINAL=26 # 4-seasons.sh — final daily clip (goes into montage) +CRF_MONTAGE=26 # montage-mvt.sh — concat and speed-adjust and final +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) + # ── Mattermost — daily sunrise upload ───────────────────────────────────────── mattermost_url=https://your-mattermost-server.example.com access_token=your-access-token-here