help quicky produce instagram reels and youtube shorts
94
96%
Does it follow best practices?
Impact
87%
2.12xAverage score across 3 eval scenarios
Passed
No findings from the security scan
#!/usr/bin/env python3
"""Alternative renderer: assemble a cut plan with MoviePy instead of ffmpeg.
Same contract as render_reel.py — same cut_plan.json in, same kind of file out —
so the two can be A/B'd against each other on identical input. Only the
assembly engine differs:
render_reel.py cuts each segment to a temp file, concat demuxer, single mux
render_moviepy.py builds an in-memory clip graph, writes once
Grading is deliberately NOT reimplemented here. The same ffmpeg filter chain
from render_reel.GRADES is applied as a second pass, so a comparison isolates
the assembly engine rather than measuring two different colour pipelines.
Requires: pip install moviepy (MoviePy 2.x API — subclipped/with_volume_scaled)
Usage:
render_moviepy.py plan/cut_plan.json --preview --out preview/mp_v1.mp4
render_moviepy.py plan/cut_plan.json --grade rapha --out work/master_mp.mp4
"""
import argparse, json, subprocess, sys, tempfile, time
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from render_reel import GRADES, RESOLUTIONS # single source of truth for looks
def apply_grade_pass(src, dst, grade, lut, srt, crf, preset):
"""Second pass: identical filter chain to render_reel.py, via ffmpeg."""
vf = []
if lut:
vf.append(f"lut3d='{lut}'")
elif GRADES.get(grade):
vf.append(GRADES[grade])
if srt:
vf.append(f"subtitles='{srt}':force_style="
"'FontName=Arial Black,FontSize=14,PrimaryColour=&HFFFFFF,"
"OutlineColour=&H000000,Outline=2,Alignment=2,MarginV=60'")
if not vf:
src.rename(dst)
return
r = subprocess.run(
["ffmpeg", "-y", "-v", "error", "-i", str(src), "-vf", ",".join(vf),
"-c:v", "libx264", "-preset", preset, "-crf", crf,
"-c:a", "copy", "-movflags", "+faststart", str(dst)],
capture_output=True, text=True)
if r.returncode != 0:
sys.exit(f"grade pass failed:\n{r.stderr[-800:]}")
def main():
ap = argparse.ArgumentParser()
ap.add_argument("plan")
ap.add_argument("--out", required=True)
ap.add_argument("--preview", action="store_true", help="fast 540x960 draft")
ap.add_argument("--grade", default="none", choices=list(GRADES))
ap.add_argument("--lut", help="Custom .cube LUT (overrides --grade)")
ap.add_argument("--srt", help="Burn in captions from SRT file")
ap.add_argument("--resolution", choices=sorted(RESOLUTIONS), default="1080")
ap.add_argument("--music-gain-db", type=float, default=-3.0)
ap.add_argument("--natural-audio", type=float, metavar="DB", default=None)
args = ap.parse_args()
try:
from moviepy import (VideoFileClip, AudioFileClip,
concatenate_videoclips, CompositeAudioClip)
except ImportError:
sys.exit("MoviePy not installed — `pip install moviepy` inside the "
"project venv, or use scripts/render_reel.py (ffmpeg engine).")
plan = json.loads(Path(args.plan).read_text())
segs = plan["segments"]
music = plan.get("music")
nat_db = args.natural_audio
if not music and nat_db is None:
nat_db = 0.0
total = plan.get("total_duration") or sum(s["duration"] for s in segs)
w, h = (540, 960) if args.preview else RESOLUTIONS[args.resolution]
crf = "26" if args.preview else "16"
preset = "veryfast" if args.preview else "slow"
out = Path(args.out)
out.parent.mkdir(parents=True, exist_ok=True)
started = time.time()
opened, parts = [], []
for n, s in enumerate(segs):
clip = VideoFileClip(s["clip"])
opened.append(clip)
piece = clip.subclipped(s["in"], s["in"] + s["duration"]).resized((w, h))
if nat_db is None:
piece = piece.without_audio()
parts.append(piece)
print(f" cut {n+1}/{len(segs)}", flush=True)
video = concatenate_videoclips(parts, method="compose")
tracks = []
if nat_db is not None and video.audio is not None:
tracks.append(video.audio.with_volume_scaled(10 ** (nat_db / 20)))
if music:
bed = AudioFileClip(music)
opened.append(bed)
start = plan.get("music_start", 0)
bed = bed.subclipped(start, min(start + total, bed.duration))
tracks.append(bed.with_volume_scaled(10 ** (args.music_gain_db / 20)))
if tracks:
mixed = tracks[0] if len(tracks) == 1 else CompositeAudioClip(tracks)
video = video.with_audio(mixed.with_duration(min(total, video.duration)))
with tempfile.TemporaryDirectory() as td:
raw = Path(td) / "assembled.mp4"
video.write_videofile(
str(raw), fps=30, codec="libx264", audio_codec="aac",
preset=preset, ffmpeg_params=["-crf", crf, "-pix_fmt", "yuv420p"],
logger=None)
for c in opened:
c.close()
video.close()
out_tmp = out.with_name(out.stem + ".tmp" + out.suffix)
apply_grade_pass(raw, out_tmp, args.grade, args.lut, args.srt, crf, preset)
r = subprocess.run(["ffprobe", "-v", "quiet", "-show_entries",
"format=duration", "-of", "csv=p=0", str(out_tmp)],
capture_output=True, text=True)
if r.returncode != 0 or not r.stdout.strip():
out_tmp.unlink(missing_ok=True)
sys.exit("Rendered file failed ffprobe validation — output discarded")
out_tmp.rename(out)
print(f"Rendered {out} ({float(r.stdout.strip()):.1f}s, engine=moviepy, "
f"{w}x{h}, grade={args.lut or args.grade}) "
f"in {time.time() - started:.1f}s wall")
if __name__ == "__main__":
main().tessl-plugin
evals
skills
reel-builder
assets
remotion-cards
references
scripts