agent-media
Python SDK for agent-media — UGC video generation for developers.
Generate AI videos with realistic talking heads, B-roll, voiceover, animated subtitles, and music. One function call, finished video.
Install
pip install agent-media
Quick Start
from agent_media import AgentMedia
client = AgentMedia(api_key="ma_YOUR_KEY")
# Generate a video — blocks until complete, returns the URL
video = client.create_video(
script="Have you tried building UGC content at scale? This API makes it trivial.",
actor_slug="sofia",
tone="energetic",
style="hormozi",
target_duration=10,
)
print(video["video_url"])
# → https://...mp4
Async
from agent_media.client import AsyncAgentMedia
async with AsyncAgentMedia(api_key="ma_YOUR_KEY") as client:
video = await client.create_video(
script="Your script here...",
actor_slug="sofia",
tone="confident",
)
print(video["video_url"])
API Reference
AgentMedia(api_key, base_url?, timeout?)
| Parameter | Type | Required | Default |
|---|---|---|---|
api_key |
str | Yes | — |
base_url |
str | No | Production API |
timeout |
float | No | 60.0 |
client.create_video(**params)
Generate a video and wait for completion. Returns { job_id, video_url, credits_deducted, duration }.
video = client.create_video(
script="Your script (50-3000 chars)",
actor_slug="sofia", # use list_actors() to browse
tone="energetic", # energetic | calm | confident | dramatic
music="chill", # chill | energetic | corporate | dramatic | upbeat
style="hormozi", # 17 subtitle styles
target_duration=10, # 5 | 10 | 15 seconds
aspect_ratio="9:16", # 9:16 | 16:9 | 1:1
allow_broll=True, # include AI-generated B-roll
template="saas-review", # optional template
webhook_url="https://...", # optional async callback
timeout_seconds=600, # max wait time (default 10 min)
)
client.submit_video(**params)
Submit without waiting. Returns { job_id, status, credits_deducted }.
client.submit_subtitle(**params)
Add subtitles to an existing video.
job = client.submit_subtitle(
video_url="https://example.com/video.mp4",
style="bold",
)
client.submit_saas_review(**params)
Generate a SaaS Review video from a URL.
job = client.submit_saas_review(
product_url="https://example.com/product",
angle="enthusiastic",
actor_slug="sofia",
)
submit_product_review(...) remains available as a deprecated wrapper for one release.
client.create_product_acting(**params)
Generate Product Acting UGC from a product image and actor.
video = client.create_product_acting(
product_image_url="https://cdn.example.com/perfume.png",
actor_slug="sofia",
product_name="Rose Noir",
product_description="Premium rose perfume with a warm vanilla dry-down.",
template="product-in-hand",
acting_style="honest-review",
duration=5,
subtitle_style="hormozi",
)
print(video["video_url"])
Use submit_product_acting(...) if you want to submit without waiting and poll with get_video_status().
Character Video — 3-step Content Machine pipeline
result = client.create_character_video(
description="Marco, 35yo Italian chef, white uniform, curly black hair",
script="Marco walks into his sunlit Brooklyn kitchen, takes a bite of fresh bread, smiles.",
duration=5,
aspect_ratio="9:16",
)
print(result["character_sheet_url"]) # Step 1
print(result["storyboard_url"]) # Step 2
print(result["video_url"]) # Step 3 (final 720p MP4)
create_character_video runs the three steps in order, threading a single session_id so the server backstops the scene prompt from the storyboard. Cost (70%+ margin on EvoLink Seedance 2.0 720p): 20 credits sheet (or 35 for description-only) + 20 storyboard + 350/700 video for 5s/10s.
For step-by-step control or the AI beat suggester:
# One of: actor_slug | reference_image_url | description
sheet = client.submit_character_sheet(description="Marco the chef")
# (poll client.get_video_status(sheet["job_id"]) until completed)
suggestions = client.suggest_storyboard(
character_description="Marco the chef",
vibe="wholesome",
)
# → {"options": [{"title", "beats": [...]}, ...]}
sb = client.submit_character_storyboard(
character_sheet_url=character_sheet_url,
beats=suggestions["options"][0]["beats"],
)
video = client.submit_character_video(
character_sheet_url=character_sheet_url,
storyboard_url=storyboard_url,
duration=5,
)
The AsyncAgentMedia class exposes await client.create_character_video(...) and the same submit_* / suggest_storyboard methods with identical signatures.
client.list_actors(limit?, offset?)
Browse available AI actors.
result = client.list_actors(limit=20)
for actor in result["actors"]:
print(f"{actor['slug']} — {actor['name']} ({actor['gender']}, {actor['nationality']})")
client.get_video_status(job_id)
Check job progress.
status = client.get_video_status("job_abc123")
if status["status"] == "completed":
print(status["video_url"])
Error Handling
from agent_media import AgentMedia, AgentMediaError
try:
video = client.create_video(script="...")
except AgentMediaError as e:
print(f"{e.code}: {e} (HTTP {e.status})")
Webhooks
Skip polling — pass webhook_url and agent-media will POST to it when the job completes or fails.
job = client.submit_video(
script="...",
actor_slug="sofia",
webhook_url="https://example.com/webhooks/agent-media?secret=MY_TOKEN",
)
Payload on success:
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"video_url": "https://media.agent-media.ai/videos/550e8400.mp4"
}
Payload on failure:
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "failed",
"error_message": "Script exceeded maximum duration for selected actor."
}
Rules:
- Must be
https://(plain HTTP is rejected) - Publicly reachable
- Max 2048 characters
- Retries on non-2xx: 3 attempts with exponential backoff (1 s, 4 s, 16 s)
- Query strings are preserved — append
?secret=MY_TOKENto verify authenticity
Batch Generation
from concurrent.futures import ThreadPoolExecutor
scripts = ["Script 1...", "Script 2...", "Script 3..."]
with ThreadPoolExecutor(max_workers=3) as pool:
videos = list(pool.map(
lambda s: client.create_video(script=s, actor_slug="sofia"),
scripts,
))
for v in videos:
print(v["video_url"])
Related Packages
| Package | Registry | Description |
|---|---|---|
@agentmedia/sdk |
npm | TypeScript SDK |
@agentmedia/mcp-server |
npm | MCP server for Claude Code, Cursor, Windsurf |
agent-media-cli |
npm | CLI tool |
@agentmedia/schema |
npm | Shared schema, types, Zod validation |
Links
License
Apache-2.0
Metadata
Release files for agent-media 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_media-0.4.0.tar.gz | 10.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_media-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.6 kB
Release files / agent_media-0.4.0.tar.gz
| Download URL | agent_media-0.4.0.tar.gz |
|---|---|
| Size | 10.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
324b2f8a65857bca2ace36f407239a0e814f9ab7ec0a4858574f5fb81cef1d8b
|
|
BLAKE2b-256 checksum How to use checksums |
6ccfa4bc4e90edf330bac8b13c303e5c94ac3739523d4d48ee7fb996c9706099
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / agent_media-0.4.0-py3-none-any.whl
| Download URL | agent_media-0.4.0-py3-none-any.whl |
|---|---|
| Size | 11.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9fc39421a011597fb857bbc0eb35a93040af7a7c228c8489f51a17a026af6df8
|
|
BLAKE2b-256 checksum How to use checksums |
5ae12251db0ca381efe2ffd0a2ea81265ac324263ea1ffd91a305baf62be1bf5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|