diff --git a/generate.sh b/generate.sh index d54eb18..aed7656 100755 --- a/generate.sh +++ b/generate.sh @@ -1,108 +1,121 @@ #!/bin/bash +# Configuration SOURCEDIR=$(pwd) PROJECT=$1 BASETEMPLATE="nluug-title-template.svg" SOURCEFILE="event.svg" -VIDEODIR=${SOURCEDIR}/output -PROJDIR=/tmp/nluug-intro-${PROJECT} - -if [ -z "${PROJECT}" ]; then - echo "Usage: $0 " - exit 1 -fi - -if [ -z "$EVENTNAME" ]; then - echo "Specify EVENTNAME env-var" - exit 2 -fi -if [ -z "$SPEAKERNAME" ]; then - echo "Specify SPEAKERNAME env-var" - exit 3 -fi -if [ -z "$TITLE1" ] || [ -z "$TITLE2" ] || [ -z "$TITLE3" ]; then - echo "Specify TITLE1/TITLE2/TITLE3 env-vars" - exit 4 -fi - -# Usage: -# EVENTNAME="NLUUG Najaar 5 November 2024" -# MAXLENGTH="SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER" -#SPEAKERNAME="Example Speaker Name" -#TITLE1="Keynote: Some example title" -#TITLE2="With 3 lines, or use some whitespace" -#TITLE3="If less are needed" - +VIDEODIR="${SOURCEDIR}/output" +PROJDIR="/tmp/nluug-intro-${PROJECT}" CONV="convert -background black -fill black -alpha off" FRAMENUM=0 -# Make project directory -mkdir -p ${PROJDIR}; cd ${PROJDIR} +# Validate input +validate_input() { + if [ -z "${PROJECT}" ]; then + echo "Usage: $0 " + exit 1 + fi -# Customize template to this event from base template -awk -v eventname="$EVENTNAME" '{gsub(/EVENTNAMEEVENTNAME/, eventname); print}' "${SOURCEDIR}/${BASETEMPLATE}" > ${SOURCEFILE} + if [ -z "$EVENTNAME" ]; then + echo "Specify EVENTNAME env-var" + exit 2 + fi -# Create initial image without title/speaker info -awk '{gsub(/SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER/, ""); gsub(/TITLE[123]/, ""); print}' ${SOURCEFILE} > frameclear.svg + if [ -z "$SPEAKERNAME" ]; then + echo "Specify SPEAKERNAME env-var" + exit 3 + fi -# Fade this image in from 100% transparent to 'normal' -echo "Generate fade-in-from-black sequence" -for i in $(seq 100 -3 0) -do - echo "Generate frame ${FRAMENUM}" - ${CONV} -colorize ${i}% frameclear.svg frame-${FRAMENUM}.webp + if [ -z "$TITLE1" ] || [ -z "$TITLE2" ] || [ -z "$TITLE3" ]; then + echo "Specify TITLE1/TITLE2/TITLE3 env-vars" + exit 4 + fi +} + +# Setup project directory +setup_project_dir() { + mkdir -p "${PROJDIR}" || { echo "Failed to create project directory"; exit 1; } + cd "${PROJDIR}" || { echo "Failed to change to project directory"; exit 1; } +} + +# Generate frames +generate_frames() { + echo "Generate fade-in-from-black sequence" + for i in $(seq 100 -3 0); do + echo "Generate frame ${FRAMENUM}" + ${CONV} -colorize ${i}% frameclear.svg "frame-${FRAMENUM}.webp" + ((FRAMENUM++)) + done + + echo "Add speakername sequence" + SLEN=${#SPEAKERNAME} + for i in $(seq 0 ${SLEN}); do + echo "Generate frame ${FRAMENUM}" + SN="${SPEAKERNAME:0:i}" + awk -v sn="$SN" '{gsub(/TITLE[123]/, ""); gsub(/SPEAKERSPEAKERSPEAKERSPEAKER/, sn); print}' ${SOURCEFILE} > "${PROJDIR}/frame-${FRAMENUM}.svg" + ${CONV} "frame-${FRAMENUM}.svg" "frame-${FRAMENUM}.webp" + ((FRAMENUM++)) + done + + echo "Add title sequence" + for i in $(seq 0 40); do + echo "Generate frame ${FRAMENUM}" + T1="${TITLE1:0:i}" + T2="${TITLE2:0:i}" + T3="${TITLE3:0:i}" + awk -v t1="$T1" -v t2="$T2" -v t3="$T3" -v sn="$SN" '{gsub(/TITLE1/, t1); gsub(/TITLE2/, t2); gsub(/TITLE3/, t3); gsub(/SPEAKERSPEAKERSPEAKERSPEAKER/, sn); print}' ${SOURCEFILE} > "${PROJDIR}/frame-${FRAMENUM}.svg" + ${CONV} "frame-${FRAMENUM}.svg" "frame-${FRAMENUM}.webp" + ((FRAMENUM++)) + done + + echo "Generate completed title" + awk -v t1="$TITLE1" -v t2="$TITLE2" -v t3="$TITLE3" -v sn="$SPEAKERNAME" '{gsub(/TITLE1/, t1); gsub(/TITLE2/, t2); gsub(/TITLE3/, t3); gsub(/SPEAKERSPEAKERSPEAKERSPEAKER/, sn); print}' ${SOURCEFILE} > "${PROJDIR}/frame-${FRAMENUM}.svg" + ${CONV} "frame-${FRAMENUM}.svg" "frame-${FRAMENUM}.webp" + LASTFRAME=$FRAMENUM ((FRAMENUM++)) -done -echo "Add speakername sequence" -SLEN=${#SPEAKERNAME} # Length of name -# Copy a new frame, and fill in the speaker name 1 character at a time -for i in $(seq 0 ${SLEN}) -do - echo "Generate frame ${FRAMENUM}" - SN="${SPEAKERNAME:0:i}" - awk -v sn="$SN" '{gsub(/TITLE[123]/, ""); gsub(/SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER/, sn); print}' ${SOURCEFILE} > ${PROJDIR}/frame-${FRAMENUM}.svg - ${CONV} frame-${FRAMENUM}.svg frame-${FRAMENUM}.webp - ((FRAMENUM++)) -done + for i in $(seq 0 1 100); do + echo "Duplicating frame ${FRAMENUM}" + cp "frame-${LASTFRAME}.webp" "frame-${FRAMENUM}.webp" + ((FRAMENUM++)) + done -echo "Add title sequence" -# With speakername, now add the title, 1 char (per line) at a time -for i in $(seq 0 40) -do - echo "Generate frame ${FRAMENUM}" - T1="${TITLE1:0:i}" # Substring, first i characters - T2="${TITLE2:0:i}" - T3="${TITLE3:0:i}" - awk -v t1="$T1" -v t2="$T2" -v t3="$T3" -v sn="$SN" '{gsub(/TITLE1/, t1); gsub(/TITLE2/, t2); gsub(/TITLE3/, t3); gsub(/SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER/, sn); print}' ${SOURCEFILE} > ${PROJDIR}/frame-${FRAMENUM}.svg - ${CONV} frame-${FRAMENUM}.svg frame-${FRAMENUM}.webp - ((FRAMENUM++)) -done + echo "Generate fade-out-sequence" + for i in $(seq 0 3 100); do + echo "Generate frame ${FRAMENUM}" + ${CONV} -colorize ${i}% "frame-${LASTFRAME}.svg" "frame-${FRAMENUM}.webp" + ((FRAMENUM++)) + done +} -# Generate final frame, with full speakername + title -echo "Generate completed title" -awk -v t1="$TITLE1" -v t2="$TITLE2" -v t3="$TITLE3" -v sn="$SPEAKERNAME" '{gsub(/TITLE1/, t1); gsub(/TITLE2/, t2); gsub(/TITLE3/, t3); gsub(/SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER/, sn); print}' ${SOURCEFILE} > ${PROJDIR}/frame-${FRAMENUM}.svg -${CONV} frame-${FRAMENUM}.svg frame-${FRAMENUM}.webp -LASTFRAME=$FRAMENUM -((FRAMENUM++)) +# Render video +render_video() { + echo "Rendering to video" + ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -framerate 25 -i frame-%d.webp -c:a aac -c:v libx264 -shortest -profile:v baseline -pix_fmt yuv420p -colorspace:v 'bt709' -color_primaries:v 'bt709' -color_trc:v 'bt709' -color_range:v 'tv' -r 30 "${VIDEODIR}/${PROJECT}-x264.mkv" +} -# Now copy the rendered output of the last frame a few more times so we can read it before the video ends -for i in $(seq 0 1 100) -do - echo "Duplicating frame ${FRAMENUM}" - cp frame-${LASTFRAME}.webp frame-${FRAMENUM}.webp - ((FRAMENUM++)) -done +# Cleanup temporary files +cleanup() { + echo "Cleaning up temporary files" + rm -rf "${PROJDIR}" +} -# Fade this image out over 100 frames back to the normal view -echo "Generate fade-out-sequence" -for i in $(seq 0 3 100) -do - echo "Generate frame ${FRAMENUM}" - ${CONV} -colorize ${i}% frame-${LASTFRAME}.svg frame-${FRAMENUM}.webp - ((FRAMENUM++)) -done +# Main execution +main() { + validate_input + setup_project_dir -echo "Rendering to video" -ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -framerate 25 -i frame-%d.webp -c:a aac -c:v libx264 -shortest -profile:v baseline -pix_fmt yuv420p -colorspace:v 'bt709' -color_primaries:v 'bt709' -color_trc:v 'bt709' -color_range:v 'tv' -r 30 ${VIDEODIR}/${PROJECT}-x264.mkv + # Customize template to this event from base template + awk -v eventname="$EVENTNAME" '{gsub(/EVENTNAMEEVENTNAME/, eventname); print}' "${SOURCEDIR}/${BASETEMPLATE}" > ${SOURCEFILE} + + # Create initial image without title/speaker info + awk '{gsub(/SPEAKERSPEAKERSPEAKERSPEAKER/, ""); gsub(/TITLE[123]/, ""); print}' ${SOURCEFILE} > frameclear.svg + + generate_frames + render_video + cleanup +} + +main diff --git a/nluug-title-template.svg b/nluug-title-template.svg index 846e9ec..1502549 100644 --- a/nluug-title-template.svg +++ b/nluug-title-template.svg @@ -48,12 +48,12 @@ inkscape:deskcolor="#000000" showgrid="false" inkscape:zoom="0.40174673" - inkscape:cx="438.08695" - inkscape:cy="311.1413" - inkscape:window-width="2304" - inkscape:window-height="1347" + inkscape:cx="301.18478" + inkscape:cy="312.38587" + inkscape:window-width="2880" + inkscape:window-height="1699" inkscape:window-x="0" - inkscape:window-y="0" + inkscape:window-y="64" inkscape:window-maximized="1" inkscape:current-layer="g61" /> EVENTNAMEEVENTNAME + id="tspan301">EVENTNAMEEVENTNAME SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER + id="tspan307">SPEAKERSPEAKERSPEAKERSPEAKER TITLE1 + id="tspan309">TITLE1 TITLE2 + id="tspan311">TITLE2 TITLE3 + id="tspan313">TITLE3