Short-form, explainer, and demo video generation via a key-optional 3-tier router. Composes scripts, oma-voice narration, oma-image/oma-slide/stock visuals, key-free captions, and a per-run agent-authored Remotion composition (always-latest Remotion + remotion-dev/skills) into reproducible run directories. Routes three modes — shorts/reels (9:16), explainer (16:9 README/code/data), and demo/walkthrough (screen capture from human-recorded video). Use for video, shorts, reels, short-form, demo, explainer, walkthrough, screencast, web capture, video generation, 영상, 숏폼, 쇼츠, 릴스, 데모, 설명 영상.
64
75%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.agents/skills/oma-video/SKILL.mdGenerate finished .mp4 videos through a key-optional, 3-tier (CLI-first / MCP / guided) provider router while preserving deterministic asset buses (script -> timing -> render-spec), reproducible manifests, cost controls, and capture-path safety.
--mode shorts, 9:16)--mode explainer, 16:9 / 9:16)--mode demo --source file, 16:9)--capture <path>; --source web --url <url> supplies URL context.render-spec.json--format json)oma-imageoma-slide (this skill calls it internally for explainer frames)oma-voice--source web); live streaming is out of scopeoma-explanationdemo --source file: a screen-capture file path (--capture) or Cap availabilitydemo --source web, supply --url as context and --capture <path> as recording input; without a recording the command returns guided capture instructions..agents/results/videos/<timestamp>-<shortid>-<mode>/script.json, timing.json, render-spec.jsonaudio/, visuals/, captions.srt / captions.vtt, the rendered <mode>-<slug>.mp4manifest.json with providers, asset hashes, cost breakdown, and exit codeoutputs:
- name: video
description: rendered <mode>-<slug>.mp4 in the run directory
artifact: ".agents/results/videos/*/*.mp4"
required: true
- name: manifest
description: reproducibility record (providers, asset sha256 hashes, cost breakdown, exit code)
artifact: ".agents/results/videos/*/manifest.json"
required: true
- name: render-spec
description: deterministic compute boundary consumed by `oma video render <runDir>`
artifact: ".agents/results/videos/*/render-spec.json"
required: true
- name: captions
description: key-free caption tracks aligned to timing.json
artifact: ".agents/results/videos/*/captions.srt"
required: falseoma video generate CLI + central error module (exit codes aligned with oma search fetch)<runDir>/remotion/ scaffolded by oma video compose on the always-latest toolchain (~/.cache/oma-video/remotion/<ver>/); the composition is agent-authored per run following remotion-dev/skills (resources/remotion-authoring/)resources/vendor-matrix.md, resources/execution-protocol.md, resources/prompt-tips.md, and the video: section of .agents/oma-config.yamldemo, confirm a capture path exists (or Cap is available); otherwise enter the guided protocol.video: section of .agents/oma-config.yaml -> env vars -> CLI flags; check output path safety and limits.demo, ingest --capture <path> or provide guided capture instructions. --source web requires --url as context; it does not start a browser recorder.demo --source file has no capture and Cap is unavailable, emit the guided capture protocol and stop (exit code maps to capture-required).order; only chain exhaustion is a stage failure.oma video compose <runDir> refreshes the toolchain + remotion-dev/skills (throttled) and scaffolds <runDir>/remotion/; you author src/Root.tsx per its AUTHORING.md and resources/remotion-authoring/<mode>.md, then oma video render <runDir>. A tsc/render failure is a composition bug: re-read the skills, fix, re-render (no fixed cap; stop only after two consecutive attempts without progress and report).oma video doctor --install once online; fall back to the MPT compositor where applicable (MPT itself needs a one-time oma video doctor --install-mpt).TODO(oma-deferred): whisper-cpp).<mode>-<slug>.mp4 and manifest.json exist in the run directory; all schemas validate.| Action | SSL primitive | Evidence |
|---|---|---|
| Validate brief + mode | VALIDATE | Clarification protocol, mode inference |
| Select provider strategy | SELECT | Vendor matrix, providers.*.order, availability |
| Read brief / capture | READ | Brief text, --capture path |
| Generate script | CALL_TOOL | AgentScriptProvider -> script.json |
| Synthesize narration + timing | CALL_TOOL | oma-voice -> audio/*.wav + timing.json |
| Produce visuals | CALL_TOOL | oma-image / oma-slide / stock -> visuals/* |
| Build captions | WRITE | key-free captions.srt / .vtt from timing |
| Compose render-spec | WRITE | render-spec.json (determinism boundary) |
| Render video | CALL_TOOL | Remotion / MPT compositor -> <mode>-<slug>.mp4 |
| Validate result | VALIDATE | Schema parse, manifest hashes, exit code |
| Report output | NOTIFY | Run-dir + mp4 path summary |
oma video generate, oma video doctor, oma video provider list, oma video renderresources/remotion-authoring/), prompt tips, vendor matrix, video configoma video doctor
oma video generate "<brief>" --mode shorts --aspect auto --captions tiktok --output jsonExplainer from a README, with a deterministic seed:
oma video generate "explain this project" --mode explainer --aspect 16:9 --seed 42 --output-dir ./outDemo from a screen capture:
oma video generate "feature walkthrough" --mode demo --capture <absolute-path>.mp4Deterministic re-render from an existing run:
oma video render .agents/results/videos/20260603-143052-ab12cd-shorts| Scope | Resource target |
|---|---|
LOCAL_FS | Briefs, captures, assets, render-spec, run dir, manifests |
PROCESS | oma-image / oma-slide CLIs, Remotion / MPT, Cap CLI, Browser web-capture driver (subprocess) |
NETWORK | Voicebox MCP (localhost), oma-image vendor APIs, the user-supplied --url for web capture (masked in logs/manifest), optional Pexels / Pixelle / RunningHub |
CREDENTIALS | oma-image vendor auth, optional PEXELS_API_KEY / RUNNINGHUB_API_KEY. Web capture handles NO credentials — a human logs in if the flow needs it; nothing is stored or printed. |
$PWD (or --allow-external-out is set).demo --source file: the capture path exists, is absolute/$PWD-guarded, and is a valid format.demo --source web, supply --url as context and --capture <path> as recording input; without a recording the command returns guided capture instructions.Clarification Protocol below.cost.guardrail_usd ($0.20, configurable) or --max-usd. --yes / OMA_VIDEO_YES=1 bypass. Local/free paths carry zero cost.$PWD require --allow-external-out. --capture is absolutized, $PWD-guarded, and format-validated; external assets are copied into the run dir and hashed (no URL refs).render-spec.json + asset files (+ seed + embedded Pretendard font) are the determinism boundary. oma video doctor --install fetches the Pretendard woff2 once; if offline, the render gracefully falls back to system fonts, and byte-identical output across machines is only guaranteed once the font is present. Re-rendering the same render-spec is byte-stable; OMA_VIDEO_MOCK=1 replays golden fixtures.limits.max_duration_sec = 180, limits.max_scenes = 40 (wall-time + memory bound).--max-usd.--capture <path>; use Cap or another available screen recorder..agents/results/videos/<run>/ accumulates one directory per run (assets + mp4 + manifest) and is never auto-pruned; the user deletes old run directories manually.oma search fetch (0 ok, 1 generic, 2 safety, 3 not-found, 4 invalid-input, 5 auth-required, 6 timeout).Before invoking oma video generate, the calling agent runs this checklist. If any answer is "no / unknown", clarify or infer-and-confirm with the user first.
Required signal (must be present or inferable):
demo --source web — a --url)demo: --source file (a --capture path) or --source web (a --url)? For --source web, state up front that a human drives the on-screen flow and that the tool never automates any login.Strongly recommended (ask if absent AND not inferable):
9:16 (shorts/reels), 16:9 (explainer/demo), 1:1, or auto (snaps to the mode default).tiktok (centered, static windowed cues), lower-third, or none.auto (derived from the script).none; music upbeat / calm / none. The default voice is none → a silent video with estimated caption timing. Pass --voice <profile> (a Voicebox profile) whenever narration is expected. Music is rendered offline by Strudel and mixed at −18 dB; it needs a one-time oma video doctor --install-strudel and degrades to no music without it.Amplification shortcut. For a one-line brief (e.g. "shorts about Jeju coffee"), do not pop a questionnaire if the request is genuinely simple. Instead amplify inline and show the user the inferred plan before invoking:
User: "make a short about Jeju coffee" Agent: "I'll generate this as: mode
shorts, 9:16, ~30s, oma-image stills with Ken Burns, TikTok captions, localeen, calm music. Proceed, or adjust mode/aspect/voice?"
Skip clarification when the user authored a full brief (mode + topic + aspect + captions). Respect their flags verbatim.
Output language. Narration and on-screen text are authored in the requested locale. Image-generation prompts passed to oma-image are sent in English (image models are trained predominantly on English captions); translate the user's request and show the translated version during amplification.
| Mode | Aspect | Source | Default visual | Compositor | Output |
|---|---|---|---|---|---|
shorts | 9:16 | synthetic (topic) | oma-image stills + Ken Burns; Pexels (key) · Pixelle AIGC (key) opt | Remotion · MPT alt | shorts-<slug>.mp4 |
explainer | 16:9 / 9:16 | README · code · data | oma-slide frames + oma-image diagrams + code | Remotion (deterministic) | explainer-<slug>.mp4 |
demo | 16:9 | --source file (Cap / capture file) · --source web (URL context + guided capture) | raw footage (default) · Remotion intro · zoom · callouts (--polish) | Remotion polish | demo-<slug>.mp4 |
| Tier | Surface | Providers | Trigger |
|---|---|---|---|
| 1 | CLI-first (subprocess, deterministic) | Remotion render, MPT, oma-image, oma-slide, oma-voice | always available (key-free defaults) |
| 2 | MCP | Voicebox MCP (voice/timing), Pixelle-MCP (AIGC, off by default) | MCP server reachable; Pixelle needs explicit consent + key |
| 3 | Guided (human-in-the-loop) | Cap recording and guided capture with --capture <path> | demo mode; supply a recording or follow the capture instructions |
/oma-video make a 30s short about Jeju coffee
/oma-video --mode explainer --aspect 16:9 explain this project from the README
/oma-video --mode demo --source file --capture ~/recordings/walkthrough.mp4 feature demo
/oma-video --mode demo --source web --url http://localhost:3000 record my app flow
/oma-video --mode demo --source web --url <url> --ready-selector "#app" --polish onboarding clipoma video generate "<brief>" [--mode shorts|explainer|demo] \
[--aspect 9:16|16:9|1:1|auto] [--locale <lang>] \
[--captions tiktok|lower-third|none] \
[--visual auto|generate|stock|aigc|slide] \
[--voice <profile>|none] [--music upbeat|calm|cinematic|lofi|piano|none] \
[--duration <sec>|auto] [--compositor remotion|mpt] \
[--capture <path>] \
[--source file|web] [--url <url>] [--device <name>] \
[--ready-selector <css>] [--show-cursor] [--polish] \
[--capture-timeout <sec>] [--capture-stop duration:<sec>|selector:<css>] \
[--output-dir <dir>] [--allow-external-output] \
[--max-usd <n>] [--seed <n>] [--timeout 600] [-y] \
[--dry-run] [--script <path>] \
[--output text|json] [--no-brief-in-manifest]
# --script: inject the agent-authored script.json (agent-as-key). Without it the
# CLI builds its own skeleton script from the brief — always pass the script
# the agent wrote so narration/on-screen text/visual prompts are honored.
# Both source modes use guided capture; pass --capture <path> to ingest a recording.
# A human drives the on-screen flow; press ENTER to stop. NO credential automation. --url/tokens masked.
# Both source modes use guided capture; pass --capture <path> to ingest a recording.
# Browser recording controls do not start an automatic recorder; capture the flow separately.
oma video doctor # readiness report only (no install): Node/Chromium/FFmpeg · Remotion toolchain · remotion-dev/skills · Pretendard font · MPT · Voicebox MCP · oma-image vendors · Pixelle-MCP · Cap
oma video doctor --install # warm the latest Remotion toolchain (deps + Chrome Headless Shell + Pretendard) and remotion-dev/skills into ~/.cache/oma-video
oma video doctor --upgrade # force a latest check now
oma video compose <runDir> [--output json] # scaffold/refresh the run's Remotion project + print the authoring contract
oma video doctor --install-mpt # one-time: MoneyPrinterTurbo checkout (clone + venv + deps) for --compositor mpt
oma video provider list # availability + key/fallback status
oma video render <runDir> # re-render from render-spec.json (deterministic)Other skills call oma video generate --output json and parse the JSON envelope ({exitCode, runDir, manifestPath, scriptPath, renderSpecPath, warnings, error}) from stdout. There is no outputs key — read output/asset paths from the manifest at manifestPath. The deterministic boundary is render-spec.json + assets, so a downstream consumer can re-render via oma video render <runDir> without re-running script/voice/visual generation.
.agents/results/videos/
└── 20260603-143052-ab12cd-shorts/ # {timestamp}-{shortid}-{mode}
├── script.json # determinism boundary start
├── timing.json
├── render-spec.json # deterministic compute boundary
├── audio/
│ └── narration-01.wav # single narration track (ALL lines joined — not per-scene)
├── visuals/
│ └── scene-01.jpg …
├── captions.srt
├── captions.vtt
├── shorts-<slug>.mp4
└── manifest.json # reproducibility recordaudio/narration-01.wav, referenced by render-spec.audio.narration. There are no per-scene narration-NN.wav files.timing.json (voicebox-stt -> estimated; the tts-native and whisper-cpp source values are reserved but not yet wired — TODO(oma-deferred): whisper-cpp); scene boundaries and caption cues are derived from it..srt (+ .vtt) built from timing.json; render-spec.captions.file points at the .srt. The compositor renders static windowed cues — the cue active at the current frame, CSS-wrapped (no per-word animation).--music <preset> renders a BGM bed with Strudel and mixes it under narration at render-spec.audio.musicGainDb (default −18 dB). The bed is generated offline (headless Chrome + OfflineAudioContext), so it needs no key, no network, and no audio device — a 30s bed renders in well under a second.
calm (sustained pad + arpeggio), upbeat (bright plucks), cinematic (drone build to a lead), lofi (warm chords, swung ticks), piano (neoclassical arpeggio). Each preset picks its key and mode from the run seed, so the same preset sounds different run to run without a second pattern.music/bgm.wav (mixed by the compositor), music/bgm.mp3 (preview), music/bgm-raw.wav (pre-master), and music/pattern.strudel — the source that produced them, editable and re-renderable by hand.musicGainDb means the same thing for every preset. Normalisation is deliberately not loudnorm's one-pass mode, which flattens the arrangement arc.@strudel/* is AGPL-3.0-or-later while the oma CLI is MIT, so the deps are never bundled and never installed implicitly. Run oma video doctor --install-strudel once. The CLI never imports Strudel — it spawns resources/strudel/render.mjs as a subprocess, the same boundary the Remotion / web-capture projects use.audio.music stays unset (never a dangling staticFile() ref).white / pink / brown) draw from Math.random() and would break that, so the templates avoid them.Follow resources/execution-protocol.md step by step.
See resources/vendor-matrix.md for provider precheck + fallback-chain rules.
Author --script files against resources/script-schema.md (full field reference + example; schemaVersion: "1.0" is required).
Use resources/prompt-tips.md for writing effective briefs per mode.
Before submitting, run resources/checklist.md.
Remotion compositions are agent-authored per run — see resources/remotion-authoring/README.md.
The MPT fallback compositor driver lives at resources/mpt/driver.py (consumed by the CLI's mpt-project internals).
Project-specific settings: the video: section of .agents/oma-config.yaml, which oma update preserves. Shipped defaults live in the CLI (DEFAULT_VIDEO_CONFIG in cli/commands/video/config.ts) — write only the keys you change. The legacy config/video-config.yaml is no longer read by the CLI; migration 022 moves anything you had changed there into oma-config (and deletes the file when it was never edited).
Env vars: OMA_VIDEO_DEFAULT_MODE, OMA_VIDEO_DEFAULT_OUT, OMA_VIDEO_YES, PEXELS_API_KEY, RUNNINGHUB_API_KEY (+ POLLINATIONS_API_KEY via oma-image), OMA_VIDEO_MOCK.
resources/execution-protocol.mdresources/vendor-matrix.mdresources/prompt-tips.mdresources/checklist.mdresources/remotion-authoring/README.md (+ shorts.md, explainer.md, demo.md)../_shared/core/context-loading.md7721120
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.