複数の独立したローカル作業を安全性と依存関係を確認して実行計画にまとめ、対応環境では並列化やAppleシリコン向け処理の選択を支援します。
- ビルドやテストの独立した処理を並列化したいとき
- 複数段階の作業計画を安全に実行したいとき
- Appleシリコン向け処理の候補を確認したいとき
人物やキャラクター、衣装、場所の見た目を複数の場面で揃えた広告動画を作り、静止画で確認してから音声・字幕付きの映像に仕上げます。
Makes multi-scene ad videos on varg in which the same people, outfits and location stay consistent in every shot, built from real actor photos or generated characters: one profile card per actor, an empty location card, scene composites approved as stills first, then image-to-video with native dialogue audio, trimmed and captioned in one cloud render. Also covers frame and audio QA of the output and turning a reference video into a scene script. Use when a script names actors (A1, A2), a location (L1) and numbered scenes, when someone sends actor or model photos, or asks for a consistent character, the same person in every scene, a recurring mascot or brand character, a UGC or skit ad with two actors, or to remake a reference ad with new people. Not for one speaker on a stage (use varg-character-keynote), seated two-person podcast dialogue (use varg-podcast-video), music videos (use varg-music-video), or one-off images and clips (use varg-ai).
実行スコア 未検証
インストール方法を見る人物写真や生成キャラクターをもとに、複数場面で人物、衣装、場所の見た目が揃った広告動画を作ります。出演者ごとのプロフィール画像と人物のいない場所画像を用意し、それらを参照して場面ごとの静止画を生成します。静止画を確認してから、台詞を含む映像を生成し、クラウド上で長さを整え、字幕を付けてまとめます。完成後は場面のフレームや音声も確認できます。台本がない場合は、参考動画の場面構成や台詞を読み取り、生成用のシーン台本に整理します。
出演者や場所が指定された複数場面の広告、同じマスコットを繰り返し登場させる動画、2人が出演するUGC風広告や寸劇に向いています。参考広告の構成を新しい人物で作り直したい場合にも使えます。ステージ上の1人語り、座った2人のポッドキャスト、ミュージックビデオ、単発の画像や短い映像には適しません。
VARG_API_KEYまたはvarg MCP接続が必要です。静止画をまとめて確認するスクリプトにはbun、ローカルで映像を検査する場合はffmpegとffprobeを使います。
この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Turn a scene script + actor photos into a multi-scene vertical ad where characters, outfits and location stay consistent across every cut. Tested on a 5-scene, 22-second 9:16 fitness ad with two real actors in one gym.
Generation runs on varg: the varg-ai skill (sign-in, models, local and cloud render) or the varg MCP server (https://mcp.varg.ai/mcp). This skill assumes a working VARG_API_KEY or MCP connection.
Never describe characters from scratch in every scene prompt. Build a small set of frozen reference images once, then compose every scene from them.
photo A1 ──edit──> a1Card ─┐
photo A2 ──edit──> a2Card ─┼──edit──> scene1..N ──image-to-video──> vid1..N
prompt ──gen───> gymLoc ─┘
Upload the actor photos first (POST /v2/files, or the MCP upload tools) and use the returned URLs.
No actor photos? Design the cast with varg-character-design (archetypes, a model sheet per character on flat grey) and use each character's full-body crop as the profile card below.
One image-edit call per actor, from their photo:
const a1Card = Image({
prompt: {
text: "Full-body character reference card of the exact same woman from the photo: same face, same grey hair, same body shape. <age/build>. She wears <FIXED OUTFIT, described precisely>. Standing straight facing camera, neutral relaxed pose, arms at her sides. Plain light grey studio background, even soft lighting, head-to-toe framing, photorealistic",
images: [A1_PHOTO_URL],
},
model: varg.imageModel("nano_banana_2_1"), // edits when images are passed
aspectRatio: "9:16",
});
Rules that make cards work:
The pipeline was first built with Nano Banana Pro edit; nano_banana_2_1 is its successor and varg's default. For the hardest identity cases try gpt_image_2_5.
One text-to-image generation, no people:
const gymLoc = Image({
prompt: "Empty modern gym interior with huge floor-to-ceiling windows... No people. ... photorealistic, 9:16 portrait framing",
model: varg.imageModel("nano_banana_2_1"),
aspectRatio: "9:16",
});
An empty location card lets every scene reuse the same walls, light and floor without characters from a previous scene leaking in.
Every scene is one edit call with all three refs:
const SAME =
"First reference image is Woman A (<short recap of card>). Second reference image is Woman B (<short recap>). Third reference image is the gym location with huge windows. Keep both women's faces, hair, bodies and outfits exactly as in their reference cards, and the gym exactly as in the location reference.";
const scene2 = Image({
prompt: { text: `${SAME} <scene-specific framing, poses, gestures>`, images: [a1Card, a2Card, gymLoc] },
model: varg.imageModel("nano_banana_2_1"),
aspectRatio: "9:16",
});
SAME preamble is shared verbatim across all scenes. It names each reference by position ("First reference image is...") and pins identity.varg-ai).Identical prompt + params = free cache hit, both locally and server-side on api.varg.ai. This is what makes the whole pipeline cheap:
Body-part wording such as "rear" or "booty" in an image prompt can silently stall generation for ~10 min (provider moderation). Rephrase to neutral anatomy: "hips and thighs". The same words inside spoken dialogue in video prompts passed fine.
Fitness and swimwear scenes trip filters on words, not pictures: "girl" instead of "woman, 28", "tight", "bikini" and short prompts without a garment description get blocked on GPT Image 2.5, FLUX 3 and Grok, while a catalog-style prompt (adult age as a number, each garment named, an activity, "activewear brand catalog photo") passed on all six image models we tried. A block can be random: retry once, then rephrase, then route. Test log, safe-phrasing table and routing: varg-character-design → references/moderation.md.
Generate and show all stills before paying for any video. A still costs a few credits; a video clip costs ten times more or more. Approve the cheap layer first.
Standalone script pattern (<project>-images.ts, run with bun):
import { Image } from "vargai/react";
import { createVarg } from "vargai/ai";
const varg = createVarg({ apiKey: process.env.VARG_API_KEY! });
// ... define a1Card, a2Card, gymLoc, scene1..sceneN exactly as in 1.x ...
async function save(name: string, el: ReturnType<typeof Image>) {
const resolved = await el; // await triggers generation (cached)
await Bun.write(`output/<project>/${name}.png`, await resolved.file.data());
}
// cards + location first, then scenes (scenes reference the cards)
await Promise.all([save("a1-card", a1Card), save("a2-card", a2Card), save("location", gymLoc)]);
await Promise.all([save("scene1", scene1), /* ... */]);
Key facts:
Image({...}) is a lazy thenable: await resolves it, .file.data() gives the bytes. Awaited results are cached, so the later video render reuses them for free.nohup bun run <project>-images.ts > images.log 2>&1 &) and report the PID.No bun? Generate the same stills one by one with POST /v2/image (or MCP generate_image), passing the references in files. Keep the prompts identical to the ones you will use in the render.
POST /v2/render)After the stills are approved, wrap them in videos + composition and submit the whole TSX to the cloud. No bun or ffmpeg needed on the machine that submits.
Dialogue is written into the video prompt and the model voices it:
const vid2 = Video({
prompt: {
text: `Same gym with huge windows. <scene action, static camera>.
The trainer says matter-of-factly: "<the scene's line>"
Soft gym ambient sounds.`,
images: [scene2], // exactly ONE image = the first frame
},
model: varg.videoModel("kling_v4"),
audio: "native", // generates and keeps the dialogue audio
duration: 4, // integer seconds (kling_v4: 3-30)
});
kling_v3 is what this pipeline was first tested on and still works the same way (integer 3-15 s); kling_v4 is the current Kling. seedance_2_5 gives the best faces and lip movement at a higher price.audio: "native". A flat providerOptions: { varg: { generate_audio: true } } is silently dropped and you get a silent clip.POST https://api.varg.ai/v2/render with {"code": "<tsx>"} (MCP: render_video with code):
createVarg: Render/Clip/Image/Video/Music/Captions and varg are injected as globals. Local LSP errors on this file are expected and fine.export default (<Render ...>...); no named exports.varg.*Model() ids as local.Price it first (MCP estimate_cost with tool render and the code, or POST /v2/estimate on each clip's request) and get the user's go-ahead. Then submit and poll:
curl -s -X POST https://api.varg.ai/v2/render \
-H "Authorization: Bearer $VARG_API_KEY" -H "Content-Type: application/json" \
-d "{\"code\": $(jq -Rs . < template-cloud.tsx)}"
# -> {"id":"job_xxx",...}; poll every 15s:
curl -s https://api.varg.ai/v2/jobs/JOB_ID -H "Authorization: Bearer $VARG_API_KEY"
# completed -> output.outputs[0].url (s3.varg.ai mp4)
If all prompts match a previous run, the cloud render costs a few credits (server cache) and finishes in ~2 min.
Generated clips have ~0.2-0.5 s of warm-up and often trailing silence. Detect speech boundaries on the generated clips, then cut tight:
ffmpeg -i scene.mp4 -af "silencedetect=noise=-35dB:d=0.35" -f null -
<Clip cutFrom={0.2} cutTo={5.6} duration={5.4}>{vid1}</Clip> // cut right after the line ends
This took the test video from 27 s to 22.4 s with no content loss.
Keep Music duration an integer: a fractional total like 22.4 failed with a 422 on ElevenLabs music. Round down.
<Captions> transcribes Speech elements by itself. For dialogue that lives in a video's native audio, the tested route is two passes (newer vargai builds also accept src={vid.audio}; if the render rejects that with "Captions src must be ...", use this route):
POST /v2/files (upload) -> POST /v2/transcription with {"model":"whisper_large_v3","audio_url":...}. The result has word-level timestamps.prompt prop can also pass context hints to Whisper.srt prop takes a file path, and template code runs on the render server, so write the file to /tmp at module eval:const SRT_CONTENT = `1
00:00:00,260 --> 00:00:00,320
You
...`;
const SRT_PATH = `/tmp/project-${Date.now()}.srt`;
await Bun.write(SRT_PATH, SRT_CONTENT);
// in <Render>:
<Captions srt={SRT_PATH} style="tiktok" position="center"
color="#ffffff" activeColor="#a3e635" wordsPerLine={3} fontSize={64} />
Re-submitting is nearly free (everything cached); only the composition re-runs. Important: if you change any clip trim, regenerate the SRT, because the timings shift.
Agents can't watch video, but they can read frames and measure audio.
After every render (and every images pass), pull frames and inspect them as images. Never ship a video you haven't frame-checked.
# one frame per scene, at a timestamp INSIDE that scene (mind the trims)
ffmpeg -v error -ss 3 -i out.mp4 -frames:v 1 -vf scale=270:-1 check-s1.png -y
ffmpeg -v error -ss 9 -i out.mp4 -frames:v 1 -vf scale=270:-1 check-s3.png -y
ffmpeg -v error -ss 14 -i out.mp4 -frames:v 1 -vf scale=270:-1 check-s4.png -y
scale=270:-1 .. 360:-1): enough to judge, cheap on context.analyze_video tool answers questions about a rendered video.Visual checklist per frame:
Also verify structure numerically:
ffprobe -v error -show_entries format=duration,size -of default=noprint_wrappers=1 out.mp4
Duration must equal the sum of clip durations; a mismatch means a clip or music duration bug, not an encoding issue.
silencedetect shows where speech actually lives in each generated clip:
ffmpeg -i scene.mp4 -af "silencedetect=noise=-35dB:d=0.35" -f null - 2>&1 | grep silence_
Read it per clip:
cutFrom;cutTo;Then confirm the words: transcribe the final mix (3.4 step 2) and diff the transcript against the script. This catches mispronunciations by the video model and mishears by Whisper. Fix mishears in the SRT; regenerate the clip only if the model actually said the wrong thing.
| Symptom | Fix |
|---|---|
| Dead air, late start, early finish | Trim with cutFrom/cutTo: free |
| Wrong/garbled spoken line | Regenerate that Video |
| Identity/outfit drift in one scene | Regenerate that scene Image, then its Video |
| Caption timing off after re-trim | Regenerate the SRT only (one transcription) |
When the user sends a reference video instead of a script, reverse-engineer the same A/L/Scene structure this skill consumes. Do this before touching any generation. (media-download fetches a reference by link.)
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1 ref.mp4
# scene cut candidates (hard cuts)
ffmpeg -i ref.mp4 -vf "select='gt(scene,0.35)',showinfo" -f null - 2>&1 | grep showinfo | grep pts_time
# speech map
ffmpeg -i ref.mp4 -af "silencedetect=noise=-35dB:d=0.35" -f null - 2>&1 | grep silence_
Scene-cut timestamps + speech gaps together give the beat structure: how many scenes, how long each, where dialogue sits.
Extract 1-2 frames inside each detected scene and read them (parallel call):
ffmpeg -v error -ss <t> -i ref.mp4 -frames:v 1 -vf scale=360:-1 ref-s1.png -y
From the frames, document for each scene:
Transcribe the reference audio (same varg call as 3.4). Map each line to its scene via the timestamps. If there's no speech, note the music mood and on-screen text instead.
Assemble the standard format and show it to the user for approval before generating anything:
Actors:
- A1: <description from frames> - C1: <wardrobe>
- A2: <description>
Location:
- L1: <description>
Scene 1 (Ns): <framing>. <action>. A2 says: "<line>". L1
Scene 2 ...
From here the pipeline is identical: cards (1.1) -> location (1.2) -> composites (1.3) -> approval pass (2) -> videos + cloud render (3). Use the reference's measured scene durations as the initial duration values, and its framing notes verbatim in scene prompts.
Rough credits from the varg catalog (October 2026). Always quote the user the exact figure from POST /v2/estimate / estimate_cost, in credits.
| Step | Credits (~) |
|---|---|
8 images (2 cards + location + 5 scenes), nano_banana_2_1 | ~65 |
| 5 Kling clips with native audio, 4-6 s at 720p | ~400-500 |
Music bed (mureka_9_5) + one transcription | ~30 |
| Cloud re-render with everything cached | a few (stitching fee) |
| Iterating one scene image / one scene video | ~8 / ~80-100 |
varg-ai (sign-in, models, render formats), varg-character-keynote (one speaker on a stage), varg-podcast-video (two seated characters in dialogue), varg-previz (plan many shots and camera moves first), media-download (fetch a reference video), video-skills (find a skill for another format).
まだレビューはありません。使ってみた感想をお寄せください。
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
複数の独立したローカル作業を安全性と依存関係を確認して実行計画にまとめ、対応環境では並列化やAppleシリコン向け処理の選択を支援します。
TikTokやMeta広告の勝ちパターンを分解し、異なる切り口のテスト案や予算、評価時期を整理して、数値から継続・修正・停止を判断するスキルです。
将来の読み手が理由を知りたくなる未決定や暫定対応を、技術的負債として登録し、後から項目ごとに整理できるスキルです。
LangChain、EINO、AutoGen、AgentScope、CrewAI向けのコード雛形やAPI対応、プロジェクト構成を参照し、バージョン確認を踏まえてAIエージェント開発を支援します。
エラーやテスト失敗、画面の異常などを再現して原因を特定し、テストで確認しながら影響を絞った修正を進めるデバッグ用スキルです。
対話を通じてAI Agentの要件整理から設計、ツール定義、コード生成、動作確認まで6段階で進め、実行可能なプロジェクトを作ります。