File size: 5,161 Bytes
404feac 71e076c 404feac 71e076c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import os
import shutil
import subprocess
import glob
import re
from pathlib import Path
def create_video(input_dir, sample, temp_dir, step_multiplier, repeat, max_images):
output_filename = f"{os.path.basename(os.getcwd())}_sample{sample}.mp4"
print(f"Processing sample {sample}. Output filename: {output_filename}")
# Create repeated images
print(f"Creating repeated images for sample {sample}...")
for img in glob.glob(f"{input_dir}/*_{sample}_*.png"):
for i in range(repeat):
base = os.path.splitext(os.path.basename(img))[0]
shutil.copy(img, f"{temp_dir}/{base}_{i+1}.png")
# Prepare ffmpeg options
vf_options = "scale=1024x1024"
if step_multiplier:
vf_options += f",drawtext=fontfile=/usr/share/fonts/TTF/Inconsolata-Light.ttf:text='Steps\\: %{{expr\\:trunc(n*{step_multiplier}/{repeat})}}':x=10:y=h-th-10:fontsize=24:fontcolor=white"
if max_images:
vf_options = f"select='not(mod(n\\,{max_images}))',{vf_options}"
# Run first ffmpeg command
temp_output = f"{temp_dir}/temp_{sample}.mp4"
ffmpeg_cmd = [
"ffmpeg", "-framerate", "60",
"-pattern_type", "glob", "-i", f"{temp_dir}/*_{sample}_*.png",
"-vf", vf_options,
"-crf", "18", "-c:v", "libx264", "-b:v", "12M",
"-pix_fmt", "yuv420p", "-y", temp_output
]
try:
subprocess.run(ffmpeg_cmd, check=True)
except subprocess.CalledProcessError:
print(f"Error: ffmpeg command failed for sample {sample}.")
return False
# Get duration and process final video
try:
duration_cmd = ["ffmpeg", "-i", temp_output]
result = subprocess.run(duration_cmd, capture_output=True, text=True)
duration_match = re.search(r'Duration: (\d{2}):(\d{2}):(\d{2})', result.stderr)
if duration_match:
hours, minutes, seconds = map(float, duration_match.groups())
duration = hours * 3600 + minutes * 60 + seconds
fade_start = duration + 3
final_cmd = [
"ffmpeg", "-i", temp_output,
"-vf", f"tpad=stop_mode=clone:stop_duration=8,fade=t=out:st={fade_start}:d=5",
"-c:v", "libx264", "-b:v", "12M", "-crf", "18",
"-pix_fmt", "yuv420p", "-y", output_filename
]
subprocess.run(final_cmd, check=True)
else:
print("Error: Could not determine video duration.")
return False
except subprocess.CalledProcessError:
print(f"Error: Final ffmpeg processing failed for sample {sample}.")
return False
# Clean up temporary files for this sample
for f in glob.glob(f"{temp_dir}/*_{sample}_*.png"):
os.remove(f)
os.remove(temp_output)
return True
def get_step_size_from_filenames(sample):
files = sorted(glob.glob(f"*_{sample}_*.png"))
if len(files) < 2:
return None
# Extract step numbers from first two files
pattern = r'_(\d{6})_'
first_match = re.search(pattern, files[0])
second_match = re.search(pattern, files[1])
if first_match and second_match:
first_step = int(first_match.group(1))
second_step = int(second_match.group(1))
return second_step - first_step
return None
def main():
parser = argparse.ArgumentParser(description='Convert PNG sequence to MP4')
parser.add_argument('--max', type=int, help='Maximum number of images')
parser.add_argument('--step', type=int, help='Step multiplier')
parser.add_argument('--repeat', type=int, default=1, help='Repeat count')
parser.add_argument('--steps-from-filename', action='store_true', help='Calculate steps from filename')
args = parser.parse_args()
# Create temporary directory
temp_dir = os.path.expanduser("~/.local/tmp")
os.makedirs(temp_dir, exist_ok=True)
print("Created temporary directory...")
# Check for PNG files
png_files = glob.glob("*.png")
if not png_files:
print("Error: No PNG files found in the current directory.")
return 1
# Find all unique sample numbers
sample_pattern = r'_(\d{2})_'
samples = sorted(set(re.findall(sample_pattern, ' '.join(png_files))))
for sample in samples:
if args.steps_from_filename:
step_multiplier = get_step_size_from_filenames(sample)
if step_multiplier:
print(f"Detected step size: {step_multiplier}")
else:
print("Error: Could not determine step size from filenames")
continue
else:
step_multiplier = args.step
success = create_video(".", sample, temp_dir, step_multiplier, args.repeat, args.max)
if not success:
shutil.rmtree(temp_dir)
return 1
# Clean up
print("Cleaning up temporary directory...")
shutil.rmtree(temp_dir)
print("All samples processed successfully.")
return 0
if __name__ == "__main__":
exit(main())
|