#!/bin/bash # set -Eeuo pipefail # Splits video to separate scenes files # Source: https://gist.github.com/achesco/4dc2ebf13378a0a61fc26c7fe01f539e # Inspired by https://stackoverflow.com/a/38205105 # The "-c:v h264_videotoolbox \" argument makes it work faster on Apple Silicon # computers. # ❗The bitrate argument is overriden in this version, we look at the original bitrate. file="" out="./" diff=0.4 bitrate="512k" trim=0 stripaudio="" script_name=$(basename "$0") usage () { echo "Usage: $script_name [[[-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 output_file="$out"/$(printf "%04d_%s" "$2" "$filename_without_spaces") echo "Creating ${output_file}" ffmpeg \ -loglevel error \ -hide_banner \ -ss "$1" \ $duration_flag "$3" \ -i "$file" \ -vcodec libx264 \ -c:v h264_videotoolbox \ -movflags faststart \ -b "$bitrate_ffprobe" \ $stripaudio \ -y "$output_file" < /dev/null } filename=$(basename "$file") filename_without_spaces="${filename// /_}" bitrate_ffprobe=$(ffprobe -v quiet -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1 "$filename" | cut -d"=" -f 2-) mkdir -p "$out" timefrom=0 i=1 echo "finding parts..." while read -r timestamp; do duration=$(bc <<< "$timestamp-$timefrom-$trim" | awk '{printf "%f", $0}') cut_part "$timefrom" "$i" "$duration" timefrom=$timestamp echo from "$timefrom" for "$duration" seconds i=$(( i + 1)) done < <( ffmpeg -i "$file" -c:v h264_videotoolbox -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