-
-
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.
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 | |
# 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 |
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 | |
# 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