Python SDK for Whiteframes AI — create AI-powered videos programmatically
Project description
Whiteframes AI Python SDK
Create AI-powered videos programmatically - whiteboard explainers, social shorts, news broadcasts, podcasts, and more.
Installation
pip install whiteframes
Quick Start
from whiteframes import WhiteframesAI
client = WhiteframesAI(api_key="wfai_your_key_here")
# Create a video and wait until ready (~2-3 minutes)
video = client.create_video("Explain how neural networks work").wait()
print(video.title) # "How Neural Networks Work"
print(video.frame_count) # 4
print(video.frames[0].narration)
Get your API key at whiteframes.ai → Settings → API Keys.
Creating Videos
create_video() returns a VideoJob. Call .wait() to block until ready.
From a text prompt
video = client.create_video(
prompt="Explain how neural networks work",
voice="Stephen", # default
quality="standard", # default - or "premium"
frames=4, # default - or 8, 12
video_type="whiteboard", # default - see Video Types below
language="en-US", # default - see Languages below
aspect_ratio="16:9", # default - or "9:16" for vertical (TikTok/Reels/Shorts)
animation_speed="normal", # default - or "slow", "fast"
).wait()
From a document (PDF, image, etc.)
video = client.create_video(
prompt="Create a video summary of this report",
file_path="quarterly-report.pdf", # uploaded automatically
frames=8,
video_type="corporate",
).wait()
The file is uploaded and its content extracted automatically. Max file size: ~4.5 MB.
Multi-speaker videocast
video = client.create_video(
prompt="Discuss the future of AI",
video_type="videocast",
frames=8,
speaker_voices={
"speaker_1": "Stephen",
"speaker_2": "Ruth",
"speaker_3": "Brian",
},
).wait()
With progress callback
def on_progress(progress, message):
print(f"[{progress}%] {message}")
video = client.create_video(prompt="Explain blockchain").wait(
on_progress=on_progress
)
Non-blocking
job = client.create_video(prompt="Explain blockchain")
# Do other work...
job.refresh()
print(job.status, job.progress) # "generating", 45
# Block when ready
video = job.wait()
Enhance a prompt
Use AI to expand a short prompt into a detailed video description before creating.
enhanced = client.enhance_prompt("explain blockchain")
# "Explore the revolutionary world of blockchain technology..."
video = client.create_video(prompt=enhanced).wait()
Manual job polling
Poll job status yourself instead of using .wait().
import time
job = client.create_video(prompt="Explain quantum computing")
while True:
status = client.get_job_status(job.job_id)
print(f"[{status.get('progress', 0)}%] {status['status']}")
if status["status"] == "ready":
video = client.get_video(status["projectId"])
break
if status["status"] == "error":
print(f"Failed: {status.get('message')}")
break
time.sleep(5)
Managing Videos
Get, list, delete
# Get a single video
video = client.get_video("my-project-id")
# List all videos (paginated)
result = client.list_videos()
for video in result["videos"]:
print(video.title, video.frame_count, "frames")
# Paginate
result2 = client.list_videos(cursor=result["next_cursor"])
# Delete
client.delete_video("my-project-id")
Edit a video
Use the SDK methods to modify videos programmatically.
Note on voice parameters: Methods that create or regenerate audio (
create_video,add_frame,regenerate_frame,regenerate_narration) usevoice=as the parameter name. Methods that patch project metadata (update_frame,update_project) usevoice_id=instead.
video = client.get_video("my-project-id")
# Update narration (triggers audio re-synthesis)
client.update_frame(video.id, frame_num=1, narration="Updated narration text here.")
# Update visual description and keywords
client.update_frame(video.id, frame_num=2,
visual_description="A detailed flowchart showing the process",
keywords=["flowchart", "process", "steps"])
# Override one frame to use a premium voice
premium_voices = client.list_premium_voices()
client.update_frame(video.id, frame_num=1,
voice_id=premium_voices[0]["voiceId"], voice_tier="premium")
# Update project-level settings
client.update_project(video.id, voice_id="Amy", video_type="educational")
# Add background music
client.update_project(video.id, music_track_id="track-02", music_volume=0.3)
# Remove background music
client.update_project(video.id, music_track_id="")
# Adjust music volume
client.update_project(video.id, music_volume=0.7)
# Change animation speed (project-wide)
client.update_project(video.id, animation_speed="slow")
# Override animation speed for a single frame
client.update_frame(video.id, frame_num=3, animation_speed="fast")
# Change language (narration metadata only - does not re-generate audio)
client.update_project(video.id, language="fr-FR")
# Switch project to a premium voice
voices = client.list_premium_voices()
client.update_project(video.id,
voice_id=voices[0]["voiceId"], voice_tier="premium")
Delete a frame
# Remove frame 3; remaining frames renumber automatically
video = client.delete_frame("my-project-id", frame_num=3)
print(video.frame_count) # one less than before
Reorder frames
# Pass a complete list of frame numbers in the desired order
# Example: move frame 3 to the front of a 4-frame video
video = client.reorder_frames("my-project-id", frame_order=[3, 1, 2, 4])
print([f.id for f in video.frames]) # [3, 1, 2, 4]
Frame Operations
Add a new frame
# Manual narration
video = client.add_frame(
project_id="my-project-id",
frame_description="A world map showing global internet usage",
narration="Over 5 billion people now have internet access.",
keywords=["internet", "global", "map"],
position=2, # insert as 3rd frame (0-based)
quality="standard",
video_type="whiteboard",
)
print(f"Now has {video.frame_count} frames")
# AI-generated narration (leave narration empty)
video = client.add_frame(
project_id="my-project-id",
frame_description="A timeline of major AI breakthroughs",
keywords=["AI", "timeline"],
)
# Premium quality + premium voice
voices = client.list_premium_voices()
video = client.add_frame(
project_id="my-project-id",
frame_description="A futuristic city skyline",
narration="",
quality="premium",
voice=voices[0]["voiceId"],
voice_tier="premium",
)
Regenerate a frame's visual
video = client.regenerate_frame(
project_id="my-project-id",
frame_num=2,
frame_description="A bar chart comparing CPU vs GPU performance",
narration="GPUs outperform CPUs for parallel workloads by 10x.",
keywords=["GPU", "CPU", "performance"],
quality="premium",
video_type="educational",
)
# With a premium voice
premium_voices = client.list_premium_voices()
video = client.regenerate_frame(
project_id="my-project-id",
frame_num=2,
frame_description="A bar chart comparing CPU vs GPU performance",
narration="GPUs outperform CPUs for parallel workloads by 10x.",
keywords=["GPU", "CPU", "performance"],
quality="premium",
video_type="educational",
voice=premium_voices[0]["voiceId"],
voice_tier="premium",
)
# Also regenerate narration with AI (+1 credit)
video = client.regenerate_frame(
project_id="my-project-id",
frame_num=1,
frame_description="A diagram showing neural network layers",
quality="standard",
video_type="educational",
regenerate_narration=True,
)
Regenerate narration only
Regenerate narration text without changing the visual. Costs 1 credit (+1 if premium voice).
video = client.regenerate_narration(
project_id="my-project-id",
frame_num=2,
frame_description="A bar chart comparing CPU vs GPU performance",
keywords=["GPU", "CPU", "performance"],
)
print(video.frames[1].narration)
Fix a frame with AI
Apply targeted fixes without regenerating the entire visual.
video = client.fix_frame(
project_id="my-project-id",
frame_num=2,
instruction="Make the title text larger and change the color to blue",
)
# Use premium quality for more complex fixes
video = client.fix_frame(
project_id="my-project-id",
frame_num=2,
instruction="Redesign the chart with gradient fills and 3D perspective",
quality="premium",
)
Frame version management
Each regeneration or fix creates a new version. You can list, switch, or delete versions.
# List all versions of a frame
versions = client.list_frame_versions("my-project-id", frame_num=1)
for v in versions:
active = " (active)" if v["active"] else ""
print(f"v{v['index'] + 1}: {v['generatedAt']}{active}")
# Switch to a previous version
video = client.switch_frame_version("my-project-id", frame_num=1, version_index=0)
# Delete a version (cannot delete the last remaining one)
video = client.delete_frame_version("my-project-id", frame_num=1, version_index=2)
Social media metadata
Every video includes AI-generated social media metadata — ready to copy and paste.
video = client.create_video("Top 10 programming languages in 2025").wait()
# Access social media metadata
social = video.social_media
print(social.get("title")) # Viral-optimized title
print(social.get("description")) # Description with hook
print(social.get("hashtags")) # 10-15 relevant hashtags
print(social.get("hookLine")) # Hook for first 3 seconds
print(social.get("thumbnailText")) # Suggested thumbnail text
API Key Management
# Create a new key (save it - shown once only!)
result = client.create_api_key("My Production App")
print(result["key"])
# List all keys
keys = client.list_api_keys()
for key in keys:
print(key["name"], key["totalCalls"], "calls")
# Revoke a key
client.revoke_api_key("key_a1b2c3d4")
Usage & Statistics
# Get full API call history
calls = client.get_usage()
total = sum(c.get("creditsUsed", 0) for c in calls)
print(f"Total credits used: {total}")
# Get account usage statistics
stats = client.get_stats()
print(f"Total videos: {stats.total_videos}")
print(f"Downloads: {stats.downloads_count}")
print(f"Credits: {stats.credits}")
# Quality breakdown
print(f"Standard: {stats.videos_by_quality.get('standard', 0)}")
print(f"Premium: {stats.videos_by_quality.get('premium', 0)}")
# Edits
print(f"Frame regenerations: {stats.frame_regenerations}")
print(f"Frames fixed: {stats.frames_fixed}")
# Monthly breakdown
for m in stats.monthly:
print(f"{m.month}: {m.videos_created} videos, {m.downloads_count} downloads")
# User profile
profile = client.get_profile()
print(f"Credits remaining: {profile['credits']}")
print(f"Name: {profile['displayName']}")
UsageStats fields
stats.total_videos # active (non-deleted) videos
stats.trashed_videos # soft-deleted videos
stats.favorited_videos # favorited count
stats.frames_generated # total frames across all videos
stats.downloads_count # total downloads
stats.reels_created # reel exports
stats.frame_regenerations # frame regenerations
stats.frames_fixed # frames fixed via AI
stats.videos_by_quality # {"standard": 170, "premium": 30}
stats.credits # remaining credits (None = unlimited)
stats.credits_used # total credits consumed via API
stats.credits_via_ui # credits consumed via the web app
stats.credits_via_api # credits consumed via the API/SDK
stats.last_video_at # timestamp of most recent video
stats.monthly # list of MonthlyStats (see below)
MonthlyStats fields
m.month # "2026-03"
m.videos_created # videos created that month
m.frames_generated # frames in videos created that month
m.downloads_count # downloads for videos created that month
m.favorited_videos # favorited videos created that month
m.videos_by_quality # {"standard": 15, "premium": 5}
Languages
Create videos in 26 languages. Narration text is generated in the specified language.
# List all supported languages
languages = client.list_languages()
for lang in languages:
print(f"{lang['code']}: {lang['name']} ({lang['voices']} voices)")
# Create a video in Hindi
video = client.create_video(
prompt="Explain how neural networks work",
voice="Kajal",
language="hi-IN",
).wait()
print(video.language) # "hi-IN"
# Create a video in French
video = client.create_video(
prompt="Explain quantum computing",
voice="Lea",
language="fr-FR",
frames=8,
).wait()
# Filter voices by language
french_voices = client.list_voices(language="fr-FR")
# [{"id": "Lea", "language": "fr-FR", ...}, {"id": "Remi", "language": "fr-FR", ...}]
# Change language on an existing video
client.update_project("my-project-id", language="de-DE")
Supported languages
en-US, en-GB, en-AU, fr-FR, de-DE, es-ES, es-MX, it-IT, pt-BR, ja-JP, ko-KR, cmn-CN, hi-IN, nl-NL, pl-PL, ar-AE, tr-TR, sv-SE, nb-NO, da-DK, fi-FI, ca-ES, cy-GB, ro-RO, ru-RU, he-IL
Voices
Standard voices (included)
35 built-in voices across 24 languages (Russian and Hebrew available via premium voices only):
# List all voices
voices = client.list_voices()
for v in voices:
print(f"{v['id']} - {v['language_name']} ({v['language']})")
# Filter by language
hindi_voices = client.list_voices(language="hi-IN")
german_voices = client.list_voices(language="de-DE")
Premium voices (+1 credit per video)
A larger catalog of high-quality voices. Browse and use them with voice_tier="premium".
# List all available premium voices
voices = client.list_premium_voices()
for v in voices:
print(f"{v['voiceId']}: {v.get('name', v['voiceId'])}")
# Create a video with a premium voice
video = client.create_video(
prompt="Explain quantum computing",
voice=voices[0]["voiceId"],
voice_tier="premium",
quality="premium",
frames=8,
).wait()
print(video.voice_tier) # "premium"
# Switch an existing project to a premium voice
video = client.update_project(
"my-project-id",
voice_id="Dennis",
voice_tier="premium",
)
Supported Video Types
| videoType | Description |
|---|---|
| whiteboard | Cinematic whiteboard - bold illustrations on white |
| saas-demo | Product demo style - clean light UI |
| infographic | Bold saturated flat design - data as landscape |
| corporate | Professional visual style - metaphorical illustrations |
| architecture | Technical system diagrams - service nodes, data flow lines |
| educational | Visual proofs and discoveries - warm light backgrounds |
| social-short | Vertical 9:16 format - massive typography |
| pitch | High-impact pitch style - hero metrics, premium canvas |
| storytelling | Cinematic narrative style - atmospheric scenes |
| news | Professional TV news - headline banners, lower-thirds |
| videocast | Animated podcast - multiple speakers with avatars |
| quiz | Trivia questions with 4 options and answer reveals |
| timeline | Chronological events along a visual timeline |
| comparison | Side-by-side versus comparison with verdict |
| geo-map | Map-based geographic visuals with regional data |
| top-10 | Countdown-style ranked lists with visual numbers |
| did-you-know | Surprising facts with bold visual hooks |
| flashcard | Term and definition study cards for learning |
| how-to | Numbered step-by-step guides with progress tracking |
| myth-vs-fact | Debunk myths with visual side-by-side comparison |
Credit Costs
New accounts receive 30 free credits.
| Action | Standard | Premium |
|---|---|---|
| Video Generation (4 frames) | 10 | 20 |
| Video Generation (8 frames) | 20 | 30 |
| Video Generation (12 frames) | 30 | 40 |
| Frame Regeneration | 3 | 5 |
| Fix Frame (AI edit) | 2 | 3 |
| Regenerate Narration | 1 | 1 |
| Premium Voice Surcharge | +1 per video | +1 per video |
| Everything else | Free | Free |
Error Handling
from whiteframes import WhiteframesAI, InsufficientCreditsError, ContentRejectedError, WhiteframesError
try:
video = client.create_video(prompt="...")
except InsufficientCreditsError:
print("Not enough credits")
except ContentRejectedError:
print("Content was rejected by moderation")
except WhiteframesError as e:
print(f"API error {e.status_code}: {e}")
Video & Frame Objects
video.id # project ID
video.title # generated title
video.status # "ready"
video.video_type # e.g. "educational"
video.voice_id # e.g. "Stephen"
video.voice_tier # "standard" or "premium"
video.language # BCP-47 code, e.g. "en-US", "hi-IN"
video.animation_speed # "slow", "normal", or "fast"
video.frame_count # number of frames
video.created_at # timestamp
video.frames # list of Frame objects
frame.id # frame number
frame.narration # spoken text
frame.visual_description # what the visual depicts
frame.duration # seconds
frame.keywords # list of keywords
frame.has_visual # bool - has generated visual
frame.has_audio # bool - has generated audio
frame.animation_speed # per-frame override: "slow", "normal", "fast", or None
frame.speaker_id # for videocast: "speaker_1", etc.
frame.status # "ready", "generating", or "error"
Self-Hosting
client = WhiteframesAI(
api_key="wfai_xxxx",
base_url="https://your-domain.com"
)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file whiteframes-0.1.14.tar.gz.
File metadata
- Download URL: whiteframes-0.1.14.tar.gz
- Upload date:
- Size: 31.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85c4d65f95ee1c41cdbaf6eba3ed64d5110c35253ad07074337eda46a48ba766
|
|
| MD5 |
6be09c668027029cdb90068fcdba1d0c
|
|
| BLAKE2b-256 |
205df4e5ec4c5c4bea4cb761a1ae68d151a787b04031cdb55e4d209d7a428555
|
File details
Details for the file whiteframes-0.1.14-py3-none-any.whl.
File metadata
- Download URL: whiteframes-0.1.14-py3-none-any.whl
- Upload date:
- Size: 26.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
994d8deeba6609d6a7a3ad88030d27414f0e2e16215676a0ff784bf75ebc48bd
|
|
| MD5 |
a498e87dfb5abc8d6abf12aa440e1340
|
|
| BLAKE2b-256 |
7d1c4521418d07c46ddd9968f3daee9cca82cff0d5454ca7e66ad3a50ede7190
|