Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions .agents/skills/zapcap-captions/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
---
name: zapcap-captions
description: Add animated, word-synced styled captions to a video with the ZapCap API. Use when the user wants viral/social caption styles (Hormozi, Beast, Devin, ...), word-level highlight captions burned into a video, emoji captions, or translated+captioned variants of the same video. Backs the OpenMontage `zapcap_captions` subtitle provider.
metadata:
openclaw:
requires:
env:
- ZAPCAP_API_KEY
primaryEnv: ZAPCAP_API_KEY
---

# ZapCap Captions

ZapCap is a captioning API. You upload a video, choose a styled caption
*template*, and ZapCap transcribes the audio and renders animated, word-synced
subtitles burned into the video — the fastest path to social-ready captions
(TikTok/Reels/Shorts).

This skill backs the `zapcap_captions` tool (`tools/subtitle/zapcap_captions.py`),
capability `subtitle`, provider `zapcap`.

## When to use it (vs. the local subtitle tools)

| Need | Tool |
|------|------|
| Viral styled, animated, word-highlight captions burned in | **`zapcap_captions`** (this) |
| Word-by-word caption burn locally via Remotion | `remotion_caption_burn` |
| Plain SRT/VTT/caption JSON from existing transcript segments | `subtitle_gen` |

ZapCap needs an **audio track with speech** — it transcribes to make captions.
Don't use it for silent/music-only videos. Max video length is **30 minutes**.

## Configuration

```bash
ZAPCAP_API_KEY=... # required (sent as the x-api-key header)
```

Calls go to `https://api.zapcap.ai`. This matches the `zapcap-mcp` server's env
var, so one `.env` configures both the OpenMontage tool and the MCP.

## The flow (what the tool does on `action="caption"`)

1. **Upload** — `POST /videos` (local file, multipart `file`) or
`POST /videos/url` (`{url}`) → `videoId`.
2. **Create task** — `POST /videos/{videoId}/task` with `templateId`
(+ options) → `taskId`. Set `autoApprove: true` so rendering starts without
a manual transcript-approval step (the tool defaults to this).
3. **Poll** — `GET /videos/{videoId}/task/{taskId}` until `status` is
`completed`. Statuses: `pending → transcribing → transcriptionCompleted →
rendering → completed` (or `failed`).
4. **Download** — stream `downloadUrl` from the completed task to `output_path`.

Auth on every call: header `x-api-key: $ZAPCAP_API_KEY`.

## Templates

List them first (names are not stable IDs — always resolve):

```python
from tools.subtitle.zapcap_captions import ZapCapCaptions
tpl = ZapCapCaptions().execute({"action": "list_templates"})
# tpl.data["templates"] -> [{id, name, categories}, ...]
```

Popular templates (categories: `animated`, `highlighted`, `basic`):
`Hormozi 1` (animated+highlighted), `Beast`, `Devin`, `Ella`, `Tracy` (basic),
`Karl`, `Maya`, `Hormozi 2/3/4/5`. The tool accepts either `template_id`
(UUID) or `template_name` (resolved case-insensitively via `/templates`).

## OpenMontage usage

Full caption of a local file (the common case):

```python
from tools.subtitle.zapcap_captions import ZapCapCaptions

res = ZapCapCaptions().execute({
"action": "caption", # default; can omit
"input_path": "projects/demo/renders/final.mp4",
"template_name": "Hormozi 1", # or template_id="a51c5222-..."
"language": "en", # omit to auto-detect
"auto_approve": True,
"output_path": "projects/demo/renders/final_captioned.mp4",
"timeout_seconds": 600,
})
# res.data -> {videoId, taskId, templateId, downloadUrl, transcriptUrl, output, ...}
# res.artifacts -> ["projects/demo/renders/final_captioned.mp4"]
```

Caption a public URL instead: pass `video_url` instead of `input_path`.

## renderOptions (subtitle appearance)

Pass any of these under `render_options`; all optional:

```python
"render_options": {
"subsOptions": {
"emoji": True, "emojiAnimation": True,
"emphasizeKeywords": True, # highlight key words per template style
"animation": True, "punctuation": False,
"displayWords": 4, # words shown at once (guidance)
},
"styleOptions": {
"top": 40, # Y position, % of height (higher = lower)
"fontUppercase": True, "fontSize": 46, "fontWeight": 900,
"fontColor": "#ffffff",
"fontShadow": "l", # none|s|m|l
"stroke": "s", "strokeColor": "#000000",
"fontId": "<uploaded font id>", # optional, from POST /fonts
},
"highlightOptions": { # colors used for emphasized keywords
"randomColourOne": "#2bf82a",
"randomColourTwo": "#fdfa14",
"randomColourThree": "#f01916",
},
}
```

