A Digital Products Agent Skill.
Assemble short promo videos from raw clips — portrait, square, or
landscape — with optional AI-generated soundtrack and branded
intro / outro.
Born at AI-DAY II, the in-house hackathon at FUNKE Digital Products in Berlin, where a portrait hackathon promo was cut end-to-end with Claude, ffmpeg, Blender, and Suno. This skill captures that pipeline so it can be reused by anyone — inside Digital Products and beyond.
- Asks a short set of questions (format, clips folder, length, music, intro, outro).
- Builds a
selection.json(clips, cue points, speed, fixed-vs-free) — via chat or via a generated browser gallery with per-clip sliders and one-click export. Drift against newly added / removed clips is auto-detected. - Runs a deterministic ffmpeg pipeline:
normalize → trim → concat → overlay → mux → fade-out. - Optional AI soundtrack via Suno (Song-Builder sub-agent).
- Optional intro / outro via Blender MCP (Blender-Builder sub-agent; no bundled scene).
Implements the open Agent Skills standard — runs in Claude Code, OpenAI Codex, Gemini CLI, Cursor, GitHub Copilot, Cline, and 30+ other hosts.
- Python 3.9+
ffmpegon PATH, built withlibx264,aac, and — for alpha-channel intro / outro MOVs —prores_ks.- macOS:
brew install ffmpeg - Debian / Ubuntu:
sudo apt install ffmpeg - Windows:
choco install ffmpeg(orwinget install Gyan.FFmpeg)
- macOS:
Uses the open skills CLI. Detects your installed agent hosts and symlinks the skill into each.
# install for every host the CLI detects on your system
npx skills add bbartosch/skill-promo-video
# or target specific hosts
npx skills add bbartosch/skill-promo-video -a claude-code -a codex
# global install (user home instead of current project)
npx skills add bbartosch/skill-promo-video -gWhere the files land:
| Host | Project scope | Global (-g) |
|---|---|---|
| Claude Code | .claude/skills/promo-video/ |
~/.claude/skills/promo-video/ |
| Cursor · Codex · Cline · Gemini CLI | .agents/skills/promo-video/ |
host-specific (~/.cursor/skills/, ~/.codex/skills/, …) |
| Others | per-host path, see agentskills.io |
For hosts not yet in the skills CLI, or when you want full control:
git clone https://github.com/bbartosch/skill-promo-video \
<your-project>/.claude/skills/promo-videoSwap the target path for your agent host (see table above).
npx skills add does not install Python deps. Run this once after
either install method, against the skill directory on your disk:
pip install -r <skill-dir>/requirements.txtInstalls jsonschema, requests, and python-dotenv — all small,
pure-Python.
Optional: copy .env.example to .env at your project root and fill in
SUNO_API_KEY if you want AI-generated soundtracks.
Open a session in your agent and say "build me a promo video from ./clips/". The agent should discover the skill and start the dialog — asking about format, clip folder, length, music, intro, and outro.
If you already have a selection.json, skip the agent and drive the
pipeline directly:
python scripts/build.py my_selection.json --out output/my_promo.mp4Same for the gallery frontend and the drift check — see the sections below.
promo-video/
├── SKILL.md # Instructions the agent reads
├── README.md # You are here
├── LICENSE.txt # CC BY 4.0
├── requirements.txt
├── .env.example
├── scripts/ # Python pipeline
│ ├── _ffmpeg.py
│ ├── normalize.py
│ ├── trim.py
│ ├── concat.py
│ ├── overlay.py
│ ├── mux_audio.py
│ ├── build.py
│ ├── gallery.py # Generates the browser selection UI
│ ├── clip_diff.py # Drift check vs. last gallery snapshot
│ └── music/
│ ├── __init__.py
│ ├── base.py
│ └── suno.py
├── references/ # Loaded by the agent on demand
│ ├── dialog_flow.md
│ ├── director_mode.md
│ ├── ffmpeg_patterns.md
│ ├── blender_mcp.md
│ ├── blender_builder_agent.md
│ ├── song_builder_agent.md
│ └── suno_api.md
├── templates/
│ └── selection.schema.json
└── examples/
└── aiday2_v10.json # The original AI-DAY II promo as a replayable spec
The agent walks you through a short Q&A, builds selection.json, then
renders. Best for quick jobs.
Four sequential roles share selection.json as state:
Narrator → Cutter → Composer → Supervisor
story clips & soundtrack review &
arc cue points build
Enable by answering "yes" to the director-mode question or by saying
"walk me through like a producer". See
references/director_mode.md.
Clip selection is the most hands-on step. You have two tools — pick whichever fits:
-
Visual gallery (
scripts/gallery.py): generatesgallery/gallery.htmlwith a thumbnail per clip (ffmpeg-extracted JPG), IN/OUT sliders, speed slider, range-preview playback, and a one-click "Export selection.json" button. Best when you have >10 clips or want to see frames before committing to cues. State is cached in the browser's localStorage so you can close and come back.python scripts/gallery.py path/to/clips \ --resolution 1080x1920 --fps 30 --target-length 30 # then open gallery/gallery.htmlScales to hundreds of clips. Each row starts as a static thumbnail
<img>; a<video>element is only mounted when you click a clip, seek with a slider, or hit "Play range". That keeps the DOM light and avoids firing metadata requests for every file up front.Adding clips later? Just re-run
gallery.pywith the sameclips_dir. Existing thumbnails are reused (pass--forceto regenerate).gallery.htmlis rewritten with all current clips, and your localStorage selections/cues for existing clips survive untouched. Clips removed from the folder appear in a dismissable "stale state" banner at the top so you're not guessing where your data went.How the agent detects drift. Every
gallery.pyrun writes a tiny snapshot (gallery/.clips_snapshot.json— just filenames, sizes, mtimes). When you come back to the agent with an existing project, both the linear and Director-mode flows runscripts/clip_diff.py <clips_dir>as their first step and tell you exactly what's new, removed, or modified — so nothing gets silently skipped.python scripts/clip_diff.py path/to/clips # exit 0 = in sync, 1 = drift (prints a summary), 2 = no snapshot yet -
Inline dialog: the agent walks you through each clip in chat, accepting entries like
3.1-7.6 @ 1.5x. Works without a browser. Shortcuts:next,skip,fast,back, andgallery(to bail out and switch to the visual tool).
Both paths produce the same selection.json. Both are available in the
linear dialog and in Director mode's Cutter role.
Copy .env.example to .env at your project root. Nothing is required
for basic operation — keys only unlock optional features:
| Key | Feature |
|---|---|
SUNO_API_KEY |
Generate a soundtrack via Suno |
SUNO_BASE_URL |
Override Suno base URL (optional, for proxies) |
selection.json can override provider choice explicitly — see
references/suno_api.md.
examples/aiday2_v10.json is the AI-DAY II
portrait promo as a sample spec: 38 clips (9 with hand-set cue points
and speed), a 5-second branded intro, a 3-second brand-beat outro, and
a pre-cut soundtrack. Clip filenames and asset paths are generic
placeholders — copy the file, drop your own footage into clips/ and
your own intro/outro/music into assets/, and run the build. Use it as
a reference when writing your own selection.json.
Creative Commons Attribution 4.0 International (CC BY 4.0) — see
LICENSE.txt. You may use, adapt, and redistribute this
skill (including for commercial purposes) as long as you give appropriate
credit to FUNKE Digital Products.
Suggested attribution:
"promo-video skill by FUNKE Digital Products, licensed under CC BY 4.0."