Files
ltx2-mps/story_generator.py
2026-01-11 20:01:20 +01:00

162 lines
5.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
generate a multi-scene story video with ltx-2
"""
import os
import subprocess
import sys
# story scenes - each generates ~4 seconds
SCENES = [
# Act 1: Introduction
{
"prompt": "Sunrise over the Swiss Alps, snow-covered peaks glowing orange and pink, peaceful morning atmosphere, cinematic wide shot, gentle wind blowing snow, 4K quality",
"name": "01_sunrise"
},
{
"prompt": "A majestic white Swiss shepherd dog standing on a snowy ridge overlooking a mountain valley, morning light, heroic pose, wind ruffling fur, cinematic portrait shot",
"name": "02_hero_intro"
},
{
"prompt": "Close-up of the Swiss shepherd's face, alert eyes scanning the horizon, breath visible in cold air, morning sunlight on fur, shallow depth of field",
"name": "03_closeup"
},
{
"prompt": "The Swiss shepherd walking through deep powder snow in the Alps, determined stride, pine trees in background, snow particles in air, tracking shot",
"name": "04_walking"
},
# Act 2: Discovery
{
"prompt": "The Swiss shepherd stops suddenly, ears perked up, alert pose, listening intently, snowy forest background, dramatic lighting, tension building",
"name": "05_alert"
},
{
"prompt": "A small white lamb alone in the snow, shivering, lost and scared, soft snowfall, vulnerable, wide snowy landscape, emotional scene",
"name": "06_lost_lamb"
},
{
"prompt": "The Swiss shepherd approaching the lamb gently, careful steps through snow, compassionate body language, soft winter light, heartwarming moment",
"name": "07_approach"
},
{
"prompt": "Close-up of the shepherd dog nuzzling the scared lamb, comforting gesture, warm breath visible, tender moment, shallow depth of field, emotional",
"name": "08_comfort"
},
# Act 3: Journey home
{
"prompt": "The Swiss shepherd leading the small lamb through snowy alpine meadow, protective stance, walking together, mountains in background, golden hour light",
"name": "09_leading"
},
{
"prompt": "Wide shot of dog and lamb crossing a snowy hill together, tiny figures in vast white landscape, beautiful alpine scenery, cinematic composition",
"name": "10_journey"
},
{
"prompt": "The shepherd and lamb walking past snow-covered pine trees, gentle snowfall, peaceful atmosphere, soft afternoon light filtering through branches",
"name": "11_forest_path"
},
{
"prompt": "A cozy Swiss mountain village appearing in the distance, warm lights glowing from windows, smoke from chimneys, dusk setting in, hopeful atmosphere",
"name": "12_village_sight"
},
# Act 4: Reunion
{
"prompt": "The Swiss shepherd and lamb arriving at a wooden barn door, warm light spilling out, welcoming atmosphere, end of journey, relief",
"name": "13_arrival"
},
{
"prompt": "A farmer in traditional Swiss clothing opening the barn door, surprised and grateful expression, warm interior light, emotional reunion moment",
"name": "14_farmer"
},
{
"prompt": "The lamb running to join other sheep in a warm barn, happy reunion, straw on floor, cozy interior, heartwarming resolution",
"name": "15_reunion"
},
{
"prompt": "The Swiss shepherd sitting proudly outside the barn, farmer patting its head gratefully, twilight sky, village lights twinkling, satisfied hero",
"name": "16_reward"
},
# Finale
{
"prompt": "Night sky over the Swiss Alps with stars and northern lights, the shepherd dog silhouette on a ridge, majestic ending, peaceful, cinematic wide shot",
"name": "17_finale"
},
]
def generate_scene(scene, output_dir, width=768, height=448, frames=97, steps=20):
"""generate a single scene"""
output_path = os.path.join(output_dir, f"{scene['name']}.mp4")
if os.path.exists(output_path):
print(f"skipping {scene['name']} (already exists)")
return output_path
cmd = [
sys.executable, "generate.py",
scene["prompt"],
"-o", output_path,
"--width", str(width),
"--height", str(height),
"--frames", str(frames),
"--steps", str(steps),
"-n", "blurry, low quality, distorted, deformed, ugly, bad anatomy"
]
print(f"\n{'='*60}")
print(f"generating: {scene['name']}")
print(f"prompt: {scene['prompt'][:80]}...")
print(f"{'='*60}\n")
subprocess.run(cmd, cwd=os.path.dirname(os.path.abspath(__file__)))
return output_path
def concatenate_videos(video_files, output_path):
"""concatenate all videos using ffmpeg"""
# create file list
list_path = "/tmp/video_list.txt"
with open(list_path, "w") as f:
for video in video_files:
f.write(f"file '{video}'\n")
cmd = [
"ffmpeg", "-y", "-f", "concat", "-safe", "0",
"-i", list_path,
"-c:v", "libx264", "-crf", "18",
"-c:a", "aac", "-b:a", "192k",
output_path
]
print(f"\nconcatenating {len(video_files)} clips...")
subprocess.run(cmd)
print(f"saved to: {output_path}")
def main():
output_dir = os.path.expanduser("~/Desktop/mountain_guardian")
os.makedirs(output_dir, exist_ok=True)
print(f"generating {len(SCENES)} scenes for 'The Mountain Guardian'")
print(f"output directory: {output_dir}")
print(f"estimated time: ~{len(SCENES) * 10} minutes\n")
video_files = []
for i, scene in enumerate(SCENES):
print(f"\n[{i+1}/{len(SCENES)}]")
video_path = generate_scene(scene, output_dir)
video_files.append(video_path)
# concatenate all videos
final_path = os.path.join(output_dir, "mountain_guardian_full.mp4")
concatenate_videos(video_files, final_path)
print(f"\n{'='*60}")
print(f"done! final video: {final_path}")
print(f"{'='*60}")
if __name__ == "__main__":
main()