StableSwarmUI
StableSwarmUI copied to clipboard
[Feature Request] - Add video formats (GIF, WebP) to 'Save Image of Current View' in Web Page Grid output
When using Grid Generator to make a grid of animations, it would be great to be able to output the grid of videos as a single video output file, either GIF, webp, or otherwise. Currently, I am using OBS Studio to record my screen.
betting this'll end up as a great way to crash your browser lol, trying to do large-res video processing in javascript
another option that comes to mind, now that I'm looking at the output folder structure, would be to drop a batch file into each grid output directory that would create this grid video with ffmpeg. the grid variables could be overlaid on the video with text https://stackoverflow.com/questions/17623676/text-on-video-ffmpeg that would keep it out of the browser entirely.
I wrestled this shell script out of chatgpt which manages to work pretty well at generating an FFMPEG command that combines all videos in subdirectories into a larger grid video. It works great on the few tests I've done. The task of pulling the JSON data out of the grid subdirectories and overlaying it as text on top of the videos seems a bit more daunting as of right now.
#!/bin/bash
ffmpeg_bin="ffmpeg" # Variable to set the ffmpeg executable path
current_time=$(date +"%Y-%m-%d-%H-%M-%S") # Current timestamp
output_file="grid-video-output-${current_time}.mp4"
declare -a inputs=()
declare -a layouts=()
# Function to generate the layout string
generate_layout() {
local num_rows=$1
local num_cols=$2
local layout_string=""
local index=0
for (( row=0; row<num_rows; row++ )); do
for (( col=0; col<num_cols; col++ )); do
if [ $col -eq 0 ]; then
x_pos="0"
else
x_pos="w0"
for (( k=1; k<col; k++ )); do
x_pos+="+w$k"
done
fi
if [ $row -eq 0 ]; then
y_pos="0"
else
y_pos="h0"
for (( k=1; k<row; k++ )); do
y_pos+="+h$k"
done
fi
layout_string+="$x_pos"_"$y_pos|"
done
done
# Remove the last pipe character
echo "${layout_string%|}"
}
# Find subdirectories and assume each subdirectory corresponds to a row
subdirs=()
for dir in */; do
# Ensure it is a directory and not empty
if [ -d "$dir" ] && [ "$(ls -A $dir*.{mp4,webp,mov} 2>/dev/null)" ]; then
subdirs+=("$dir")
# Using a glob pattern to match mp4, webp, and mov files
videos=($(ls $dir*.{mp4,webp,mov} 2>/dev/null))
# For the first directory, define the number of columns
if [ ${#inputs[@]} -eq 0 ]; then
num_columns=${#videos[@]}
fi
# Append each video to ffmpeg input
for (( i=0; i<num_columns; i++ )); do
inputs+=("-i \"${videos[$i]}\"")
done
fi
done
num_rows=${#subdirs[@]}
# Check if we have at least one column and one row
if [ ${#inputs[@]} -eq 0 ] || [ $num_rows -eq 0 ]; then
echo "No video files found in subdirectories."
exit 1
fi
# Generate layout string
layout_str=$(generate_layout $num_rows $num_columns)
# Join inputs
input_str=$(IFS=" "; echo "${inputs[*]}")
# Construct the ffmpeg command
ffmpeg_command="$ffmpeg_bin $input_str -filter_complex \"xstack=inputs=$((${#inputs[@]})):layout=$layout_str[v]\" -map '[v]' $output_file"
# Output the command to use it directly
echo "Generated ffmpeg command:"
echo "$ffmpeg_command"
# Uncomment the following line to execute the ffmpeg command directly
# eval "$ffmpeg_command"