## Translation & fan-out (transcribe once, render many)

To caption one video into several languages or templates **without paying to
transcribe N times**, transcribe once and reuse the transcript:

```python
tool = ZapCapCaptions()
# 1. upload + create first task, but only wait for transcription
up = tool.execute({"action": "upload", "input_path": "in.mp4"})
vid = up.data["videoId"]
first = tool.execute({"action": "create_task", "video_id": vid,
"template_name": "Hormozi 1", "language": "en"})
# (poll first.data["taskId"] to transcriptionCompleted with get_task)

# 2. fan out: reuse the transcript, translate per target
for lang in ["es", "fr", "de"]:
tool.execute({"action": "create_task", "video_id": vid,
"template_name": "Hormozi 1",
"transcript_task_id": first.data["taskId"],
"translate_to": lang, "auto_approve": True})
```

The `mcp__zapcap__*` MCP tools (`upload_video_*`, `create_video_task`,
`wait_for_task`) expose the same flow and `wait_for_task` supports
`waitFor="transcriptionCompleted"` for the fan-out barrier.

## Pipelines that benefit

`clip-factory`, `podcast-repurpose`, `talking-head`, and `localization-dub`
all produce speech-driven social clips where styled burned-in captions are the
norm. Offer `zapcap_captions` at the edit/compose stage for those briefs as an
alternative to `remotion_caption_burn` when the user wants ZapCap's template
styles.

## Failure modes

- `401/403` → bad or missing `ZAPCAP_API_KEY`, or no API credits / wrong plan.
- task `status: failed` with an `error` → usually no speech, unsupported codec,
or >30 min. Re-check the source has an audio track.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ PEXELS_API_KEY= # Pexels stock footage/images (free)
PIXABAY_API_KEY= # Pixabay stock footage/images (free)
UNSPLASH_ACCESS_KEY= # Unsplash stock images (free developer key)

# --- Captions (styled subtitles) ---
ZAPCAP_API_KEY= # ZapCap captioning API — animated word-synced caption templates (Hormozi, Beast, ...)
# Get one at https://platform.zapcap.ai/dashboard/api-key (Pro plan + credits)

# --- Analysis ---
HF_TOKEN= # HuggingFace token — enables speaker diarization in transcriber

Expand Down
1 change: 1 addition & 0 deletions AGENT_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ The `.agents/skills/` directory is large. When you're not coming in through a to
| **Image generation** | `bfl-api`, `flux-best-practices` |
| **Video generation** | `seedance-2-0` (preferred premium default — cinematic, trailer, multi-shot, synced audio, lip-sync), `ai-video-gen`, `ltx2` |
| **Audio** | `elevenlabs`, `music`, `sound-effects`, `acestep`, `text-to-speech`, `setup-api-key` |
| **Captions / subtitles** | `zapcap-captions` (styled/animated word-synced caption templates via the `zapcap_captions` tool) |
| **Avatar / lip-sync** | `avatar-video`, `heygen`, `create-video`, `faceswap`, `video-translate`, `speech-to-text`, `agents` |
| **Capture** | `playwright-recording` (browser flows), `ffmpeg` (post) |
| **Visualization** | `beautiful-mermaid`, `d3-viz`, `manim-composer`, `manimce-best-practices`, `manimgl-best-practices` |
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ You don't need paid API keys to make real videos. Out of the box, `make setup` g
| **Composition (React)** | Remotion | React-based rendering — spring-animated image scenes, text cards, stat cards, charts, TikTok-style word-level captions, TalkingHead |
| **Composition (HTML/GSAP)** | HyperFrames | HTML/CSS/GSAP rendering — kinetic typography, product promos, launch reels, registry blocks, website-to-video, rigged SVG character animation |
| **Post-production** | FFmpeg | Encoding, subtitle burn-in, audio mixing, color grading |
| **Subtitles** | Built-in | Auto-generated captions with word-level timing |
| **Subtitles** | Built-in + ZapCap | Auto-generated captions with word-level timing; optional styled/animated caption templates (Hormozi, Beast, ...) via ZapCap |

