Skip to content

Instantly share code, notes, and snippets.

@bonelifer
Forked from dzogrim/vignettage_kodi.sh
Created October 2, 2025 20:25
Show Gist options
  • Save bonelifer/58cee542d2876a70492d46f0a7fa0a35 to your computer and use it in GitHub Desktop.
Save bonelifer/58cee542d2876a70492d46f0a7fa0a35 to your computer and use it in GitHub Desktop.
Kodi video "poster" automatic generator for series episode and so on
#!/usr/bin/env bash
# _ __ _ _
# | |/ /___ __| (_)
# | ' </ _ \/ _` | |
# |_|\_\___/\__,_|_|
#
#########################################
# Kodi video "poster" automatic generator
# for series episode and so on ...
#########################################
# Set defaults
ROOTPATH="$( pwd )"
INFORMAT="avi"
TIMECODE="00:02:01"
FORCE=0
# Help
displayUsage()
{
NAME="$( basename "${0}" )"
local CODE="${1}"
printf "\nBy default, this program run with all AVI files in current directory"
printf "\nand generates screenshot from minute 2'00. ffmpeg is required on the system."
printf "\nThis behavior can be changed with some valid arguments as described below."
printf "\n\nUsage: %s [arguments] " "$NAME"
printf "\n --format=avi (defaults! but you can specify another format"
printf "\n like: mp4, mov, m4v, mkv ...)"
printf "\n --twomin (defaults!)"
printf "\n --onemin (will generate screenshot from minute 1)"
printf "\n --starts (will generate screenshot from second 1)"
printf "\n --forced (will force screenshot regeneration)\n"
printf "\nDefaults : %s " "$NAME"
printf "\nExample 1: %s --format=mkv" "$NAME"
printf "\nExample 2: %s --format=avi --starts --forced\n\n" "$NAME"
exit "${CODE}"
}
checkTools()
{
local misstools
for entry in "${@}"
do
if ! command -v "${entry}" >/dev/null 2>&1
then
misstools="${misstools} ${entry}"
fi
done
[ -z "${misstools}" ] \
&& return \
|| {
printf "\n[ERROR] Required tools could not be found: \n %s\n" "${misstools}"
exit 1
}
}
# Make sure required tools are installed on system
checkTools ffmpeg
while [[ $# -gt 0 ]] && [[ "$1" == "--"* ]] ;
do
opt="$1";
# Expose next argument:
shift;
case "$opt" in
"--" ) break 2;;
"--format="* )
INFORMAT="${opt#*=}";;
"--forced" )
# Force screenshot regeneration:
FORCE=1;;
"--starts" )
# Timecode change:
TIMECODE="00:00:01";;
"--onemin" )
# Timecode change:
TIMECODE="00:01:01";;
"--twomin" )
# Timecode change:
TIMECODE="00:02:01";;
"--help" )
# Usage:
displayUsage 0 ;;
*) printf "\nInvalid option supplied!\n" >&2 ;
# Usage on invalid argument error:
displayUsage 1 ;;
esac
done
while IFS= read -r -d '' file; do
# Ignore existing video file and poster file couple:
if [[ ! -f "${file%.$INFORMAT}-poster.jpg" ]]; then
# Generates a screenshot
ffmpeg -loglevel quiet -nostdin -ss ${TIMECODE} -i "${file}" -vframes 1 -q:v 2 "${file%.$INFORMAT}-poster.jpg"
# Override if poster exists but regeneration are required:
elif [[ -f "${file%.$INFORMAT}-poster.jpg" ]] && [[ ${FORCE} -gt 0 ]]; then
# Removes existing screenshot
rm "${file%.$INFORMAT}-poster.jpg"
# Generates new screenshot after deletion
ffmpeg -loglevel quiet -nostdin -ss ${TIMECODE} -i "${file}" -vframes 1 -q:v 2 "${file%.$INFORMAT}-poster.jpg"
fi
done < <( find "${ROOTPATH}" -mindepth 1 -maxdepth 1 -type f -iname "*.${INFORMAT}" -print0 )
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment