Cleanup script, use functions
This commit is contained in:
parent
d7102a274d
commit
28c419e1d5
2 changed files with 114 additions and 101 deletions
189
generate.sh
189
generate.sh
|
@ -1,108 +1,121 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Configuration
|
||||||
SOURCEDIR=$(pwd)
|
SOURCEDIR=$(pwd)
|
||||||
PROJECT=$1
|
PROJECT=$1
|
||||||
BASETEMPLATE="nluug-title-template.svg"
|
BASETEMPLATE="nluug-title-template.svg"
|
||||||
SOURCEFILE="event.svg"
|
SOURCEFILE="event.svg"
|
||||||
VIDEODIR=${SOURCEDIR}/output
|
VIDEODIR="${SOURCEDIR}/output"
|
||||||
PROJDIR=/tmp/nluug-intro-${PROJECT}
|
PROJDIR="/tmp/nluug-intro-${PROJECT}"
|
||||||
|
|
||||||
if [ -z "${PROJECT}" ]; then
|
|
||||||
echo "Usage: $0 <project>"
|
|
||||||
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"
|
|
||||||
|
|
||||||
CONV="convert -background black -fill black -alpha off"
|
CONV="convert -background black -fill black -alpha off"
|
||||||
FRAMENUM=0
|
FRAMENUM=0
|
||||||
|
|
||||||
# Make project directory
|
# Validate input
|
||||||
mkdir -p ${PROJDIR}; cd ${PROJDIR}
|
validate_input() {
|
||||||
|
if [ -z "${PROJECT}" ]; then
|
||||||
|
echo "Usage: $0 <project>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Customize template to this event from base template
|
if [ -z "$EVENTNAME" ]; then
|
||||||
awk -v eventname="$EVENTNAME" '{gsub(/EVENTNAMEEVENTNAME/, eventname); print}' "${SOURCEDIR}/${BASETEMPLATE}" > ${SOURCEFILE}
|
echo "Specify EVENTNAME env-var"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
# Create initial image without title/speaker info
|
if [ -z "$SPEAKERNAME" ]; then
|
||||||
awk '{gsub(/SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER/, ""); gsub(/TITLE[123]/, ""); print}' ${SOURCEFILE} > frameclear.svg
|
echo "Specify SPEAKERNAME env-var"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
# Fade this image in from 100% transparent to 'normal'
|
if [ -z "$TITLE1" ] || [ -z "$TITLE2" ] || [ -z "$TITLE3" ]; then
|
||||||
echo "Generate fade-in-from-black sequence"
|
echo "Specify TITLE1/TITLE2/TITLE3 env-vars"
|
||||||
for i in $(seq 100 -3 0)
|
exit 4
|
||||||
do
|
fi
|
||||||
echo "Generate frame ${FRAMENUM}"
|
}
|
||||||
${CONV} -colorize ${i}% frameclear.svg frame-${FRAMENUM}.webp
|
|
||||||
|
# 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++))
|
((FRAMENUM++))
|
||||||
done
|
|
||||||
|
|
||||||
echo "Add speakername sequence"
|
for i in $(seq 0 1 100); do
|
||||||
SLEN=${#SPEAKERNAME} # Length of name
|
echo "Duplicating frame ${FRAMENUM}"
|
||||||
# Copy a new frame, and fill in the speaker name 1 character at a time
|
cp "frame-${LASTFRAME}.webp" "frame-${FRAMENUM}.webp"
|
||||||
for i in $(seq 0 ${SLEN})
|
((FRAMENUM++))
|
||||||
do
|
done
|
||||||
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
|
|
||||||
|
|
||||||
echo "Add title sequence"
|
echo "Generate fade-out-sequence"
|
||||||
# With speakername, now add the title, 1 char (per line) at a time
|
for i in $(seq 0 3 100); do
|
||||||
for i in $(seq 0 40)
|
echo "Generate frame ${FRAMENUM}"
|
||||||
do
|
${CONV} -colorize ${i}% "frame-${LASTFRAME}.svg" "frame-${FRAMENUM}.webp"
|
||||||
echo "Generate frame ${FRAMENUM}"
|
((FRAMENUM++))
|
||||||
T1="${TITLE1:0:i}" # Substring, first i characters
|
done
|
||||||
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
|
|
||||||
|
|
||||||
# Generate final frame, with full speakername + title
|
# Render video
|
||||||
echo "Generate completed title"
|
render_video() {
|
||||||
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
|
echo "Rendering to video"
|
||||||
${CONV} frame-${FRAMENUM}.svg frame-${FRAMENUM}.webp
|
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"
|
||||||
LASTFRAME=$FRAMENUM
|
}
|
||||||
((FRAMENUM++))
|
|
||||||
|
|
||||||
# Now copy the rendered output of the last frame a few more times so we can read it before the video ends
|
# Cleanup temporary files
|
||||||
for i in $(seq 0 1 100)
|
cleanup() {
|
||||||
do
|
echo "Cleaning up temporary files"
|
||||||
echo "Duplicating frame ${FRAMENUM}"
|
rm -rf "${PROJDIR}"
|
||||||
cp frame-${LASTFRAME}.webp frame-${FRAMENUM}.webp
|
}
|
||||||
((FRAMENUM++))
|
|
||||||
done
|
|
||||||
|
|
||||||
# Fade this image out over 100 frames back to the normal view
|
# Main execution
|
||||||
echo "Generate fade-out-sequence"
|
main() {
|
||||||
for i in $(seq 0 3 100)
|
validate_input
|
||||||
do
|
setup_project_dir
|
||||||
echo "Generate frame ${FRAMENUM}"
|
|
||||||
${CONV} -colorize ${i}% frame-${LASTFRAME}.svg frame-${FRAMENUM}.webp
|
|
||||||
((FRAMENUM++))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Rendering to video"
|
# Customize template to this event from base template
|
||||||
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
|
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
|
||||||
|
|
||||||
|
|
|
@ -48,12 +48,12 @@
|
||||||
inkscape:deskcolor="#000000"
|
inkscape:deskcolor="#000000"
|
||||||
showgrid="false"
|
showgrid="false"
|
||||||
inkscape:zoom="0.40174673"
|
inkscape:zoom="0.40174673"
|
||||||
inkscape:cx="438.08695"
|
inkscape:cx="301.18478"
|
||||||
inkscape:cy="311.1413"
|
inkscape:cy="312.38587"
|
||||||
inkscape:window-width="2304"
|
inkscape:window-width="2880"
|
||||||
inkscape:window-height="1347"
|
inkscape:window-height="1699"
|
||||||
inkscape:window-x="0"
|
inkscape:window-x="0"
|
||||||
inkscape:window-y="0"
|
inkscape:window-y="64"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="1"
|
||||||
inkscape:current-layer="g61" />
|
inkscape:current-layer="g61" />
|
||||||
<g
|
<g
|
||||||
|
@ -71,9 +71,9 @@
|
||||||
transform="matrix(0.64500845,0,0,0.64500845,533.85281,-45.33011)"><tspan
|
transform="matrix(0.64500845,0,0,0.64500845,533.85281,-45.33011)"><tspan
|
||||||
x="107.36523"
|
x="107.36523"
|
||||||
y="802.76728"
|
y="802.76728"
|
||||||
id="tspan300"><tspan
|
id="tspan303"><tspan
|
||||||
dx="0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00010681152"
|
dx="0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00010681152"
|
||||||
id="tspan298">EVENTNAMEEVENTNAME</tspan></tspan></text>
|
id="tspan301">EVENTNAMEEVENTNAME</tspan></tspan></text>
|
||||||
<text
|
<text
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
id="text281-5"
|
id="text281-5"
|
||||||
|
@ -81,21 +81,21 @@
|
||||||
transform="matrix(0.64500845,0,0,0.64500845,3.9182847,183.75561)"><tspan
|
transform="matrix(0.64500845,0,0,0.64500845,3.9182847,183.75561)"><tspan
|
||||||
x="107.36523"
|
x="107.36523"
|
||||||
y="802.76728"
|
y="802.76728"
|
||||||
id="tspan304"><tspan
|
id="tspan307"><tspan
|
||||||
dx="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00010681152 0 0 0 0 0 -0.0001373291 0 0.00019836426 0 0 0 0 0.00010681152"
|
dx="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00010681152 0 0 0 0 0 -0.0001373291"
|
||||||
id="tspan302">SPEAKERSPEAKERSPEAKERSPEAKERSPEAKER
|
id="tspan305">SPEAKERSPEAKERSPEAKERSPEAKER
|
||||||
</tspan></tspan><tspan
|
</tspan></tspan><tspan
|
||||||
x="107.36523"
|
x="107.36523"
|
||||||
y="952.76728"
|
y="952.76728"
|
||||||
id="tspan306">TITLE1
|
id="tspan309">TITLE1
|
||||||
</tspan><tspan
|
</tspan><tspan
|
||||||
x="107.36523"
|
x="107.36523"
|
||||||
y="1102.7673"
|
y="1102.7673"
|
||||||
id="tspan308">TITLE2
|
id="tspan311">TITLE2
|
||||||
</tspan><tspan
|
</tspan><tspan
|
||||||
x="107.36523"
|
x="107.36523"
|
||||||
y="1252.7673"
|
y="1252.7673"
|
||||||
id="tspan310">TITLE3
|
id="tspan313">TITLE3
|
||||||
</tspan></text>
|
</tspan></text>
|
||||||
<image
|
<image
|
||||||
width="1914.1414"
|
width="1914.1414"
|
||||||
|
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Loading…
Add table
Add a link
Reference in a new issue