Last active
September 26, 2021 10:01
-
-
Save FarisHijazi/4ba8d9768eddc6f218ecd21824c24909 to your computer and use it in GitHub Desktop.
segment videos into video or GIF segments using ffmpeg
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 | |
# https://gist.github.com/FarisHijazi/4ba8d9768eddc6f218ecd21824c24909 | |
#TODO: fix directory naming, name it something related to the file | |
# argparsing from: https://stackoverflow.com/a/39376824/7771202 | |
# usage function | |
function usage() | |
{ | |
cat << HEREDOC | |
Usage: $progname [--num NUM] [-t|--segduration INT] [--gif] [--yes] [--verbose] [--dry-run] | |
optional arguments: | |
-h, --help show this help message and exit | |
-n, --num NUM increase this value to make it output less of the video (default: 20) | |
-t, --segduration NUM segment/gif duration in seconds (default: 3) | |
-g, --gif create gifs instead of video segments? | |
-y, --yes overwrite files | |
-v, --verbose increase the verbosity of the bash script | |
to apply on multiple videos in a folder | |
find /path/to/videofolder/ -name "*.mp4" -not -name "*.seg.*" | xargs -P \$(nproc --all) -I{} sh -c 'sh vidsplit.sh {} --gif --verbose' | |
HEREDOC | |
} | |
# initialize variables | |
progname=$(basename $0) | |
verbose=0 | |
dryrun=0 | |
gif=0 | |
num_str=40 | |
segduration=3 | |
yes=0 | |
# use getopt and store the output into $OPTS | |
# note the use of -o for the short options, --long for the long name options | |
# and a : for any option that takes a parameter | |
OPTS=$(getopt -a -o "hn:t:g,y,v" --long "help,num:,segduration:,gif,yes,verbose,dry-run" -n "$progname" -- "$@") | |
if [ $? != 0 ] ; then echo "Error in command line arguments." >&2 ; usage; exit 1 ; fi | |
eval set -- "$OPTS" | |
while true; do | |
# uncomment the next line to see how shift is working | |
# echo "\$1:\"$1\" \$2:\"$2\"" | |
case "$1" in | |
-h | --help ) usage; exit; ;; | |
-n | --num ) num_str="$2"; shift 2 ;; | |
-t | --segduration ) segduration="$2"; shift 2 ;; | |
-g | --gif ) gif=$((gif + 1)); shift ;; | |
-y | --yes ) yes=$((yes + 1)); shift ;; | |
-v | --verbose ) verbose=$((verbose + 1)); shift ;; | |
-- ) shift; break ;; | |
* ) break ;; | |
esac | |
done | |
input=$1 | |
if [ -z "$input" ]; then | |
echo "infile not passed" | |
usage | |
exit 1 | |
fi | |
if [ ! -f "$input" ]; then | |
echo "Cannot access '$input': No such file or directory" | |
exit 1 | |
fi | |
# echo dirname: $(dirname "$input") | |
cd "$(dirname $input)" # || echo "unable to cd" && exit 1 | |
input=$(basename "$input") | |
fullduration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$input") | |
segduration=3 | |
skipsec=$(echo "$fullduration/($segduration*$num_str)" | bc) | |
if (( $verbose > 0 )); then | |
# print out all the parameters we read in | |
cat <<EOM | |
1=$1 | |
num=$num_str | |
time=$segduration | |
gif=$gif | |
yes=$yes | |
skipsec=$skipsec | |
verbose=$verbose | |
EOM | |
fi | |
if (( $yes > 0 )); then | |
yes=y | |
else | |
yes=n | |
fi | |
if (( $gif > 0 )); then | |
seq $skipsec | xargs -I{} sh -c "echo {}*$num_str*$segduration|bc -l" -- {} | xargs -P $(nproc --all) -I{} sh -c "mkdir -p gifs; ffmpeg -hide_banner -loglevel error -$yes -ss {} -t $segduration -i \"$input\" -vf \"fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" -loop 0 gifs/\"${input%.*}.{}.seg.gif\" && echo \"${input%.*}.{}.seg.gif\"" -- {} | tqdm --desc "segmenting video" --total $skipsec --unit gif >/dev/null | |
else | |
seq $skipsec | xargs -I{} sh -c "echo {}*$num_str*$segduration|bc -l" -- {} | xargs -P $(nproc --all) -I{} sh -c "mkdir -p segments; ffmpeg -hide_banner -loglevel error -$yes -ss {} -t $segduration -i \"$input\" -loop 0 segments/\"${input%.*}.{}.seg.mp4\" && echo \"${input%.*}.{}.seg.mp4\"" -- {} | tqdm --desc "segmenting video" --total $skipsec --unit file >/dev/null | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment