O OpenMontage

Composition Runtimes#

OpenMontage dispatches video composition through the video_compose tool using one of three engines. The chosen runtime is locked at the proposal stage in proposal_packet.production_plan.render_runtime, carried verbatim into edit_decisions.render_runtime, and enforced at render time. Silent swaps are blocked by the tool and flagged during review.

See the Tool System for the video_compose contract and the Pipeline System for how proposal and edit stages produce these artifacts.

The Three Runtimes#

Runtime Engine Primary Use Cases Requirements
remotion React + Remotion 4 Data-driven explainers, text/stat cards, charts, spring-animated scenes, TalkingHead, CinematicRenderer, word-level captions Node.js 18+, remotion-composer/ installed
hyperframes HTML/CSS/GSAP (via npx) Kinetic typography, product promos, launch reels, SVG/GSAP character rigs, website-to-video Node.js ≥ 22, FFmpeg, npx
ffmpeg FFmpeg CLI Pure concat/trim, subtitle burn-in FFmpeg binary (always present)

Remotion#

Remotion lives in the standalone remotion-composer/ subproject (React 18 + Remotion 4.0 + TypeScript). It renders component-based scenes such as text_card, stat_card, bar/line/pie charts, and animated image sequences with spring physics. video_compose routes to _remotion_render when edit_decisions.render_runtime is set to remotion.

HyperFrames#

HyperFrames is invoked via npx hyperframes (no monorepo checkout). The driver tools/video/hyperframes_compose.py materializes a workspace under projects/<name>/hyperframes/, runs lint → validate → render, and outputs renders/final.mp4. It is the default for motion-graphics-heavy briefs and the character-animation pipeline's rigged SVG characters. video_compose routes to _render_via_hyperframes for this runtime.

FFmpeg#

FFmpeg handles simple cuts and post-hoc operations such as subtitle burn-in. It is the fallback when no composition engine is required. video_compose routes to _render_via_ffmpeg when edit_decisions.render_runtime is ffmpeg.

video_compose.get_info() reports live availability:

"render_engines": {
  "ffmpeg": true,
  "remotion": <bool>,
  "hyperframes": <bool>
}

Routing Logic#

video_compose.execute({"operation": "render", ...}) (or the legacy compose operation) reads the locked render_runtime value from edit_decisions and dispatches accordingly. The tool returns a structured blocker if the locked runtime is unavailable. Runtime swaps are never performed silently; the agent must obtain explicit approval and log the decision before changing the value.

Locking at Proposal#

The runtime is selected and locked during the proposal stage. It is recorded in proposal_packet.production_plan.render_runtime together with renderer_family and delivery_promise. The value is copied unchanged into edit_decisions.render_runtime and must match at compose time. schemas/artifacts/edit_decisions.schema.json and proposal_packet.schema.json enforce the enum ["remotion", "hyperframes", "ffmpeg"].

When both Remotion and HyperFrames are available, the agent must present both options before locking: a one-sentence description of what each is best at for the brief, an honest tradeoff, and a recommendation tied to the delivery_promise. The full shortlist is recorded as options_considered in a render_runtime_selection entry in decision_log.json.

Governance Rules#

  • render_runtime is locked at proposal and must not change without a logged decision.
  • Motion-required deliveries (delivery_promise.motion_required: true) forbid still-image or FFmpeg-only fallbacks that alter the approved character of the deliverable.
  • composition_validator and final review compare proposal_packet and edit_decisions; mismatches are reported as runtime_swap_detected.
  • If only one runtime is present, the agent must state it explicitly and record the unavailable option as rejected_because: "runtime not available on this machine".
Warning

A log entry that considers only one runtime when both were available is treated as a critical reviewer finding. All production paths that reach video_compose must respect the locked value.

See Architecture for the high-level flow and Running Pipelines for how checkpoints carry the locked runtime forward.