OpenMontage

CLI Tool

calesthio/OpenMontage

World's first open-source agentic video production system.

Overview

OpenMontage turns your AI coding assistant into a full video production studio. It provides 12 pipelines and 52 tools for research, scripting, asset generation, and editing. Supports both free and paid workflows.

README Preview

\n  \n\n\nOpenMontage\n\nThe first open-source, agentic video production system.\n\n\n  Paste A Video  · \n  Quick Start  · \n  Try These Prompts  · \n  Pipelines  · \n  How It Works  · \n  Providers  · \n  Agent Guide\n\n\n\n  \n\n\nFollow The Build\n\n\n  \n  \n  \n\n\n---\n\nTurn your AI coding assistant into a full video production studio. Describe what you want in plain language — your agent handles research, scripting, asset generation, editing, and final composition.\n\n**Important distinction:** OpenMontage can make image-based videos, but it can also make a real **video video** for free/open-source workflows: the agent builds a corpus from free stock footage and open archives, retrieves actual motion clips, edits them into a timeline, and renders a finished piece. That is not the usual "animate a handful of stills and call it video" trick.\n\n\n  \n\n\n> **"SIGNAL FROM TOMORROW"** — a cinematic sci-fi trailer fully produced through OpenMontage: concept, script, scene plan, Veo-generated motion clips, soundtrack, and Remotion composition.\n\n\n  \n\n\n> **"THE LAST BANANA"** — a 60-second Pixar-style animated short about a lonely banana who finds friendship with a kiwi. 6 Kling v3-generated motion clips (via fal.ai), Google Chirp3-HD narration, royalty-free piano music, TikTok-style word-level captions, and Remotion composition. Total cost: **$1.33**.\n\n\n  \n\n\n> **"VOID — Neural Interface"** — a product ad produced with just one API key (OpenAI). 4 AI-generated images (gpt-image-1), TTS narration, auto-sourced royalty-free music, word-level subtitles via WhisperX, and Remotion data visualizations. Total cost: **$0.69**. Zero manual asset work.\n\n\n  \n\n\n> **"Afternoon in Candyland"** — a Ghibli-style anime animation. A little girl's whimsical afternoon adventure through candy gates, gumdrop rivers, and lollipop gardens. 12 FLUX-generated images with multi-image crossfade, cinematic camera mot

FAQ (5)

Troubleshooting
How to fix FFmpeg `afade=t=out` making delayed audio_mixer tracks silent after the first few seconds?

This happens because afade=t=out:d=N defaults to st=0, so the fade-out starts at the beginning of the stream. After N seconds, the track remains silent for the rest of its duration, including delayed segments.

Fix it by probing each source track's duration and setting an explicit fade-out start time. Apply fades on the source timeline before adelay:

import subprocess

duration = float(
    subprocess.check_output([
        "ffprobe", "-v", "error",
        "-show_entries", "format=duration",
        "-of", "csv=p=0",
        track_path,
    ]).strip()
)

if fade_in > 0:
    filters.append(f"afade=t=in:st=0:d={fade_in}")

if fade_out > 0:
    fade_out_start = duration - fade_out
    filters.append(
        f"afade=t=out:st={fade_out_start:.4f}:d={fade_out}"
    )

# Add adelay after the source-timeline fades.
filters.append(f"adelay={int(start_seconds * 1000)}|{int(start_seconds * 1000)}")

If afade is applied after adelay, use:

fade_out_start = start_seconds + duration - fade_out
filters.append(f"afade=t=out:st={fade_out_start:.4f}:d={fade_out}")

Apply the same correction in both _mix() and _duck(). Temporary workarounds are to remove fade_out_seconds, or place a single afade filter after amix using the final output timeline.

GitHub Issue #347
Troubleshooting
Why does hyperframes_compose report "render exited 0 but output file missing" even though the MP4 was rendered successfully?

A relative output_path is resolved against two different working directories. The render subprocess runs with cwd=workspace, so it writes the file under the workspace, but the subsequent output_path.exists() check runs against the tool process's CWD, usually the repository root. Fix it by resolving the output path once to an absolute path before rendering:

