forked from cwtv/stuff
				
			Successfull test script
This commit is contained in:
		
							parent
							
								
									fbe67bb400
								
							
						
					
					
						commit
						9d6b13c19d
					
				
							
								
								
									
										226
									
								
								render-chunks.sh
								
								
								
								
							
							
						
						
									
										226
									
								
								render-chunks.sh
								
								
								
								
							| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
#!/usr/bin/env bash
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
set -euo pipefail
 | 
					set -o errexit -o nounset -o pipefail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IFS=$'\n'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# License MIT
 | 
					# License MIT
 | 
				
			||||||
# Authors 2024
 | 
					# Authors 2024
 | 
				
			||||||
| 
						 | 
					@ -23,82 +25,91 @@ which ffmpeg >/dev/null || (echo "Please install ffmpeg" ; exit 1)
 | 
				
			||||||
which fzf >/dev/null || (echo "Please install fzf" ; exit 1)
 | 
					which fzf >/dev/null || (echo "Please install fzf" ; exit 1)
 | 
				
			||||||
which mpv >/dev/null || (echo "Please install mpv" ; exit 1)
 | 
					which mpv >/dev/null || (echo "Please install mpv" ; exit 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INTROS_PATH="$HOME/Dokumente/syncthing/intros"
 | 
					INTROS_PATH="${HOME}/Dokumente/cloud.ctbk.de/FSCK/2025/VOC/Talk-Intros/"
 | 
				
			||||||
OUTROS_PATH="$HOME/Dokumente/syncthing/outros"
 | 
					OUTROS_PATH="${HOME}/Dokumente/cloud.ctbk.de/FSCK/2025/VOC/Talk-Outro/"
 | 
				
			||||||
CHUNKS_PATH="$HOME/Dokumente/syncthing/"
 | 
					CHUNKS_PATH="${HOME}/Dokumente/syncthing/fsck2025/streamingrechner/Recordings/"
 | 
				
			||||||
OUTPUT_PATH="$HOME/Videos/WK25/rendered"
 | 
					OUTPUT_PATH="${HOME}/Dokumente/syncthing/cwtv/cwtv-synthing/rendered/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# temp dir
 | 
					 | 
				
			||||||
WORKDIR=$(mktemp -d)
 | 
					WORKDIR=$(mktemp -d)
 | 
				
			||||||
function finish {
 | 
					function finish {
 | 
				
			||||||
  rm -r "$WORKDIR"
 | 
					  rm -r "$WORKDIR"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
trap finish EXIT
 | 
					trap finish EXIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Function to convert image to video with audio
 | 
				
			||||||
 | 
					convert_image_to_video() {
 | 
				
			||||||
 | 
					    local IMAGE_FILE="${1}"
 | 
				
			||||||
 | 
					    local VIDEO_FILE="${2}"
 | 
				
			||||||
 | 
					    local DURATION="${3}"
 | 
				
			||||||
 | 
					    local FADE_TYPE
 | 
				
			||||||
 | 
					    local FADE_START
 | 
				
			||||||
 | 
					    local FADE_DURATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if [[ "$4" == 0 ]]
 | 
				
			||||||
 | 
					    then
 | 
				
			||||||
 | 
					        # Fade-out
 | 
				
			||||||
 | 
					        FADE_TYPE="out"
 | 
				
			||||||
 | 
					        FADE_DURATION="${5}"
 | 
				
			||||||
 | 
					        FADE_START="$(echo "${DURATION} - ${FADE_DURATION} - 0.02" | bc | awk '{printf "%.5f\n", $0}')"
 | 
				
			||||||
 | 
					        # Note: The 0.02 = 1/50 is a hack to ensure we don't miss the last (fully black) frame
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        # Fade-in
 | 
				
			||||||
 | 
					        FADE_TYPE="in"
 | 
				
			||||||
 | 
					        FADE_DURATION="${4}"
 | 
				
			||||||
 | 
					        FADE_START="0"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    echo "Rendering fade:"
 | 
				
			||||||
 | 
					    echo "Type:     ${FADE_TYPE}"
 | 
				
			||||||
 | 
					    echo "Start:    ${FADE_START}"
 | 
				
			||||||
 | 
					    echo "Duration: ${FADE_DURATION}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ffmpeg \
 | 
				
			||||||
 | 
					        -loop 1 \
 | 
				
			||||||
 | 
					        -framerate 50 \
 | 
				
			||||||
 | 
					        -i "${IMAGE_FILE}" \
 | 
				
			||||||
 | 
					        -f lavfi -i anullsrc=r=48000:cl=stereo \
 | 
				
			||||||
 | 
					        -vf "fade=type=${FADE_TYPE}:start_time=${FADE_START}:duration=${FADE_DURATION},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 \
 | 
				
			||||||
 | 
					        -t "${DURATION}" "${VIDEO_FILE}"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# STEP 1
 | 
				
			||||||
# Select the appropriate files
 | 
					# Select the appropriate files
 | 
				
			||||||
SELECTED_INTRO="$(find  "$INTROS_PATH" -type f | sort --reverse --human-numeric-sort | fzf --delimiter / --with-nth -1 --prompt "Intro File:")"
 | 
					SELECTED_INTRO="$(find  "$INTROS_PATH" -type f | sort --reverse --human-numeric-sort | fzf --delimiter / --with-nth -1 --prompt "Intro File:")"
 | 
				
			||||||
SELECTED_OUTRO="$(find  "$OUTROS_PATH" -type f | sort --reverse --human-numeric-sort | fzf --delimiter / --with-nth -1 --prompt "Outro File:")"
 | 
					SELECTED_OUTRO="$(find  "$OUTROS_PATH" -type f | sort --reverse --human-numeric-sort | fzf --delimiter / --with-nth -1 --prompt "Outro File:")"
 | 
				
			||||||
SELECTED_CHUNKS="$(find "$CHUNKS_PATH" -type f | sort --reverse | fzf --delimiter / --with-nth -1 -m --prompt "Video Chunks (use tab to select multiple):" | sort )"
 | 
					SELECTED_CHUNKS="$(find "$CHUNKS_PATH" -type f | sort --reverse | fzf --delimiter / --with-nth -1 -m --prompt "Video Chunks (use tab to select multiple):" | sort )"
 | 
				
			||||||
readarray -t CHUNKS_ARRAY < <(echo "$SELECTED_CHUNKS")
 | 
					readarray -t CHUNKS_ARRAY < <(echo "$SELECTED_CHUNKS")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FOOBARWTF="$(basename "$SELECTED_INTRO")"
 | 
					BASEPATH="$(basename "${SELECTED_INTRO}")"
 | 
				
			||||||
DEFAULT_OUTPUT_NAME="${FOOBARWTF%.*}"
 | 
					DEFAULT_OUTPUT_NAME="${BASEPATH%.*}"
 | 
				
			||||||
read -p "Please enter a name for the outputfile (path and extension will be added automatically): " -i "$DEFAULT_OUTPUT_NAME" -e OUTPUT_NAME
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Function to convert image to video with audio
 | 
					read -r -p "Please enter a name for the outputfile (path and extension will be added automatically): " -i "${DEFAULT_OUTPUT_NAME}" -e OUTPUT_NAME
 | 
				
			||||||
convert_image_to_video() {
 | 
					 | 
				
			||||||
    local image_file="$1"
 | 
					 | 
				
			||||||
    local output_video="$2"
 | 
					 | 
				
			||||||
    local duration="$3"
 | 
					 | 
				
			||||||
    local fade_in="$4"
 | 
					 | 
				
			||||||
    local fade_out="$5"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if [[ $fade_in == 0 ]]
 | 
					CONFIG_FILE="${OUTPUT_PATH}/${OUTPUT_NAME}.config"
 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# find the start-offset for the first chunk
 | 
					# find the start-offset for the first chunk
 | 
				
			||||||
read -p "Do you want to play the first chunk ${CHUNKS_ARRAY[0]} to find the start-offset? (y/n) [n]: " PLAY_FIRST_CHUNK
 | 
					read -r -p "Do you want to play the first chunk ${CHUNKS_ARRAY[0]} to find the start-offset? (y/n) [n]: " PLAY_FIRST_CHUNK
 | 
				
			||||||
PLAY_FIRST_CHUNK="${PLAY_FIRST_CHUNK:-n}"
 | 
					PLAY_FIRST_CHUNK="${PLAY_FIRST_CHUNK:-n}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[ "$PLAY_FIRST_CHUNK" == "y" ]] && mpv "${CHUNKS_ARRAY[0]}" --osd-level=3 --osd-status-msg='${=time-pos}' --really-quiet
 | 
					[[ "$PLAY_FIRST_CHUNK" == "y" ]] && mpv "${CHUNKS_ARRAY[0]}" --osd-level=3 --osd-status-msg='${=time-pos}' --really-quiet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
read -p "Enter the start-offset in seconds for the first chunk ${CHUNKS_ARRAY[0]} [0]: " START_OFFSET
 | 
					read -r -p "Enter the start-offset in seconds for the first chunk ${CHUNKS_ARRAY[0]} [0]: " START_OFFSET
 | 
				
			||||||
START_OFFSET="${START_OFFSET:-0}"
 | 
					START_OFFSET="${START_OFFSET:-0}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
# find the end-offset for the last chunk
 | 
					# find the end-offset for the last chunk
 | 
				
			||||||
read -p "Do you want to play the last chunk ${CHUNKS_ARRAY[-1]} to find the end-offset? (y/n) [n]: " PLAY_LAST_CHUNK
 | 
					read -r -p "Do you want to play the last chunk ${CHUNKS_ARRAY[-1]} to find the end-offset? (y/n) [n]: " PLAY_LAST_CHUNK
 | 
				
			||||||
PLAY_LAST_CHUNK="${PLAY_LAST_CHUNK:-n}"
 | 
					PLAY_LAST_CHUNK="${PLAY_LAST_CHUNK:-n}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[ "$PLAY_LAST_CHUNK" == "y" ]] && mpv "${CHUNKS_ARRAY[-1]}" --osd-level=3 --osd-status-msg='${=time-pos}' --really-quiet
 | 
					[[ "$PLAY_LAST_CHUNK" == "y" ]] && mpv "${CHUNKS_ARRAY[-1]}" --osd-level=3 --osd-status-msg='${=time-pos}' --really-quiet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
read -p "Enter the end-offset in seconds for the last chunk ${CHUNKS_ARRAY[0]} [1]: " END_OFFSET
 | 
					read -r -p "Enter the end-offset in seconds for the last chunk ${CHUNKS_ARRAY[0]} [1]: " END_OFFSET
 | 
				
			||||||
END_OFFSET="${END_OFFSET:-1}"
 | 
					END_OFFSET="${END_OFFSET:-1}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Check if intro is an image and convert if necessary
 | 
					# Check if intro is an image and convert if necessary
 | 
				
			||||||
| 
						 | 
					@ -117,10 +128,9 @@ if [[ "$EXT_OUTRO" == "png" || "$EXT_OUTRO" == "jpg" || "$EXT_OUTRO" == "jpeg" ]
 | 
				
			||||||
    SELECTED_OUTRO="$OUTRO_VIDEO"
 | 
					    SELECTED_OUTRO="$OUTRO_VIDEO"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cat <<EOT
 | 
					# print and log choices
 | 
				
			||||||
 | 
					echo ; echo ; echo
 | 
				
			||||||
 | 
					cat <<EOT | tee "${CONFIG_FILE}"
 | 
				
			||||||
 | 
					 | 
				
			||||||
I will be rendering with the following configuration:
 | 
					I will be rendering with the following configuration:
 | 
				
			||||||
    + Selected Intro: ${SELECTED_INTRO}
 | 
					    + Selected Intro: ${SELECTED_INTRO}
 | 
				
			||||||
    + Selected Outro: ${SELECTED_OUTRO}
 | 
					    + Selected Outro: ${SELECTED_OUTRO}
 | 
				
			||||||
| 
						 | 
					@ -133,17 +143,18 @@ I will be rendering with the following configuration:
 | 
				
			||||||
EOT
 | 
					EOT
 | 
				
			||||||
for index in "${!CHUNKS_ARRAY[@]}"
 | 
					for index in "${!CHUNKS_ARRAY[@]}"
 | 
				
			||||||
do
 | 
					do
 | 
				
			||||||
    echo "            + $index: ${CHUNKS_ARRAY[index]}"
 | 
					    echo "            + $index: ${CHUNKS_ARRAY[index]}" | tee -a "${CONFIG_FILE}"
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
echo "Export: ${OUTPUT_PATH}/${OUTPUT_NAME}.mkv"
 | 
					echo "Export: ${OUTPUT_PATH}/${OUTPUT_NAME}.mkv" | tee -a "${CONFIG_FILE}"
 | 
				
			||||||
 | 
					echo "Config: ${CONFIG_FILE}" | tee -a "${CONFIG_FILE}"
 | 
				
			||||||
echo ; echo ; echo
 | 
					echo ; echo ; echo
 | 
				
			||||||
read -p "Do you want to proceed with this configuration? (y/n) [y]" PROCEED
 | 
					read -r -p "Do you want to proceed with this configuration? (y/n) [y]" PROCEED
 | 
				
			||||||
PROCEED="${PROCEED:-y}"
 | 
					PROCEED="${PROCEED:-y}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[ "$PROCEED" == "y" ]] || (echo "aborting"; exit 1)
 | 
					[[ "$PROCEED" == "y" ]] || (echo "aborting"; exit 1)
 | 
				
			||||||
echo "doing ffmpeg things here"
 | 
					echo "doing ffmpeg things here"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# combine the videos...
 | 
					# combine the videos
 | 
				
			||||||
ARRAY_LENGTH="${#CHUNKS_ARRAY[@]}"
 | 
					ARRAY_LENGTH="${#CHUNKS_ARRAY[@]}"
 | 
				
			||||||
if [[ ${ARRAY_LENGTH} -lt 2 ]]
 | 
					if [[ ${ARRAY_LENGTH} -lt 2 ]]
 | 
				
			||||||
then
 | 
					then
 | 
				
			||||||
| 
						 | 
					@ -151,28 +162,9 @@ then
 | 
				
			||||||
    exit 1
 | 
					    exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# STEP 1
 | 
					 | 
				
			||||||
# temp dir
 | 
					 | 
				
			||||||
WORKDIR=$(mktemp -d)
 | 
					 | 
				
			||||||
function finish {
 | 
					 | 
				
			||||||
  rm -r "$WORKDIR"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
trap finish EXIT
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# STEP 2
 | 
					# STEP 2
 | 
				
			||||||
# Dauer des Intros ermitteln
 | 
					 | 
				
			||||||
echo "==== STEP 2 ===="
 | 
					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
 | 
					# Prüfen, ob CHUNKS_ARRAY existiert und nicht leer ist
 | 
				
			||||||
if [[ -z "${CHUNKS_ARRAY[0]}" ]]; then
 | 
					if [[ -z "${CHUNKS_ARRAY[0]}" ]]; then
 | 
				
			||||||
| 
						 | 
					@ -180,44 +172,82 @@ if [[ -z "${CHUNKS_ARRAY[0]}" ]]; then
 | 
				
			||||||
    exit 1
 | 
					    exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Dauer des Intros ermitteln
 | 
				
			||||||
 | 
					INTRO_DURATION="$(ffprobe -i "$SELECTED_INTRO" -show_entries format=duration -v quiet -of csv="p=0")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sicherstellen, dass die Dauer gültig ist
 | 
				
			||||||
 | 
					if [[ -z "$INTRO_DURATION" || "$INTRO_DURATION" == "N/A" ]]; then
 | 
				
			||||||
 | 
					    echo "Fehler: Die Dauer des Intros konnte nicht ermittelt werden."
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OUTRO_DURATION="$(ffprobe -i "$SELECTED_OUTRO" -show_entries format=duration -v quiet -of csv="p=0")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sicherstellen, dass die Dauer gültig ist
 | 
				
			||||||
 | 
					if [[ -z "$OUTRO_DURATION" || "$OUTRO_DURATION" == "N/A" ]]; then
 | 
				
			||||||
 | 
					    echo "Fehler: Die Dauer des Outros konnte nicht ermittelt werden."
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CROSSFADE_DURATION="0.5"
 | 
					CROSSFADE_DURATION="0.5"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Offset berechnen und negative Werte verhindern
 | 
				
			||||||
 | 
					INTRO_OFFSET="$(echo "${INTRO_DURATION} - ${CROSSFADE_DURATION}" | bc | awk '{printf "%.5f\n", $0}')"
 | 
				
			||||||
 | 
					if (( $(echo "${INTRO_OFFSET} < 0" | bc) )); then INTRO_OFFSET=0; fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OUTRO_OFFSET="$(echo "${END_OFFSET} - ${CROSSFADE_DURATION}" | bc | awk '{printf "%.5f\n", $0}')"
 | 
				
			||||||
 | 
					if (( $(echo "${OUTRO_OFFSET} < 0" | bc) )); then OUTRO_OFFSET=0; fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Intro mit Crossfade zum ersten Chunk
 | 
					# Intro mit Crossfade zum ersten Chunk
 | 
				
			||||||
ffmpeg -i "$SELECTED_INTRO" -ss "$START_OFFSET" -i "${CHUNKS_ARRAY[0]}" \
 | 
					echo "Rendering intro transition:"
 | 
				
			||||||
 | 
					echo "Intro duration:     ${INTRO_DURATION}"
 | 
				
			||||||
 | 
					echo "Intro offset:       ${INTRO_OFFSET}"
 | 
				
			||||||
 | 
					echo "Crossfade duration: ${CROSSFADE_DURATION}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ffmpeg \
 | 
				
			||||||
 | 
					-i "${SELECTED_INTRO}" \
 | 
				
			||||||
 | 
					-ss "${START_OFFSET}" -accurate_seek -i "${CHUNKS_ARRAY[0]}" \
 | 
				
			||||||
-filter_complex \
 | 
					-filter_complex \
 | 
				
			||||||
"[0:v:0]format=pix_fmts=yuv420p,fps=50[va]; \
 | 
					"[0:v:0]format=pix_fmts=yuv420p,fps=50[vintro]; \
 | 
				
			||||||
 [1:v:0]format=pix_fmts=yuv420p,fps=50[vb]; \
 | 
					 [1:v:0]format=pix_fmts=yuv420p,fps=50[vchunk1]; \
 | 
				
			||||||
 [va][vb]xfade=transition=fade:duration=${CROSSFADE_DURATION}:offset=${OFFSET}[v]; \
 | 
					 [vintro][vchunk1]xfade=transition=fade:duration=${CROSSFADE_DURATION}:offset=${INTRO_OFFSET}[vout]; \
 | 
				
			||||||
 [1:a:0]afade=t=in:st=0:d=${CROSSFADE_DURATION}[a]; \
 | 
					 [0:a:0]atrim=start=0:end=${INTRO_OFFSET}[atrim]; \
 | 
				
			||||||
 [0:a:0][a]concat=n=2:v=0:a=1[a0]" \
 | 
					 [atrim]asetpts=PTS-STARTPTS[aintro]; \
 | 
				
			||||||
-map '[v]' -map '[a0]' \
 | 
					 [1:a:0]afade=type=in:start_time=0:duration=${CROSSFADE_DURATION}[achunk1]; \
 | 
				
			||||||
 | 
					 [aintro][achunk1]concat=n=2:v=0:a=1[aout]" \
 | 
				
			||||||
 | 
					-map '[vout]' -map '[aout]' \
 | 
				
			||||||
-c:a aac -b:a 192k \
 | 
					-c:a aac -b:a 192k \
 | 
				
			||||||
-c:v libx264 -threads 4 -pix_fmt yuv420p -crf 18 -profile:v high -level 4.1 -disposition default \
 | 
					-c:v libx264 -threads 0 -pix_fmt yuv420p -crf 18 -profile:v high -level 4.1 -disposition default \
 | 
				
			||||||
-movflags +faststart \
 | 
					 | 
				
			||||||
-metadata:s:a:0 language=native \
 | 
					-metadata:s:a:0 language=native \
 | 
				
			||||||
"${WORKDIR}/introcombined.mkv"
 | 
					"${WORKDIR}/introcombined.mkv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# STEP 3
 | 
					 | 
				
			||||||
# Outro mit Crossfade vom letzten Chunk
 | 
					# Outro mit Crossfade vom letzten Chunk
 | 
				
			||||||
echo "==== STEP 3 ===="
 | 
					echo "Rendering outro transition:"
 | 
				
			||||||
FOO=$(echo "${END_OFFSET} - ${CROSSFADE_DURATION}" | bc)
 | 
					echo "Outro duration:     ${OUTRO_DURATION}"
 | 
				
			||||||
ffmpeg -i "$SELECTED_OUTRO" -t "$END_OFFSET" -i "${CHUNKS_ARRAY[$((${#CHUNKS_ARRAY[@]} - 1))]}" \
 | 
					echo "Outro offset:       ${OUTRO_OFFSET}"
 | 
				
			||||||
 | 
					echo "Crossfade duration: ${CROSSFADE_DURATION}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ffmpeg \
 | 
				
			||||||
 | 
					-i "${SELECTED_OUTRO}" \
 | 
				
			||||||
 | 
					-t "${END_OFFSET}" -accurate_seek -i "${CHUNKS_ARRAY[$((${#CHUNKS_ARRAY[@]} - 1))]}" \
 | 
				
			||||||
-filter_complex \
 | 
					-filter_complex \
 | 
				
			||||||
"[1:v:0]format=pix_fmts=yuv420p,fps=50[v1]; \
 | 
					"[0:v:0]format=pix_fmts=yuv420p,fps=50[voutro]; \
 | 
				
			||||||
 [0:v:0]format=pix_fmts=yuv420p,fps=50[v0]; \
 | 
					 [1:v:0]format=pix_fmts=yuv420p,fps=50[vchunkn]; \
 | 
				
			||||||
 [v1][v0]xfade=transition=fade:duration=${CROSSFADE_DURATION}:offset=${FOO}[v]; \
 | 
					 [vchunkn][voutro]xfade=transition=fade:duration=${CROSSFADE_DURATION}:offset=${OUTRO_OFFSET}[vout]; \
 | 
				
			||||||
 [1:a:0]afade=t=out:st=${FOO}:d=${CROSSFADE_DURATION}[a1]; \
 | 
					 [1:a:0]afade=type=out:start_time=${OUTRO_OFFSET}:duration=${CROSSFADE_DURATION}[achunkn]; \
 | 
				
			||||||
 [0:a:0]afade=t=in:st=0:d=${CROSSFADE_DURATION}[a0]; \
 | 
					 [0:a:0]atrim=start=${CROSSFADE_DURATION}:end=${OUTRO_DURATION}[atrim]; \
 | 
				
			||||||
 [a1][a0]acrossfade=d=1[a]" \
 | 
					 [atrim]asetpts=PTS-STARTPTS[aoutro]; \
 | 
				
			||||||
-map "[v]" -map "[a]" \
 | 
					 [achunkn][aoutro]concat=n=2:v=0:a=1[aout]" \
 | 
				
			||||||
 | 
					-map '[vout]' -map '[aout]' \
 | 
				
			||||||
-c:a aac -b:a 192k \
 | 
					-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 0 -pix_fmt yuv420p -crf 18 -profile:v high -level 4.1 -disposition default \
 | 
				
			||||||
-metadata:s:a:0 language=native \
 | 
					-metadata:s:a:0 language=native \
 | 
				
			||||||
"${WORKDIR}/outrocombined.mkv"
 | 
					"${WORKDIR}/outrocombined.mkv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# STEP 4
 | 
					
 | 
				
			||||||
 | 
					# STEP 3
 | 
				
			||||||
# Encoded intro+outro und alle Chunks in between mit c:v copy und audio dynnorm + encode
 | 
					# Encoded intro+outro und alle Chunks in between mit c:v copy und audio dynnorm + encode
 | 
				
			||||||
echo "==== STEP 4 ===="
 | 
					echo "==== STEP 3 ===="
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CHUNKLIST="${WORKDIR}/chunklist.txt"
 | 
					CHUNKLIST="${WORKDIR}/chunklist.txt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,7 +256,7 @@ echo "file '${WORKDIR}/introcombined.mkv'" > "$CHUNKLIST"
 | 
				
			||||||
FFMPEG_CONCAT_CHUNKS=""
 | 
					FFMPEG_CONCAT_CHUNKS=""
 | 
				
			||||||
if [[ ${ARRAY_LENGTH} -gt 2 ]]
 | 
					if [[ ${ARRAY_LENGTH} -gt 2 ]]
 | 
				
			||||||
then
 | 
					then
 | 
				
			||||||
    for index in $(seq 1 $(( ${ARRAY_LENGTH} - 2 )) )
 | 
					    for index in $(seq 1 $(( ARRAY_LENGTH - 2 )) )
 | 
				
			||||||
    do
 | 
					    do
 | 
				
			||||||
        FFMPEG_CONCAT_CHUNKS="${FFMPEG_CONCAT_CHUNKS}|${CHUNKS_ARRAY[index]}"
 | 
					        FFMPEG_CONCAT_CHUNKS="${FFMPEG_CONCAT_CHUNKS}|${CHUNKS_ARRAY[index]}"
 | 
				
			||||||
        echo "file '${CHUNKS_ARRAY[index]}'" >> "$CHUNKLIST"
 | 
					        echo "file '${CHUNKS_ARRAY[index]}'" >> "$CHUNKLIST"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								render.sh
								
								
								
								
							
							
						
						
									
										29
									
								
								render.sh
								
								
								
								
							| 
						 | 
					@ -1,29 +0,0 @@
 | 
				
			||||||
#!/bin/bash
 | 
					 | 
				
			||||||
set -euxo pipefail
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
INTRO="$1"
 | 
					 | 
				
			||||||
RECORDING="$2"
 | 
					 | 
				
			||||||
OUTRO="${3:-intros/outro_ccbysa.mkv}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
START_SECONDS="$3"
 | 
					 | 
				
			||||||
STOP_SECONDS="$4"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DURATION_SECONDS=$(($STOP_SECONDS - $START_SECONDS))
 | 
					 | 
				
			||||||
FADEOUT_SECONDS=$(($DURATION_SECONDS - 1))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ffmpeg -i "$INTRO" \
 | 
					 | 
				
			||||||
  -ss $START_SECONDS -t $DURATION_SECONDS -i "$RECORDING" \
 | 
					 | 
				
			||||||
  -i "$OUTRO" -filter_complex \
 | 
					 | 
				
			||||||
  "[1:v:0]fade=t=in:st=0:d=0.2[x];[x]fade=t=out:st=$FADEOUT_SECONDS:d=1.0[y];\
 | 
					 | 
				
			||||||
  [1:a:0]afade=t=in:st=0:d=0.2[a];[a]afade=t=out:st=$FADEOUT_SECONDS:d=1.0[b];\
 | 
					 | 
				
			||||||
  [b]dynaudnorm[bd];\
 | 
					 | 
				
			||||||
  [0:v:0][0:a:0]\
 | 
					 | 
				
			||||||
  [y][bd]\
 | 
					 | 
				
			||||||
  [2:v:0][2:a:0]\
 | 
					 | 
				
			||||||
  concat=n=3:v=1:a=1\
 | 
					 | 
				
			||||||
  [v][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 \
 | 
					 | 
				
			||||||
  -metadata:s:a:0 language=native \
 | 
					 | 
				
			||||||
  "rendered_recordings/$(basename -s .mp4 ${INTRO})_$(basename -s .mkv ${RECORDING})_COMBINED.mkv"
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue