Sometimes, I need to post longer videos on social media that are limited to a few minutes in duration. Manually splitting a longer video into segments is for amateurs.
The script below takes two command-line arguments: -f [/file_path/file_name.mp4]
and -d [maximum_segment_duration_minutes]
The script will add small labels in the top left-hand corner of each resulting video segment indicating the segment’s number in the sequence. Comments in the script explain how to disable this feature if you don’t need it.
The trick to having this script work is having a version of ffmpeg
that supports libharfbuzz
and a few other features. You can read more about compiling ffmpeg
from source here.
The script is below, and you can also download it from my GitHub repo.
The script
#!/bin/bash
random="${RANDOM}"
font="/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
if [ ! -f "${font}" ]; then
echo "Font file not found. Please update the font path in the script." >&2
exit 1
fi
# Function to convert seconds to HH:MM:SS format
convert_to_hms() {
local total_seconds=$1
printf "%02d:%02d:%02d" $(("${total_seconds}"/3600)) $(("${total_seconds}"%3600/60)) $(("${total_seconds}"%60))
}
# Parse command line arguments
while getopts f:d: flag
do
case "${flag}" in
f) video_path=${OPTARG};;
d) segment_length_minutes=${OPTARG};;
*) echo "Invalid flag: ${flag}" >&2
exit 1;;
esac
done
if [[ -z "${video_path}" || -z "${segment_length_minutes}" ]]; then
echo "Usage: $0 -f [input video file path] -d [max duration of each segment in minutes]"
exit 1
fi
if [[ "$segment_length_minutes" =~ ^[0-9]+$ ]] ; then
.
else
echo "Error: Video duration must be a positive integer."
exit 1
fi
if [ ! -f "${video_path}" ]; then
echo "Input video file not found." >&2
exit 1
fi
# Convert segment length from minutes to seconds
segment_length=$(("${segment_length_minutes}" * 60))
# Get the duration of the video in seconds
duration=$(ffprobe -i "${video_path}" -show_entries format=duration -v quiet -of csv="p=0")
# Calculate the number of segments needed
num_segments=$(echo "($duration / $segment_length) + 1" | bc)
# Use ffmpeg to split the video and add text
for ((i=0; i<num_segments; i++)); do
start_time=$(echo "$i * ${segment_length}" | bc)
start_time_hms=$(convert_to_hms "${start_time}")
output_file=$(printf "segment_${random}_%03d.mp4" $i)
part_number=$(printf "Part %d" $((i+1)))
# The following command will also attach the "Part X" text to the video. If you don't want that,
# you can remove the `-vf` option and that entire line from the command below.
ffmpeg -ss "${start_time_hms}" -i "${video_path}" \
-vf "drawtext=fontfile=${font}:text='${part_number}':x=10:y=10:fontsize=24:fontcolor=white:box=1:boxcolor=black@0.5:boxborderw=5" \
-t "${segment_length}" -c:a copy -y "${output_file}"
done
Experienced Unix/Linux System Administrator with 20-year background in Systems Analysis, Problem Resolution and Engineering Application Support in a large distributed Unix and Windows server environment. Strong problem determination skills. Good knowledge of networking, remote diagnostic techniques, firewalls and network security. Extensive experience with engineering application and database servers, high-availability systems, high-performance computing clusters, and process automation.