png2mp4: only draw text when needed, remove x265 as it has been electrified too much by an engineer with access to a large language model 🐺
Browse files- zsh/png2mp4.zsh +10 -82
zsh/png2mp4.zsh
CHANGED
@@ -1,82 +1,6 @@
|
|
1 |
-
# png2mp4_x265()
|
2 |
-
# Converts a series of PNG images to an MP4 video using x265 encoding
|
3 |
-
#
|
4 |
-
# Usage: png2mp4_x265 [--max <number>] [--step <number>] [--repeat <number>]
|
5 |
-
#
|
6 |
-
# Options:
|
7 |
-
# --max <number> : Maximum number of images to process
|
8 |
-
# --step <number> : Multiplier for step count in overlay text (default: 1)
|
9 |
-
# --repeat <number> : Number of times to repeat each image (default: 1)
|
10 |
-
#
|
11 |
-
# This function:
|
12 |
-
# 1. Finds all PNG files in the current directory
|
13 |
-
# 2. Uses the current directory name as the output filename prefix
|
14 |
-
# 3. Uses ffmpeg to create an MP4 with x265 encoding, including:
|
15 |
-
# - Frame rate of 60 fps
|
16 |
-
# - Image scaling to 1024x1024
|
17 |
-
# - Step count overlay text (divided by 1,000,000 and truncated to remove 6 zeros and decimal places)
|
18 |
-
# - High-quality encoding settings
|
19 |
-
# 4. Adds padding and fade-out effect to the final video
|
20 |
-
#
|
21 |
-
# Requirements:
|
22 |
-
# - ffmpeg with libx265 support
|
23 |
-
# - Inconsolata-Light.ttf font in /usr/share/fonts/TTF/
|
24 |
-
png2mp4_x265() {
|
25 |
-
local step_multiplier=1
|
26 |
-
local repeat=1
|
27 |
-
local frame_rate=60
|
28 |
-
local resolution="1024x1024"
|
29 |
-
|
30 |
-
while [[ "$#" -gt 0 ]]; do
|
31 |
-
case $1 in
|
32 |
-
--step) step_multiplier="$2"; shift ;;
|
33 |
-
--repeat) repeat="$2"; shift ;;
|
34 |
-
*) echo "Unknown parameter passed: $1"; return 1 ;;
|
35 |
-
esac
|
36 |
-
shift
|
37 |
-
done
|
38 |
-
|
39 |
-
# Find all unique sample numbers
|
40 |
-
local samples=($(ls *.png | sed -n 's/.*_\([0-9][0-9]\)_.*/\1/p' | sort -u))
|
41 |
-
|
42 |
-
for sample in "${samples[@]}"; do
|
43 |
-
local output_filename="$(basename "$(pwd)")_sample${sample}_x265.mp4"
|
44 |
-
echo "Processing sample ${sample}. Output filename: $output_filename"
|
45 |
-
|
46 |
-
local nframes=$(ls *_${sample}_*.png | wc -l)
|
47 |
-
local duration=$(($nframes * $repeat / ${frame_rate}.))
|
48 |
-
local fade_start=$((duration + 3))
|
49 |
-
echo "Found $nframes frames for sample ${sample}, duration of $duration seconds"
|
50 |
-
|
51 |
-
echo "Running ffmpeg with x265 encoding for sample ${sample}..."
|
52 |
-
local font=/usr/share/fonts/TTF/Inconsolata-Light.ttf
|
53 |
-
local drawtext="drawtext=fontfile=${font}:text='Steps\: %{eif\\:trunc(n*$step_multiplier)\\:u\\:3}':x=10:y=h-th-10:fontsize=24:fontcolor=white"
|
54 |
-
local fadeout="tpad=stop_mode=clone:stop_duration=8,fade=t=out:st=${fade_start}:d=5"
|
55 |
-
local encoder=(
|
56 |
-
-pix_fmt yuv420p
|
57 |
-
-c:v libx265
|
58 |
-
-preset slower
|
59 |
-
-tune animation
|
60 |
-
-crf 22
|
61 |
-
-x265-params "keyint=${repeat}:min-keyint=$((repeat-1)):scenecut=0:ref=5:bframes=8:b-adapt=2:rc-lookahead=$((2*repeat)):lookahead-slices=4:aq-mode=3:aq-strength=0.8:deblock=-1,-1:sao=0"
|
62 |
-
)
|
63 |
-
|
64 |
-
ffmpeg -framerate "$frame_rate/$repeat" -pattern_type glob -i "*_${sample}_*.png" \
|
65 |
-
-vf "scale=${resolution},${drawtext},fps=${frame_rate},${fadeout}" \
|
66 |
-
"${encoder[@]}" -y "$output_filename"
|
67 |
-
if [ $? -ne 0 ]; then
|
68 |
-
echo "Error: ffmpeg command failed for sample ${sample}."
|
69 |
-
return 1
|
70 |
-
fi
|
71 |
-
done
|
72 |
-
|
73 |
-
echo "All samples processed successfully."
|
74 |
-
}
|
75 |
-
|
76 |
-
# Same thing but x264
|
77 |
png2mp4() {
|
78 |
local max_images=""
|
79 |
-
local step_multiplier=
|
80 |
local repeat=1
|
81 |
local temp_dir="/home/kade/.local/tmp"
|
82 |
|
@@ -115,14 +39,18 @@ png2mp4() {
|
|
115 |
done
|
116 |
|
117 |
echo "Running ffmpeg for sample ${sample}..."
|
|
|
|
|
|
|
|
|
|
|
118 |
if [[ -n "$max_images" ]]; then
|
119 |
-
|
120 |
-
-c:v libx264 -pix_fmt yuv420p -y "$temp_dir/temp_${sample}.mp4"
|
121 |
-
else
|
122 |
-
ffmpeg -framerate 60 -pattern_type glob -i "$temp_dir/*_${sample}_*.png" -vf "scale=1024x1024,drawtext=fontfile=/usr/share/fonts/TTF/Inconsolata-Light.ttf:text='Steps\: %{expr\:trunc(n*$step_multiplier/$repeat/1000000)}':x=10:y=h-th-10:fontsize=24:fontcolor=white" -crf 28 \
|
123 |
-
-c:v libx264 -pix_fmt yuv420p -y "$temp_dir/temp_${sample}.mp4"
|
124 |
fi
|
125 |
|
|
|
|
|
|
|
126 |
if [ $? -ne 0 ]; then
|
127 |
echo "Error: ffmpeg command failed for sample ${sample}."
|
128 |
rm -rf "$temp_dir"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
png2mp4() {
|
2 |
local max_images=""
|
3 |
+
local step_multiplier=""
|
4 |
local repeat=1
|
5 |
local temp_dir="/home/kade/.local/tmp"
|
6 |
|
|
|
39 |
done
|
40 |
|
41 |
echo "Running ffmpeg for sample ${sample}..."
|
42 |
+
local vf_options="scale=1024x1024"
|
43 |
+
if [[ -n "$step_multiplier" ]]; then
|
44 |
+
vf_options+=",drawtext=fontfile=/usr/share/fonts/TTF/Inconsolata-Light.ttf:text='Steps\: %{expr\:trunc(n*$step_multiplier/$repeat/1000000)}':x=10:y=h-th-10:fontsize=24:fontcolor=white"
|
45 |
+
fi
|
46 |
+
|
47 |
if [[ -n "$max_images" ]]; then
|
48 |
+
vf_options="select='not(mod(n\,$max_images))',$vf_options"
|
|
|
|
|
|
|
|
|
49 |
fi
|
50 |
|
51 |
+
ffmpeg -framerate 60 -pattern_type glob -i "$temp_dir/*_${sample}_*.png" -vf "$vf_options" -crf 28 \
|
52 |
+
-c:v libx264 -pix_fmt yuv420p -y "$temp_dir/temp_${sample}.mp4"
|
53 |
+
|
54 |
if [ $? -ne 0 ]; then
|
55 |
echo "Error: ffmpeg command failed for sample ${sample}."
|
56 |
rm -rf "$temp_dir"
|