diff --git a/render-chunks.sh b/render-chunks.sh index 5089e5a..d203f04 100755 --- a/render-chunks.sh +++ b/render-chunks.sh @@ -53,9 +53,32 @@ convert_image_to_video() { local fade_in="$4" local fade_out="$5" - ffmpeg -loop 1 -t "$duration" -i "$image_file" -f lavfi -i anullsrc=r=48000:cl=stereo \ - -vf "fade=t=in:st=0:d=$fade_in,fade=t=out:st=$(($duration - $fade_out)):d=$fade_out,format=yuv420p" \ - -r 50 -c:v libx264 -c:a aac -b:a 192k -t "$duration" "$output_video" + if [[ $fade_in == 0 ]] + then + ffmpeg -loop 1 \ + -framerate 50 \ + -t "$duration" \ + -i "$image_file" -f lavfi \ + -i anullsrc=r=48000:cl=stereo \ + -vf "fade=t=out:st=$(($duration - $fade_out)):d=$fade_out,format=pix_fmts=yuv420p,fps=50" \ + -c:a aac -b:a 192k \ + -c:v libx264 -threads 0 -pix_fmt yuv420p -crf 18 \ + -profile:v high -level 4.1 -disposition default -color_range tv \ + -metadata:s:a:0 language=native \ + -t "$duration" "$output_video" + else + ffmpeg -loop 1 \ + -framerate 50 \ + -t "$duration" \ + -i "$image_file" -f lavfi \ + -i anullsrc=r=48000:cl=stereo \ + -filter_complex "fade=t=in:st=0:d=$fade_in,format=pix_fmts=yuv420p,fps=50" \ + -c:a aac -b:a 192k \ + -c:v libx264 -threads 0 -pix_fmt yuv420p -crf 18 \ + -profile:v high -level 4.1 -disposition default -color_range tv \ + -metadata:s:a:0 language=native \ + -t "$duration" "$output_video" + fi } @@ -104,7 +127,7 @@ I will be rendering with the following configuration: + Video Chunks: + First chunk: ${CHUNKS_ARRAY[0]} Starting at second ${START_OFFSET} - + Last chunk: ${CHUNKS_ARRAY[-1]} + + Last chunk: ${CHUNKS_ARRAY[$((${#CHUNKS_ARRAY[@]} - 1))]} Ending at second ${END_OFFSET} + All chunks: EOT @@ -137,39 +160,64 @@ function finish { trap finish EXIT # STEP 2 -# introfile with first chunk and crossfade encode +# Dauer des Intros ermitteln +echo "==== STEP 2 ====" +DURATION_INTRO=$(ffprobe -i "$SELECTED_INTRO" -show_entries format=duration -v quiet -of csv="p=0") + +# Sicherstellen, dass die Dauer gültig ist +if [[ -z "$DURATION_INTRO" || "$DURATION_INTRO" == "N/A" ]]; then + echo "Fehler: Die Dauer des Intros konnte nicht ermittelt werden." + exit 1 +fi + +# Offset berechnen und negative Werte verhindern +OFFSET=$(echo "scale=2; $DURATION_INTRO - 0.5" | bc) +if (( $(echo "$OFFSET < 0" | bc -l) )); then OFFSET=0; fi + +# Prüfen, ob CHUNKS_ARRAY existiert und nicht leer ist +if [[ -z "${CHUNKS_ARRAY[0]}" ]]; then + echo "Fehler: CHUNKS_ARRAY ist leer oder nicht definiert." + exit 1 +fi + +CROSSFADE_DURATION="0.5" + +# Intro mit Crossfade zum ersten Chunk ffmpeg -i "$SELECTED_INTRO" -ss "$START_OFFSET" -i "${CHUNKS_ARRAY[0]}" \ -filter_complex \ -"[1:v:0]fade=t=in:st=0:d=0.2[x]; - [1:a:0]afade=t=in:st=0:d=0.2[a]; - [0:v:0][0:a:0] - [x][a] - concat=n=2:v=1:a=1 - [v0][a0]" \ --map '[v0]' -map '[a0]' \ +"[0:v:0]format=pix_fmts=yuv420p,fps=50[va]; \ + [1:v:0]format=pix_fmts=yuv420p,fps=50[vb]; \ + [va][vb]xfade=transition=fade:duration=${CROSSFADE_DURATION}:offset=${OFFSET}[v]; \ + [1:a:0]afade=t=in:st=0:d=${CROSSFADE_DURATION}[a]; \ + [0:a:0][a]concat=n=2:v=0:a=1[a0]" \ +-map '[v]' -map '[a0]' \ -c:a aac -b:a 192k \ --c:v libx264 -threads 0 -pix_fmt yuv420p -crf 18 -profile:v high -level 4.1 -disposition default \ +-c:v libx264 -threads 4 -pix_fmt yuv420p -crf 18 -profile:v high -level 4.1 -disposition default \ +-movflags +faststart \ -metadata:s:a:0 language=native \ "${WORKDIR}/introcombined.mkv" # STEP 3 -# outrofile with last chunk and corssface encode -ffmpeg -i "$SELECTED_OUTRO" -t "$END_OFFSET" -i "${CHUNKS_ARRAY[-1]}" \ +# Outro mit Crossfade vom letzten Chunk +echo "==== STEP 3 ====" +FOO=$(echo "${END_OFFSET} - ${CROSSFADE_DURATION}" | bc) +ffmpeg -i "$SELECTED_OUTRO" -t "$END_OFFSET" -i "${CHUNKS_ARRAY[$((${#CHUNKS_ARRAY[@]} - 1))]}" \ -filter_complex \ -"[1:v:0]fade=t=out:st=$(($END_OFFSET - 1)):d=1.0[x]; - [1:a:0]afade=t=out:st=$(($END_OFFSET - 1)):d=1.0[a]; - [x][a] - [0:v:0][0:a:0] - concat=n=2:v=1:a=1 - [v0][a0]" \ --map '[v0]' -map '[a0]' \ +"[1:v:0]format=pix_fmts=yuv420p,fps=50[v1]; \ + [0:v:0]format=pix_fmts=yuv420p,fps=50[v0]; \ + [v1][v0]xfade=transition=fade:duration=${CROSSFADE_DURATION}:offset=${FOO}[v]; \ + [1:a:0]afade=t=out:st=${FOO}:d=${CROSSFADE_DURATION}[a1]; \ + [0:a:0]afade=t=in:st=0:d=${CROSSFADE_DURATION}[a0]; \ + [a1][a0]acrossfade=d=1[a]" \ +-map "[v]" -map "[a]" \ -c:a aac -b:a 192k \ -c:v libx264 -threads 0 -pix_fmt yuv420p -crf 18 -profile:v high -level 4.1 -disposition default \ -metadata:s:a:0 language=native \ "${WORKDIR}/outrocombined.mkv" # STEP 4 -# encoded intro+outro and all chunks in between with c:v copy and audio dynnorm + encode +# Encoded intro+outro und alle Chunks in between mit c:v copy und audio dynnorm + encode +echo "==== STEP 4 ====" CHUNKLIST="${WORKDIR}/chunklist.txt"