Last active
February 18, 2025 01:01
-
-
Save unixabg/3ab52bb5067d88cf6372892da6f3931c to your computer and use it in GitHub Desktop.
Script to generate clip rips from a video
This file contains hidden or 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 | |
# clip-ripper v1.0.0 | |
# Author: Richard Nelson [email protected] | |
# Description: A script to slice videos into smaller clips using FFmpeg. | |
# Usage: Run with required parameters to extract video segments. | |
VERSION="1.0.0" | |
# Function to display help message | |
usage() { | |
echo "" | |
echo "Clip-Ripper v$VERSION" | |
echo "Usage: $0 --input-video <input_video> --length <segment_length_in_seconds> --slice-file <slice_file> [--output-dir <output_directory>] [--prefix-time <seconds>] [--separator <char>]" | |
echo "" | |
echo "Parameters:" | |
echo " --input-video <input_video> Required. Path to the input video file." | |
echo " --length <seconds> Required. Length of each segment in seconds." | |
echo " --slice-file <slice_file> Required. File containing HH:MM:SS and tags." | |
echo " --output-dir <directory> Optional. Directory to save sliced video files." | |
echo " --prefix-time <seconds> Optional. Shift start time of each slice backward." | |
echo " --separator <char> Optional. Custom field separator (default: '|')." | |
echo "" | |
echo "Example:" | |
echo " $0 --input-video myVideo.MOV --length 3 --slice-file slices.txt --output-dir clips --prefix-time 2 --separator '|'" | |
echo "" | |
exit 1 | |
} | |
# Show help message if no arguments are provided or if --help is used | |
if [[ "$#" -eq 0 || "$1" == "--help" ]]; then | |
usage | |
fi | |
# Default separator | |
separator="|" | |
# Parse command-line arguments | |
while [[ "$#" -gt 0 ]]; do | |
case $1 in | |
--input-video) input_file="$2"; shift 2;; | |
--length) segment_length="$2"; shift 2;; | |
--slice-file) slice_file="$2"; shift 2;; | |
--output-dir) output_dir="$2"; shift 2;; | |
--prefix-time) prefix_time="$2"; shift 2;; | |
--separator) separator="$2"; shift 2;; | |
*) echo "Unknown parameter: $1"; usage;; | |
esac | |
done | |
# Validate required parameters | |
if [[ -z "$input_file" || -z "$segment_length" || -z "$slice_file" ]]; then | |
echo "Error: Missing required parameters." | |
usage | |
fi | |
# Validate input video | |
if [[ ! -f "$input_file" ]]; then | |
echo "Error: Input video file '$input_file' does not exist." | |
usage | |
fi | |
# Validate segment length | |
if ! [[ "$segment_length" =~ ^[0-9]+$ ]]; then | |
echo "Error: Segment length must be a positive integer." | |
usage | |
fi | |
# Validate slice file | |
if [[ ! -f "$slice_file" ]]; then | |
echo "Error: Slice file '$slice_file' does not exist." | |
usage | |
fi | |
# Validate prefix time (default to 0 if not set) | |
if [[ -z "$prefix_time" ]]; then | |
prefix_time=0 | |
elif ! [[ "$prefix_time" =~ ^[0-9]+$ ]]; then | |
echo "Error: Prefix time must be a positive integer." | |
usage | |
fi | |
# Validate and create output directory if specified | |
if [[ -n "$output_dir" ]]; then | |
mkdir -p "$output_dir" || { echo "Error: Failed to create output directory '$output_dir'"; exit 1; } | |
else | |
output_dir="." # Default to current directory | |
fi | |
counter=1 | |
while IFS="$separator" read -r start_time tag_info; do | |
# Trim whitespace from tag_info | |
tag_info=$(echo "$tag_info" | xargs) | |
# Validate HH:MM:SS format using regex | |
if ! [[ "$start_time" =~ ^[0-9]{2}:[0-9]{2}:[0-9]{2}$ ]]; then | |
echo "Error: Invalid time format '$start_time'. Expected HH:MM:SS." | |
exit 1 | |
fi | |
# Convert start time to total seconds | |
IFS=: read -r h m s <<< "$start_time" | |
start_seconds=$((10#$h * 3600 + 10#$m * 60 + 10#$s)) | |
# Apply prefix-time shift **backwards** | |
adjusted_start_seconds=$((start_seconds - prefix_time)) | |
# Ensure start time doesn't go negative | |
if [[ "$adjusted_start_seconds" -lt 0 ]]; then | |
adjusted_start_seconds=0 | |
fi | |
# Calculate end time | |
end_seconds=$((adjusted_start_seconds + segment_length)) | |
# Convert times back to HH:MM:SS format | |
adjusted_start_time=$(printf "%02d:%02d:%02d" $((adjusted_start_seconds/3600)) $(((adjusted_start_seconds%3600)/60)) $((adjusted_start_seconds%60))) | |
end_time=$(printf "%02d:%02d:%02d" $((end_seconds/3600)) $(((end_seconds%3600)/60)) $((end_seconds%60))) | |
# Sanitize tag for filename (keep alphanumeric and spaces) | |
if [[ -n "$tag_info" ]]; then | |
safe_tag=$(echo "$tag_info" | tr -cd '[:alnum:] ') # Keep only alphanumeric and spaces | |
safe_tag=$(echo "$safe_tag" | tr ' ' '_') # Replace spaces with underscores | |
output_file="$output_dir/${input_file%.*}-slice${counter}-${safe_tag}.${input_file##*.}" | |
else | |
output_file="$output_dir/${input_file%.*}-slice${counter}.${input_file##*.}" | |
fi | |
# Generate FFmpeg command | |
echo "ffmpeg -i \"$input_file\" -ss $adjusted_start_time -to $end_time -c copy \"$output_file\"" | |
counter=$((counter + 1)) | |
done < "$slice_file" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment