Skip to content

Instantly share code, notes, and snippets.

@IAmStoxe
Created December 24, 2024 21:22
Show Gist options
  • Save IAmStoxe/9a5a16c282a9039f21da20eeace4cfa6 to your computer and use it in GitHub Desktop.
Save IAmStoxe/9a5a16c282a9039f21da20eeace4cfa6 to your computer and use it in GitHub Desktop.

Gist README

Generate Sprites for All Videos in a Folder

This script loops through all video files in a specified folder, extracts a set number of frames (20 by default), and generates a single sprite sheet (vertical strip) for each video.

How It Works

  1. Input Folder: The first argument is the path to the folder containing video files.
  2. Output Folder: The second argument is the path to the folder where generated sprite sheets will be saved.
  3. Frames: By default, the script extracts 20 frames, evenly spaced across the duration of each video, and arranges them vertically in a single image (tile=1x20).
  4. Filename Matching: Currently, the script searches for *.mp4 files in the input folder. You can modify the glob pattern to include other video formats (.mov, .mkv, etc.).
  5. Sprite Sheet Dimensions: The sprite sheet is scaled to a width or height of 135 pixels (maintaining aspect ratio), padded if necessary, and saved as a .jpg.

Requirements

  • ffmpeg and ffprobe (often included together in ffmpeg distributions).
  • bc (for floating-point arithmetic in Bash).
  • A Unix-like shell environment (e.g., Linux, macOS, or WSL on Windows).

Usage

# Make the script executable (only needed once):
chmod +x generate_sprites_for_folder.sh

# Run the script, passing in:
# 1) The folder containing your videos
# 2) The folder where you want to save the sprite sheets
./generate_sprites_for_folder.sh /path/to/videos /path/to/output

Example:

./generate_sprites_for_folder.sh ~/Movies ~/SpriteSheets

Customization

  • Frames: Change the FRAMES=20 variable to your preferred number of frames (e.g., FRAMES=10).
  • Glob Pattern: If your videos have extensions other than .mp4, modify:
    for INPUT in "$IN_FOLDER"/*.mp4; do
    to include other patterns (e.g., *.mov, *.mkv, *.avi) or something more general like *.*.
  • Sprite Sheet Dimensions: The -filter_complex line uses a fixed height of 135 (with -1 for width to preserve aspect ratio). Change these values to your preference.
  • Error Handling: If ffprobe cannot read the video duration or if the duration is 0, bc might generate an error. You can wrap FPS calculation and the ffmpeg command in conditionals to handle that gracefully.

Script

#!/usr/bin/env bash

# Usage:
#   ./generate_sprites_for_folder.sh /path/to/videos /path/to/output

IN_FOLDER="$1"
OUT_FOLDER="$2"
FRAMES=20

# Create the output folder if it doesn’t exist
mkdir -p "$OUT_FOLDER"

# Loop through all video files in the input folder
# Adjust the glob (*.mp4) to include other extensions if needed
for INPUT in "$IN_FOLDER"/*.mp4; do
  
  # Skip if no matching file was found (in case the folder is empty)
  [ -e "$INPUT" ] || continue

  # Extract the base filename (without path and extension)
  BASENAME="$(basename "$INPUT" .mp4)"
  
  # Construct the output sprite sheet name
  OUTPUT="$OUT_FOLDER/${BASENAME}_sprite.jpg"

  echo "Processing: $INPUT -> $OUTPUT"

  # Extract video duration in seconds
  DURATION_S=$(ffprobe -v error -show_entries format=duration \
               -of default=noprint_wrappers=1:nokey=1 "$INPUT")

  # Calculate the FPS if we want 20 frames in our sprite sheet
  FPS=$(echo "scale=8; $FRAMES / $DURATION_S" | bc)
  
  # Generate the sprite sheet
  ffmpeg \
    -y \
    -i "$INPUT" \
    -frames 1 \
    -q:v 2 \
    -filter_complex "fps=$FPS,
                     pad=width=max(iw\,ih*(16/9)):height=ow/(16/9):x=(ow-iw)/2:y=(oh-ih)/2,
                     scale=-1:135:force_original_aspect_ratio=decrease,
                     tile=1x$FRAMES" \
    "$OUTPUT"
done

echo "All sprite sheets have been generated in $OUT_FOLDER."

License

This script is provided under the MIT License. Feel free to use, modify, and distribute it in your own projects.


If you find this helpful, consider giving it a star on Gist or share your improvements!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment