Add MONTAGE_MUSIC_LOOPS per-movement music loop multiplier
Short adagio movements (Summer Mvt 2 at 107s, Winter Mvt 2 at 132s, etc.) compress each day to only 3-5 seconds of screen time at 1×. Looping the music N times multiplies the per-day target duration proportionally so the footage is less aggressively sped up and more watchable. - sky-cam.conf: add MONTAGE_MUSIC_LOOPS and per-movement overrides (Summer Mvt2=3×, Winter Mvt2=3×, Autumn Mvt2=2×, Summer Mvt3=2×, Spring Mvt2=2×) - 4-seasons.sh: multiply target_per_clip by loops - montage-mvt.sh: compute effective_duration, use -stream_loop for audio, fix fade_out_start, -t, and post-build duration check - make-finals.sh: multiply target by loops https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
This commit is contained in:
+12
-7
@@ -71,6 +71,11 @@ fi
|
||||
music_duration=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$music_file")
|
||||
echo "Music: $(basename "$music_file") (${music_duration}s)"
|
||||
|
||||
loops_var="MONTAGE_MUSIC_LOOPS_${SEASON}_${MVT_NUM}"
|
||||
loops="${!loops_var:-${MONTAGE_MUSIC_LOOPS:-1}}"
|
||||
effective_duration=$(echo "scale=3; $music_duration * $loops" | bc)
|
||||
[ "$loops" -gt 1 ] && echo "Music loops: ${loops}x (effective ${effective_duration}s)"
|
||||
|
||||
# ── Collect sorted daily clips ────────────────────────────────────────────────
|
||||
mapfile -d '' daily_clips < <(find "$video_dir" -maxdepth 1 -name "*-final.mp4" -print0 | sort -z)
|
||||
if [ "${#daily_clips[@]}" -eq 0 ]; then
|
||||
@@ -139,15 +144,15 @@ pad=${VIDEO_W}:${VIDEO_H}:(ow-iw)/2:(oh-ih)/2,setsar=1" \
|
||||
# ── Step 2: Speed-adjust — saved permanently so music/overlay failure is recoverable ─
|
||||
# Deleted automatically if step 3 succeeds.
|
||||
concat_dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$temp_concat")
|
||||
speed_factor=$(echo "scale=6; $concat_dur / $music_duration" | bc)
|
||||
echo "Step 2/3: speed $speed_factor (raw=${concat_dur}s → music=${music_duration}s)"
|
||||
speed_factor=$(echo "scale=6; $concat_dur / $effective_duration" | bc)
|
||||
echo "Step 2/3: speed $speed_factor (raw=${concat_dur}s → target=${effective_duration}s)"
|
||||
|
||||
sped_file="$output_dir/${MVT_START}_${SEASON}_Mvt${MVT_NUM}-Sped.mp4"
|
||||
if ! ffmpeg -loglevel warning \
|
||||
-i "$temp_concat" \
|
||||
-vf "setpts=PTS/$speed_factor" \
|
||||
-c:v libx264 -pix_fmt yuv420p -preset "$ENCODE_PRESET" -crf "$CRF_MONTAGE" -an \
|
||||
-t "$music_duration" -y "$sped_file"; then
|
||||
-t "$effective_duration" -y "$sped_file"; then
|
||||
rm -f "$sped_file"
|
||||
"$SCRIPT_DIR/notify.sh" "FAILED: montage step 2/3 (speed) $SEASON Mvt$MVT_NUM ($ASTRO_YEAR)" \
|
||||
"speed-adjust failed — concat temp lost; re-run montage-mvt.sh" || true
|
||||
@@ -165,7 +170,7 @@ ATTR_FADE_END=$(echo "$ATTR_DUR - $ATTR_FADE" | bc)
|
||||
ALPHA="if(lt(t,${ATTR_FADE}),t/${ATTR_FADE},if(gt(t,${ATTR_FADE_END}),(${ATTR_DUR}-t)/${ATTR_FADE},1))"
|
||||
ENABLE="between(t,0,${ATTR_DUR})"
|
||||
|
||||
fade_out_start=$(echo "scale=3; $music_duration - $FADE_DUR" | bc)
|
||||
fade_out_start=$(echo "scale=3; $effective_duration - $FADE_DUR" | bc)
|
||||
echo "Step 3/3: music + fades + attribution overlay..."
|
||||
|
||||
# Build attribution drawtext filters (box=1 gives a per-line background).
|
||||
@@ -193,20 +198,20 @@ output_file="$output_dir/${MVT_START}_${SEASON}_Mvt${MVT_NUM}-Montage.mp4"
|
||||
# If music/overlay fails, the sped video is promoted to the output path so
|
||||
# year-end-join can still include this movement (as a silent, no-overlay clip).
|
||||
if ffmpeg -loglevel warning \
|
||||
-i "$sped_file" -i "$music_file" \
|
||||
-i "$sped_file" -stream_loop $((loops - 1)) -i "$music_file" \
|
||||
-filter_complex \
|
||||
"[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 libx265 -pix_fmt yuv420p -preset "$ENCODE_PRESET" -crf "$CRF_MONTAGE_FINAL" \
|
||||
-tag:v hvc1 -c:a aac -b:a "$AUDIO_BITRATE" \
|
||||
-t "$music_duration" -y "$output_file"; then
|
||||
-t "$effective_duration" -y "$output_file"; then
|
||||
rm -f "$sped_file"
|
||||
echo "Done: $output_file"
|
||||
|
||||
# ── Post-build checks ─────────────────────────────────────────────────────
|
||||
actual_dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$output_file")
|
||||
dur_delta=$(echo "scale=1; $actual_dur - $music_duration" | bc | sed 's/^-//')
|
||||
dur_delta=$(echo "scale=1; $actual_dur - $effective_duration" | bc | sed 's/^-//')
|
||||
stream_types=$(ffprobe -v error -show_entries stream=codec_type -of csv=p=0 "$output_file" 2>/dev/null)
|
||||
has_video=$(echo "$stream_types" | grep -c "video" || echo 0)
|
||||
has_audio=$(echo "$stream_types" | grep -c "audio" || echo 0)
|
||||
|
||||
Reference in New Issue
Block a user