Files

90 lines
1.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
die() {
echo "$*" >&2
exit 1
}
usage() {
cat <<'EOF' >&2
Usage: convert-to-video.sh /path/to/audio.file
Creates a slideshow video from stormux images and the provided audio.
EOF
exit 1
}
require_commands() {
for cmd in "$@"; do
command -v "$cmd" >/dev/null 2>&1 || die "Missing dependency: $cmd"
done
}
locate_images() {
local candidate="."
local have_all=true
for i in 1 2 3 4 5; do
[ -f "$candidate/stormux${i}.png" ] || have_all=false
done
if [ "$have_all" = true ]; then
printf '%s\n' "$candidate"
return
fi
candidate="/usr/share/stormux/slideshow"
for i in 1 2 3 4 5; do
[ -f "$candidate/stormux${i}.png" ] || die "Missing image: $candidate/stormux${i}.png"
done
printf '%s\n' "$candidate"
}
detect_container() {
local audio_file="$1"
local codec
codec="$(ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of csv=p=0 "$audio_file" || true)"
case "$codec" in
aac|mp3) echo "mp4" ;;
*) echo "mkv" ;;
esac
}
build_video() {
local audio_file="$1"
local image_dir="$2"
local container="$3"
local output_filename="$4"
local output_dir="$HOME/Videos"
mkdir -p "$output_dir"
ffmpeg -y \
-stream_loop -1 -framerate 1/35 -start_number 1 -i "$image_dir/stormux%d.png" \
-i "$audio_file" \
-map 0:v:0 -map 1:a:0 \
-c:v libx264 -crf 18 -preset veryfast -r 30 -pix_fmt yuv420p \
-c:a copy \
-shortest \
"$output_dir/${output_filename##*/}"
}
[ "$#" -eq 1 ] || usage
audio="$1"
[ -f "$audio" ] || die "Audio file not found: $audio"
require_commands ffmpeg ffprobe
image_dir="$(locate_images)"
container="$(detect_container "$audio")"
base="$(basename "$audio")"
name="${base%.*}"
output="${name}.${container}"
build_video "$audio" "$image_dir" "$container" "$output"
echo "Wrote $HOME/Videos/$output"