output_path = Path(
    inputs.get("output_path") or (workspace / "renders" / "final.mp4")
).expanduser().resolve()

Use that same absolute path for both the --output argument and the existence check. As a workaround, pass an absolute output_path, or look for the successfully rendered file under <workspace>/<relative-output> instead of treating the message as a real render failure.

GitHub Issue #360
Troubleshooting
How to fix FFmpeg chromakey overlay producing a 1x1 solid-color video and losing the subject?

The background stays 1x1 because scale=iw:ih uses the color source's own dimensions, and overlay uses the size of its first input. Scale the 1x1 background to the foreground frame with scale2ref before overlaying:

ffmpeg -y -f lavfi -i "color=c=0x0E172A:size=1x1" -i frame.png \
  -filter_complex "[0:v][1:v]scale2ref[bg][fgbase];[fgbase]chromakey=color=0x00FF00:similarity=0.3:blend=0.08[fg];[bg][fg]overlay=0:0" \
  -frames:v 1 out.png

Equivalent filter graph:

[0:v][1:v]scale2ref[bg][fgbase];
[fgbase]chromakey=color=0x00FF00:similarity=0.3:blend=0.08[fg];
[bg][fg]overlay=0:0

In GreenScreenProcessor._process_chromakey, replace the no-op [0:v]scale=iw:ih[bg] step with this scale2ref flow. Verify the result with:

ffprobe -v quiet -show_entries stream=width,height -of csv=p=0 out.png

It should report the source frame dimensions, such as 320,240, instead of 1,1.

GitHub Issue #336
Troubleshooting
How to fix corpus_builder reporting success with an empty index.jsonl when all CLIP embeddings fail on transformers 5?

This occurs because transformers>=5.0 changed the return type of get_image_features(), while lib/clip_embedder.py expects the pre-5.x tensor API. Every image then fails, but older corpus_builder versions return success=True even when clips_added=0.

Immediate workaround: downgrade Transformers to the latest 4.x release:

pip install "transformers<5"

For example:

pip install "transformers==4.46.3"

Then delete the empty index.jsonl and rerun corpus_builder. Confirm that the result reports clips_added > 0 before running clip_search or retrieval.

Permanent fixes:

1. Pin the dependency in requirements.txt or the install instructions:

transformers<5

2. Update lib/clip_embedder.py to handle the transformers>=5 return value by unwrapping the tensor or pooler_output as appropriate.
3. Make corpus_builder.execute() fail closed when no candidate is embedded:

if candidates_seen > 0 and clips_added == 0:
    return ToolResult(
        success=False,
        error=f"All {candidates_seen} candidates failed to embed",
        data={"errors": errors},
    )

A high failure-ratio check can also be added, but the essential condition is that a non-empty run producing zero clips must not report success or write a valid-looking empty corpus index.

GitHub Issue #357
Troubleshooting
How do I fix WAN 2.2 text-to-video producing flickering, unrelated stills inside a valid MP4 in ComfyUI?

Use a temporal video latent instead of an image latent. In the bundled wan22-t2v-4step.json, replace node 11, EmptyLatentImage, with EmptyHunyuanLatentVideo:

"11": {
  "class_type": "EmptyHunyuanLatentVideo",
  "inputs": {
    "width": 832,
    "height": 480,
    "length": 81,
    "batch_size": 1
  }
}

Then update ComfyUIVideo._build_t2v so it no longer sets batch_size to the frame count. It must patch length instead:

node_11["inputs"].update({
    "width": width,
    "height": height,
    "length": num_frames,
    "batch_size": 1,
})

EmptyLatentImage(batch_size=81) creates 81 independent images, causing the strobe effect. EmptyHunyuanLatentVideo(length=81, batch_size=1) creates one coherent 81-frame video latent. This matches ComfyUI's official WAN 2.2 t2v template.

ffprobe cannot detect this problem because the MP4 container, codec, duration, and frame count are valid. Verify by watching the output or comparing adjacent frames; a broken render shows large frame-to-frame differences, while coherent motion shows small, smooth differences. Apply the workflow/builder PR if using a maintained release, and optionally add the runtime strobing detection from the companion validation PR.

GitHub Issue #526