OpenMontage picks between Remotion and HyperFrames at proposal time (locked as `render_runtime`). Remotion is the default for data-driven explainers and anything using the existing React scene stack; HyperFrames is the default for motion-graphics-heavy briefs that express naturally as HTML + GSAP, including the `character-animation` pipeline's SVG/GSAP rig output. See `skills/core/hyperframes.md` for the full decision matrix.

Expand Down
54 changes: 54 additions & 0 deletions docs/PROVIDERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Everything you need to know about every provider in OpenMontage — setup instru
| 8 | **$12/month** | Runway | Gen-4 video — highest quality AI video |
| 9 | **pay-as-you-go** | HeyGen | Avatar videos, multi-model video gateway |
| 10 | **pay-as-you-go** | Suno | Full song generation with vocals and lyrics |
| 10b | **Pro plan + credits** | ZapCap | Animated/word-synced styled captions (Hormozi, Beast, ...) |
| 11 | **$0 + GPU** | Local video gen | WAN 2.1, Hunyuan, CogVideo, LTX — free, offline |
| 12 | **$0 + GPU** | Local Diffusion | Stable Diffusion images — free, offline |

Expand Down Expand Up @@ -50,6 +51,9 @@ HEYGEN_API_KEY= # HeyGen avatar video gateway
RUNWAY_API_KEY= # Runway Gen-4 video (direct)
SUNO_API_KEY= # Suno music generation

# CAPTIONS (styled subtitles)
ZAPCAP_API_KEY= # ZapCap animated/word-synced caption templates

# LOCAL (no keys needed — just GPU + install)
VIDEO_GEN_LOCAL_ENABLED= # Set to "true" for local video gen
VIDEO_GEN_LOCAL_MODEL= # wan2.1-1.3b, wan2.1-14b, hunyuan-1.5, ltx2-local, cogvideo-5b
Expand Down Expand Up @@ -207,6 +211,56 @@ Doubao Speech 2.0 is billed by character package or usage in Volcengine. OpenMon

---

### ZapCap — Caption Templates

> **Animated, word-synced caption templates.** Upload a video, pick a template (Hormozi, Beast, Devin, ...), and ZapCap transcribes and burns in styled subtitles.

**Tools unlocked:** `zapcap_captions`
**Env var:** `ZAPCAP_API_KEY`
**Layer 3 skill:** `.agents/skills/zapcap-captions/SKILL.md`

#### Setup

1. Subscribe to a ZapCap Pro plan and buy API credits at [platform.zapcap.ai](https://platform.zapcap.ai/dashboard/billing).
2. Copy your key from the [API key page](https://platform.zapcap.ai/dashboard/api-key).
3. Add to `.env`: `ZAPCAP_API_KEY=your-key-here`

#### What It Is Best For

- Viral caption styles (Hormozi, Beast, Devin, Ella, ...) out of the box
- Word-level highlight + emoji captions burned into the video
- Translating + captioning the same video into many languages (transcribe once, fan out)
- Speech-driven social clips (`clip-factory`, `podcast-repurpose`, `talking-head`, `localization-dub`)

Needs a speech audio track (it transcribes to caption). Max length 30 min.
For local/offline burn-in use `remotion_caption_burn`; for plain SRT/VTT use
`subtitle_gen`.

#### Usage

```python
from tools.subtitle.zapcap_captions import ZapCapCaptions

res = ZapCapCaptions().execute({
"input_path": "projects/demo/renders/final.mp4",
"template_name": "Hormozi 1", # or template_id="a51c5222-..."
"output_path": "projects/demo/renders/final_captioned.mp4",
})
# res.artifacts -> ["projects/demo/renders/final_captioned.mp4"]
```

`action="list_templates"` lists templates; `render_options` overrides subtitle
appearance; `translate_to` + `transcript_task_id` drive multi-language fan-out.
See the Layer 3 skill for the full schema.

#### Pricing

Billed in ZapCap API credits (Pro plan + credits required). Cost scales with
video minutes processed. The tool does not estimate USD; track credits on the
[ZapCap dashboard](https://platform.zapcap.ai/dashboard/billing).

---

### Google — TTS + Imagen (Shared Key)

> **One key, two tools.** Google Cloud TTS has 700+ voices in 50+ languages — the strongest localization option. Imagen 4 generates high-quality images.
Expand Down
Loading