Skip to content

Instantly share code, notes, and snippets.

@jacobtender
Last active April 23, 2024 22:06
Show Gist options
  • Save jacobtender/454a9c82fa041c4001fbb139e106e40d to your computer and use it in GitHub Desktop.
Save jacobtender/454a9c82fa041c4001fbb139e106e40d to your computer and use it in GitHub Desktop.
Two scripts that accept two videos as input and outputs a collection of comparative thumbnails. The second iteration uses a faster method of taking screen grabs.
#!/bin/bash
# Function to cleanup temporary files
cleanup() {
echo "cleaning up"
rm -rf tmp
}
# Function to get video duration
get_video_duration() {
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$1" 2>/dev/null)
if [ "$duration" != "N/A" ]; then
# Calculate hours, minutes, and seconds
hours=$(printf "%.0f" $(echo "$duration / 3600" | bc))
minutes=$(printf "%.0f" $(echo "($duration % 3600) / 60" | bc))
seconds=$(printf "%.0f" $(echo "$duration % 60" | bc))
# Format the duration
formatted_duration=$(printf "%02d:%02d:%02d" "$hours" "$minutes" "$seconds")
echo "${formatted_duration}"
else
echo "N/A"
fi
}
# Function to get video size in GB
get_video_size() {
size_bytes=$(ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1:nokey=1 "$1" 2>/dev/null)
if [ "$size_bytes" != "N/A" ]; then
size_gb=$(awk "BEGIN {printf \"%.2f\", $size_bytes / (1024^3)}")
echo "${size_gb:-N/A} GB"
else
echo "N/A"
fi
}
# Check if ffmpeg and ImageMagick are installed
if ! command -v ffmpeg &> /dev/null || ! command -v montage &> /dev/null || ! command -v convert &> /dev/null; then
echo "Please make sure ffmpeg, ImageMagick, and montagem are installed."
exit 1
fi
# Input video files
video1="$1"
video2="$2"
# Check if both video files are provided
if [ -z "$video1" ] || [ -z "$video2" ]; then
echo "Usage: $0 <video1> <video2>"
exit 1
fi
# rm -rf comparison
# Extract titles from video filenames
title1=$(basename "$video1" | sed 's/\.[^.]*$//') # Remove extension
title2=$(basename "$video2" | sed 's/\.[^.]*$//') # Remove extension
# Function to extract video width
get_video_width() {
ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 "$1"
}
# Get video widths
width1=$(get_video_width "$video1")
width2=$(get_video_width "$video2")
# Determine the minimum width
min_width=$(echo "$width1 $width2" | tr ' ' '\n' | sort -n | head -n1)
# Create directories to store screenshots
mkdir -p tmp
mkdir -p tmp/screenshots1
mkdir -p tmp/screenshots2
# Extract screenshots from video1
ffmpeg -i "$video1" -vf fps=1/500 -t 1800 tmp/screenshots1/screenshot_%03d.png -hide_banner
# Extract screenshots from video2
ffmpeg -i "$video2" -vf fps=1/500 -t 1800 tmp/screenshots2/screenshot_%03d.png -hide_banner
# Check if both videos have the same number of screenshots
num_screenshots_video1=$(ls -1 tmp/screenshots1/*.png | wc -l)
num_screenshots_video2=$(ls -1 tmp/screenshots2/*.png | wc -l)
if [ "$num_screenshots_video1" -ne "$num_screenshots_video2" ]; then
echo "Number of screenshots extracted from each video are not equal."
exit 1
fi
# Create directory to store comparison images
mkdir -p tmp/comparison
mkdir -p comparison
# Combine screenshots for comparison and add titles
for screenshot1 in tmp/screenshots1/*.png; do
screenshot2="tmp/screenshots2/$(basename "$screenshot1")"
tmp_output="tmp/comparison/$(basename "$screenshot1" .png)"
output="comparison/$(basename "$screenshot1" .png)"
# Get video duration and size
duration1=$(get_video_duration "$video1")
size1=$(get_video_size "$video1")
duration2=$(get_video_duration "$video2")
size2=$(get_video_size "$video2")
# Generate titles
title1_image="tmp/title1.png"
title2_image="tmp/title2.png"
title1_with_info="$title1 | Duration: $duration1, Size: $size1 bytes"
title2_with_info="$title2 | Duration: $duration2, Size: $size2 bytes"
convert -size "${min_width}x30" -background none -fill white -gravity west -font Arial -pointsize 24 \
caption:"$title1_with_info" "$title1_image"
convert -size "${min_width}x30" -background none -fill white -gravity west -font Arial -pointsize 24 \
caption:"$title2_with_info" "$title2_image"
# Trim black bars from left and right
convert "$screenshot1" -bordercolor black -border 1x1 -fuzz 5% -trim +repage "$screenshot1"
convert "$screenshot1" -bordercolor black -border 1x1 -fuzz 5% -trim +repage "$screenshot2"
# Combine screenshots and titles
montage "$screenshot1" "$screenshot2" "$title1_image" "$title2_image" \
-tile 2x2 -geometry +0+0 -border 5x10 -bordercolor black "${output}_labeled.png"
montage "$screenshot1" "$screenshot2" \
-tile 2x -geometry +0+0 -border 5x10 -bordercolor black "${tmp_output}_clean.png"
# Remove temporary title images
# rm "$title1_image" "$title2_image"
done
echo "Comparison images created in 'comparison' directory."
# Create the output filename
output_filename="comparison_result.png"
output_titles="tmp/comparison_titles.png"
# Stitch all comparison images vertically and add filename label at the top
montage tmp/comparison/*_clean.png -tile 1x -geometry +0+0 -border 0x10 -bordercolor black "$output_filename"
montage "$title1_image" "$title2_image" -tile 2x -geometry +0+0 -border 5x10 -bordercolor black "$output_titles"
montage "$output_titles" "$output_filename" -tile 1x -geometry +0+0 -border 0 -bordercolor black "$output_filename"
echo "Final comparison image created: $output_filename"
# Clean up temporary files
cleanup
#!/bin/bash
# Function to cleanup temporary files
cleanup() {
echo "cleaning up"
rm -rf tmp
}
# Function to get video duration
get_video_duration() {
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$1" 2>/dev/null)
if [ "$duration" != "N/A" ]; then
# Calculate hours, minutes, and seconds
hours=$(printf "%.0f" $(echo "$duration / 3600" | bc))
minutes=$(printf "%.0f" $(echo "($duration % 3600) / 60" | bc))
seconds=$(printf "%.0f" $(echo "$duration % 60" | bc))
# Format the duration
formatted_duration=$(printf "%02d:%02d:%02d" "$hours" "$minutes" "$seconds")
echo "${formatted_duration}"
else
echo "N/A"
fi
}
split_video_timestamps() {
# Get video duration in seconds
# duration=$(ffmpeg -i "$1" 2>&1 | grep "Duration" | cut -d ' ' -f 4 | sed 's/,//')
# echo $duration
# Get video duration in seconds
duration_seconds=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$1" | awk '{print int($1)}')
# echo $duration_seconds
offset=$((duration_seconds / 8))
echo $offset
echo $(($offset * 3))
echo $(($offset * 5))
echo $(($offset * 7))
}
# Function to get video size in GB
get_video_size() {
size_bytes=$(ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1:nokey=1 "$1" 2>/dev/null)
if [ "$size_bytes" != "N/A" ]; then
size_gb=$(awk "BEGIN {printf \"%.2f\", $size_bytes / (1024^3)}")
echo "${size_gb:-N/A} GB"
else
echo "N/A"
fi
}
# Check if ffmpeg and ImageMagick are installed
if ! command -v ffmpeg &> /dev/null || ! command -v montage &> /dev/null || ! command -v convert &> /dev/null; then
echo "Please make sure ffmpeg, ImageMagick, and montagem are installed."
exit 1
fi
# Input video files
video1="$1"
video2="$2"
# Check if both video files are provided
if [ -z "$video1" ] || [ -z "$video2" ]; then
echo "Usage: $0 <video1> <video2>"
exit 1
fi
# rm -rf comparison
# Extract titles from video filenames
title1=$(basename "$video1" | sed 's/\.[^.]*$//') # Remove extension
title2=$(basename "$video2" | sed 's/\.[^.]*$//') # Remove extension
# Function to extract video width
get_video_width() {
ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 "$1"
}
# Get video widths
width1=$(get_video_width "$video1")
width2=$(get_video_width "$video2")
# Determine the minimum width
min_width=$(echo "$width1 $width2" | tr ' ' '\n' | sort -n | head -n1)
# Create directories to store screenshots
mkdir -p tmp
mkdir -p tmp/screenshots1
mkdir -p tmp/screenshots2
i=1
timestamps_array=($(split_video_timestamps "$1"))
for timestamp in "${timestamps_array[@]}"; do
# Extract screenshots from video1
ffmpeg -y -ss $timestamp -i "$video1" -sn -vframes 1 tmp/screenshots1/screenshot_$(printf "%03d" "$i").png >/dev/null 2>&1
# Extract screenshots from video2
ffmpeg -y -ss $timestamp -i "$video2" -sn -vframes 1 tmp/screenshots2/screenshot_$(printf "%03d" "$i").png >/dev/null 2>&1
((i++))
done
break
# Check if both videos have the same number of screenshots
num_screenshots_video1=$(ls -1 tmp/screenshots1/*.png | wc -l)
num_screenshots_video2=$(ls -1 tmp/screenshots2/*.png | wc -l)
if [ "$num_screenshots_video1" -ne "$num_screenshots_video2" ]; then
echo "Number of screenshots extracted from each video are not equal."
exit 1
fi
# Create directory to store comparison images
mkdir -p tmp/comparison
mkdir -p comparison
# Combine screenshots for comparison and add titles
for screenshot1 in tmp/screenshots1/*.png; do
screenshot2="tmp/screenshots2/$(basename "$screenshot1")"
tmp_output="tmp/comparison/$(basename "$screenshot1" .png)"
output="comparison/$(basename "$screenshot1" .png)"
# Get video duration and size
duration1=$(get_video_duration "$video1")
size1=$(get_video_size "$video1")
duration2=$(get_video_duration "$video2")
size2=$(get_video_size "$video2")
# Generate titles
title1_image="tmp/title1.png"
title2_image="tmp/title2.png"
title1_with_info="$title1 | Duration: $duration1, Size: $size1 bytes"
title2_with_info="$title2 | Duration: $duration2, Size: $size2 bytes"
convert -size "${min_width}x30" -background none -fill white -gravity west -font Arial -pointsize 24 \
caption:"$title1_with_info" "$title1_image"
convert -size "${min_width}x30" -background none -fill white -gravity west -font Arial -pointsize 24 \
caption:"$title2_with_info" "$title2_image"
# Trim black bars from left and right
convert "$screenshot1" -bordercolor black -border 1x1 -fuzz 5% -trim +repage "$screenshot1"
convert "$screenshot1" -bordercolor black -border 1x1 -fuzz 5% -trim +repage "$screenshot2"
# Combine screenshots and titles
montage "$screenshot1" "$screenshot2" "$title1_image" "$title2_image" \
-tile 2x2 -geometry +0+0 -border 5x10 -bordercolor black "${output}_labeled.png"
montage "$screenshot1" "$screenshot2" \
-tile 2x -geometry +0+0 -border 5x10 -bordercolor black "${tmp_output}_clean.png"
# Remove temporary title images
# rm "$title1_image" "$title2_image"
done
echo "Comparison images created in 'comparison' directory."
# Create the output filename
output_filename="comparison_result.png"
output_titles="tmp/comparison_titles.png"
# Stitch all comparison images vertically and add filename label at the top
montage tmp/comparison/*_clean.png -tile 1x -geometry +0+0 -border 0x10 -bordercolor black "$output_filename"
montage "$title1_image" "$title2_image" -tile 2x -geometry +0+0 -border 5x10 -bordercolor black "$output_titles"
montage "$output_titles" "$output_filename" -tile 1x -geometry +0+0 -border 0 -bordercolor black "$output_filename"
echo "Final comparison image created: $output_filename"
# Clean up temporary files
cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment