- name
- arcads-ai-video-generation
- description
- Generate AI marketing videos and static image ads using the Arcads API with skills for Seedance 2.0, Sora 2, Veo 3.1, Kling 3.0, Nano Banana, and 37 Meta ad templates
- triggers
- ["create an Arcads video","generate a UGC video with Seedance","make a Nano Banana product image","build a Meta image ad","animate this still with Veo","create a Pixar-style animated ad","generate AI influencer images","make a claymation ad video"]
# Arcads AI Video Generation
> Skill by [ara.so](https://ara.so) — Claude Code Skills collection.
## What this project does
**arcads-claude-code** is a Python-based agent skill pack that provides programmatic access to the full Arcads creative stack for generating AI marketing videos and images. It includes:
- **Video models**: Seedance 2.0 (flagship), Sora 2, Veo 3.1, Kling 3.0, Grok Video, OmniHuman, Audio-driven
- **Image models**: Nano Banana 2/Pro/Edit, ChatGPT Image 2
- **37 static Meta image ad templates** with dedicated generators
- **Multi-step pipelines**: Pixar-style ads, claymation ads, YouTube thumbnails
- **Agent-native workflows**: polling, cost gates, prompt engineering, file organization
The project is designed for AI coding agents (Claude Code, Cursor) to autonomously generate marketing creative through natural language commands.
## Installation
### 1. Clone and setup
```bash
git clone https://github.com/krusemediallc/arcads-claude-code.git
cd arcads-claude-code
./scripts/setup.sh
```
The setup script will:
- Prompt for your Arcads API key (get it from [app.arcads.ai/settings/api](https://app.arcads.ai/settings/api))
- Create `.env` with `ARCADS_API_KEY=your_key_here`
- Verify API connection
- Generate `MASTER_CONTEXT.md` workspace file
### 2. Install dependencies
**Core (required for all workflows):**
```bash
python3 -m pip install requests python-dotenv
```
**Optional (for specific pipelines):**
```bash
# For video stitching and Pixar/claymation workflows
brew install ffmpeg jq
# For caption burn-in
brew install node
pip install openai-whisper
# For Meta ad publishing
pip install -r shared/skills/meta-ad-builder/scripts/requirements.txt
```
### 3. Environment variables
Create `.env` in the project root:
```bash
ARCADS_API_KEY=your_api_key_here
```
## Core API patterns
### Base configuration
```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv('ARCADS_API_KEY')
BASE_URL = 'https://api.arcads.ai'
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
```
### Standard video generation flow
```python
# 1. Submit generation request
def generate_video(prompt, model='seedance-2', duration=12):
response = requests.post(
f'{BASE_URL}/v1/videos/generate',
headers=headers,
json={
'prompt': prompt,
'model': model,
'duration': duration
}
)
return response.json()
# 2. Poll for completion
def poll_video(job_id, interval=10):
import time
while True:
response = requests.get(
f'{BASE_URL}/v1/videos/{job_id}',
headers=headers
)
data = response.json()
if data['status'] == 'completed':
return data['videoUrl']
elif data['status'] == 'failed':
raise Exception(f"Generation failed: {data.get('error')}")
time.sleep(interval)
# 3. Download result
def download_video(url, output_path):
response = requests.get(url)
with open(output_path, 'wb') as f:
f.write(response.content)
```
### Full example workflow
```python
# Generate a 12-second Seedance UGC video
result = generate_video(
prompt="""
A young woman in her mid-20s sits in a cozy kitchen, natural morning light
streaming through a window. She holds up a skincare bottle, speaking directly
to camera with natural eye contact breaks. iPhone-shot aesthetic, authentic
and casual delivery.
""",
model='seedance-2',
duration=12
)
job_id = result['jobId']
print(f"Job submitted: {job_id}")
# Poll until complete
video_url = poll_video(job_id)
print(f"Video ready: {video_url}")
# Download
download_video(video_url, 'output/ugc_skincare.mp4')
```
## Video models
### Seedance 2.0 (flagship model)
**Best for:** UGC content, product reveals, feature walkthroughs, 4-15s clips with native audio
```python
# UGC selfie-style product review (9-layer formula)
response = requests.post(
f'{BASE_URL}/v1/videos/generate',
headers=headers,
json={
'model': 'seedance-2',
'duration': 12,
'prompt': """
Shot on iPhone 14 Pro in natural light. A woman in her late 20s sits
in a modern kitchen, holding [PRODUCT]. She speaks directly to camera
with natural pauses and eye-contact breaks. Casual, authentic delivery.
"I used to buy [COMPETITOR] until I found this..."
""",
'style': 'ugc'
}
)
```
**Premium product reveal (no person):**
```python
response = requests.post(
f'{BASE_URL}/v1/videos/generate',
headers=headers,
json={
'model': 'seedance-2',
'duration': 10,
'prompt': """
Dark void background. Premium watch floats and rotates slowly.
Text overlay appears: "Swiss precision. 40-hour power reserve."
Dramatic lighting with subtle reflections. Hero product reveal.
""",
'style': 'premium'
}
)
```
**Image-to-video with reference:**
```python
import base64
with open('product_hero.jpg', 'rb') as f:
img_b64 = base64.b64encode(f.read()).decode('utf-8')
response = requests.post(
f'{BASE_URL}/v1/videos/generate',
headers=headers,
json={
'model': 'seedance-2',
'duration': 8,
'prompt': 'Zoom into the product label, then pan around showing texture details',
'startFrame': img_b64
}
)
```
### Veo 3.1 (start-frame animation)
**Best for:** Animating stills into videos with dialogue, UGC still → video pipeline
```python
# Animate a Nano Banana still with dialogue
with open('ugc_still.jpg', 'rb') as f:
start_frame = base64.b64encode(f.read()).decode('utf-8')
response = requests.post(
f'{BASE_URL}/v1/veo3/animate',
headers=headers,
json={
'startFrame': start_frame,
'duration': 8,
'prompt': 'Natural head movement, blinking, slight smile',
'dialogue': "This serum changed my entire skincare routine"
}
)
```
**IMPORTANT:** Veo 3.1 requires explicit dialogue confirmation before generation:
```python
def confirm_dialogue(script):
"""Agent must get user approval for dialogue before Veo generation"""
print(f"Dialogue to be embedded:\n{script}\n")
confirm = input("Approve dialogue? (yes/no): ")
return confirm.lower() == 'yes'
if confirm_dialogue(dialogue_text):
# proceed with generation
```
### Sora 2 (text-to-video, up to 20s)
**Best for:** Longer scenes, cinematic establishing shots
```python
response = requests.post(
f'{BASE_URL}/v1/sora2/generate',
headers=headers,
json={
'prompt': """
Aerial drone shot: sunrise over a mountain lake. Camera slowly descends
revealing a lone figure standing at the water's edge. Golden hour light,
mist rising from the water. Cinematic, 24fps feel.
""",
'duration': 16,
'aspectRatio': '16:9'
}
)
```
**Sora 2 remix (restyle existing video):**
```python
response = requests.post(
f'{BASE_URL}/v1/sora2/remix/video',
headers=headers,
json={
'sourceVideoUrl': 'https://example.com/original.mp4',
'prompt': 'Transform into cyberpunk aesthetic with neon colors',
'strength': 0.7 # 0.0-1.0, higher = more transformation
}
)
```
### Kling 3.0 (B-roll and scene generation)
**Best for:** Background footage, establishing shots, 5-10s clips
```python
# B-roll clip
response = requests.post(
f'{BASE_URL}/v1/b-roll',
headers=headers,
json={
'prompt': 'Coffee being poured into a white mug, steam rising, macro shot',
'duration': 5
}
)
# Scene generation
response = requests.post(
f'{BASE_URL}/v1/scene',
headers=headers,
json={
'prompt': 'Modern minimalist office space, large windows, afternoon light',
'duration': 8
}
)
```
### Other models
```python
# Grok Video
response = requests.post(
f'{BASE_URL}/v2/videos/generate',
headers=headers,
json={
'model': 'grok-video',
'prompt': 'Your scene description',
'duration': 10
}
)
# OmniHuman (talking avatar)
response = requests.post(
f'{BASE_URL}/v1/omnihuman',
headers=headers,
json={
'avatarImage': avatar_base64,
'script': 'Welcome to our product demo...',
'voiceId': 'professional-female'
}
)
# Audio-driven (lip sync)
response = requests.post(
f'{BASE_URL}/v1/audio-driven',
headers=headers,
json={
'videoUrl': 'https://example.com/person_silent.mp4',
'audioUrl': 'https://example.com/voiceover.mp3'
}
)
```
## Image generation
### Nano Banana (photoreal images)
**Model variants:**
- `nano-banana-2`: Default, fast, good quality
- `nano-banana` (Pro): Gemini 3 Pro Image — higher fidelity, better character consistency
- `nano-banana-edit`: Inpainting/editing
```python
# Generate a UGC product selfie
response = requests.post(
f'{BASE_URL}/v1/images/generate',
headers=headers,
json={
'model': 'nano-banana-2',
'prompt': """
iPhone selfie shot. Young woman, 24, freckles, natural makeup, holding
skincare bottle. Bedroom background, soft morning light through curtain.
Authentic, unfiltered aesthetic. Slight lens distortion, natural grain.
""",
'aspectRatio': '9:16',
'numImages': 1
}
)
```
**With reference images for character consistency:**
```python
import base64
# Load reference images
refs = []
for img_path in ['hero_front.jpg', 'hero_3quarter.jpg', 'hero_profile.jpg']:
with open(f'references/influencers/{img_path}', 'rb') as f:
refs.append(base64.b64encode(f.read()).decode('utf-8'))
response = requests.post(
f'{BASE_URL}/v1/images/generate',
headers=headers,
json={
'model': 'nano-banana-2',
'prompt': 'Same person holding product in different pose',
'referenceImages': refs,
'aspectRatio': '4:5'
}
)
```
**Create AI influencer character sheet (10-image workflow):**
```python
def create_influencer_sheet(character_description):
# Phase 1: Generate hero front portrait
hero = requests.post(
f'{BASE_URL}/v1/images/generate',
headers=headers,
json={
'model': 'nano-banana-2',
'prompt': f"""
Professional front-facing portrait. {character_description}.
Direct eye contact, neutral expression, even lighting, white background.
High detail on facial features for reference consistency.
""",
'aspectRatio': '4:5'
}
).json()
hero_url = poll_image(hero['jobId'])
# User approval gate
print(f"Hero portrait: {hero_url}")
if input("Approve hero? (yes/no): ").lower() != 'yes':
return None
# Download hero for references
hero_b64 = download_as_base64(hero_url)
# Phase 2: Generate 9 additional angles using hero as reference
angles = [
"3/4 view looking left, slight smile",
"3/4 view looking right, neutral expression",
"Profile view left side, serious expression",
"Profile view right side, laughing",
"Close-up of face, surprised expression",
"Close-up of face, concentrated expression",
"Full body shot, casual standing pose",
"Candid expression, mid-conversation",
"Looking over shoulder, playful expression"
]
images = [hero_url]
for angle_prompt in angles:
response = requests.post(
View on GitHub