-
-
Save achesco/4dc2ebf13378a0a61fc26c7fe01f539e to your computer and use it in GitHub Desktop.
# Splits video to separate scenes files | |
# Inspired by https://stackoverflow.com/a/38205105 | |
#!/bin/bash | |
file="" | |
out="./" | |
diff=0.4 | |
bitrate="512k" | |
trim=0 | |
stripaudio="" | |
usage () { | |
echo "Usage: $(basename $0) [[[-o folder] [-d ratio]] | [-h]] -f file.mp4" | |
echo | |
echo "Options:" | |
echo "-f, --file Input file" | |
echo "-o, --out Outpup files folder path, default" | |
echo " to current folder" | |
echo "-d, --diff Number from 0 to 1, default to 0.4." | |
echo " Scene change difference factor" | |
echo "-b, --bitrate Bitrate to encode parts, default to 512k" | |
echo "-t, --trim Trim last given seconds number, default 0" | |
echo "-sa, --strip-audio Strip audio" | |
echo "-h, --help Display this help message" | |
echo | |
echo "Example: split.sh -d 0.5 -o /tmp/parts -f file.mp4" | |
echo "Splits file.mp4 file to scenes with change more than 0.5" | |
echo "and saves output parts to /tmp/parts folder" | |
} | |
if [ "$1" = "" ]; then | |
usage | |
fi | |
while [ "$1" != "" ]; do | |
case $1 in | |
-f | --file ) | |
shift | |
file=$1 | |
;; | |
-d | --diff ) | |
shift | |
diff=$1 | |
;; | |
-o | --out ) | |
shift | |
out=$1 | |
;; | |
-b | --bitrate ) | |
shift | |
bitrate=$1 | |
;; | |
-t | --trim ) | |
shift | |
trim=$1 | |
;; | |
-sa | --strip-audio ) | |
stripaudio="-an" | |
;; | |
-h | --help ) | |
usage | |
exit | |
;; | |
* ) | |
usage | |
exit 1 | |
esac | |
shift | |
done | |
cut_part () { | |
duration_flag="" | |
if [ "$3" != "" ]; then | |
duration_flag="-t" | |
fi | |
ffmpeg -loglevel error -hide_banner -ss $1 $duration_flag $3 -i $file \ | |
-vcodec libx264 -movflags faststart -b $bitrate $stripaudio \ | |
-y $out/`printf "%04d_%s" $2 $filename` < /dev/null | |
} | |
filename=`basename $file` | |
mkdir -p $out | |
timefrom=0 | |
i=1 | |
while read -r timestamp; do | |
duration=`bc <<< "$timestamp-$timefrom-$trim" | awk '{printf "%f", $0}'` | |
cut_part $timefrom $i $duration | |
timefrom=$timestamp | |
i=`expr $i + 1` | |
done < <( | |
ffmpeg -i $file -filter:v "select='gt(scene,$diff)',showinfo" -f null - 2>&1 | \ | |
grep Parsed_showinfo | grep pts_time:[0-9.]* -o | grep "[0-9]*\.[0-9]*" -o | |
) | |
if [ $timefrom != 0 ]; then | |
cut_part $timefrom $i | |
fi |
Sorry for bothering with another comment. I needed a script like this but the scene detection from ffmpeg didn't work in my use case. Gladly, in my videos, I have fully black screens so I touched up the script and created a version that would detect these and split without encoding (remuxing). I also didn't want to bother fixing the output to feed it to the loop so I ended up writing two log files to parse. https://gist.github.com/david-treblig/e26186b8f4c6795b19c043fffb6f9861
@davidwebca the link you posted is borked. is there a new location?
Oh lord, must be because I changed my username. Github redirects repos but not gists... interesting 🤔 Well, here you go: https://gist.github.com/davidwebca/e26186b8f4c6795b19c043fffb6f9861
I forked:
- following some ShellCheck advice
- reading bitrate from original file
- being able to split files with spaces in their name
- using Apple Silicon hardware for some speedup
https://gist.github.com/nielsbom/c86c504fa5fd61ae9530caec654c6ae6
Hi! Just checking in if you ended up with a working solution for this script? I'm very interested in it. 👀