Created
March 11, 2023 16:23
-
-
Save Voldrix/a66cb5c66dfae00e3f1e931e7a368adf to your computer and use it in GitHub Desktop.
Generate .BIF media preview thumbnails (trick play)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#Generate .BIF media preview thumbnails | |
#REQUIRES: ffmpeg, mediainfo, and roku's biftool | |
if [ -z "$1" ]; then echo -e "\nGenerate .BIF media preview thumbnails\nFiles are stored in source folder\n\nUsage: ${0##*/} [video files/directories...] <Absolute or Relative paths. Recursive>\n";exit 1;fi | |
tmpdir="/tmp/bifgen" | |
[ -d "$tmpdir" ] && rm -f "$tmpdir"/* || mkdir -p "$tmpdir" | |
IFS=$'\n' | |
wd="$(pwd)" | |
cd /tmp/ | |
new=0 | |
#Store bif files in separate directory tree. The directory tree will match the folder structure of the input files, but with a different directory prefix | |
#e.g. /dir/vids/* => /bif/* | |
#disabled if null, .bif in source folder | |
indir="" | |
outdir="" | |
for z;do | |
#Input parameter is a relative or absolute path | |
[[ "$z" =~ ^/ ]] || z="$wd/$z" | |
[ -e "$z" ] || continue | |
[ -d "$z" ] && files=($(find "$z" -type f -regextype sed -regex ".*\.[mM][kKpP][vV4]")) | |
[ -f "$z" ] && files=("$z") | |
for i in "${files[@]}";do | |
if [[ -n "$indir" && "$i" =~ ^"$indir" ]]; then | |
outd=$(sed "s:^${indir}:${outdir}:" <<< ${i%/*}) | |
[ -d "$outd" ] || (mkdir -p "$outd" && echo -e "\e[35mMKDIR: $outd\e[39m") | |
out="${outd}/${i##*/}.bif" | |
else | |
out="${i}.bif" | |
fi | |
#bif already exists, don't overwrite | |
if [ -f "$out" ];then | |
echo -e "\e[33mSKIP: $out\e[39m" | |
continue | |
fi | |
duration=$(mediainfo --Inform="General;%Duration%" "$i") | |
separation=10 #1-15min 1-90frames | |
[ -n "$duration" ] && [ "$duration" -gt 900000 ] && separation=12 #15-70min 90-350frames (150frames/30min) | |
[ -n "$duration" ] && [ "$duration" -gt 4200000 ] && separation=22 #70min-2hr 190-327frames | |
[ -n "$duration" ] && [ "$duration" -gt 7200000 ] && separation=26 #2hr+ 277frames+ | |
#Do not select frames at a fixed time interval, as the timecode will drift. | |
#BIF does not contain timecodes, you have to calculate them by multiplying the framerate/separation by the frame number. | |
#Selecting the first frame after the modulo of the separation time rolls over to zero, you ensure the frame number multiplication will line up with the timecode. | |
ffmpeg -nostdin -i "$i" -vsync vfr -vf "select=gt(ld(1)\,st(1\,mod(t\,${separation})))+isnan(prev_selected_t),scale=240:160:force_original_aspect_ratio=decrease:flags=bicubic:sws_dither=none" -c:v mjpeg -qscale:v 4 -v 0 -y -f image2 "${tmpdir}/%08d.jpg" | |
if [ $? -ne 0 ];then | |
rm -f "${tmpdir}"/* | |
continue | |
fi | |
#ffmpeg's image sequence output starts at number one. We must shift every image down one to start at zero in order to line up with the timecode | |
j="${tmpdir}/00000000.jpg" | |
for f in "$tmpdir"/*; do | |
mv "$f" "$j" | |
j="$f" | |
done | |
#Make sure biftool is in $PATH, or add absolute path to it | |
biftool -t ${separation}000 "${tmpdir}" | |
if [ -f "${tmpdir##*/}.bif" ]; then | |
mv "${tmpdir##*/}.bif" "$out" && echo -e "\e[32m$out\e[39m" && chmod 664 "$out" || echo -e "\e[31mFAILED: $out\e[39m" | |
((new++)) | |
else | |
echo -e "\e[31mFAILED: $i\e[39m" | |
fi | |
rm -f "${tmpdir}"/* | |
done | |
done | |
rmdir "$tmpdir" | |
echo "new bif created: $new" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment