Skip to main content

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) use voice= as the parameter name. Methods that patch project metadata (update_frame, update_project) use voice_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

whiteframes-0.1.14.tar.gz (31.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

whiteframes-0.1.14-py3-none-any.whl (26.7 kB view details)

Uploaded Python 3

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

Hashes for whiteframes-0.1.14.tar.gz
Algorithm Hash digest
SHA256 85c4d65f95ee1c41cdbaf6eba3ed64d5110c35253ad07074337eda46a48ba766
MD5 6be09c668027029cdb90068fcdba1d0c
BLAKE2b-256 205df4e5ec4c5c4bea4cb761a1ae68d151a787b04031cdb55e4d209d7a428555

See more details on using hashes here.

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

Hashes for whiteframes-0.1.14-py3-none-any.whl
Algorithm Hash digest
SHA256 994d8deeba6609d6a7a3ad88030d27414f0e2e16215676a0ff784bf75ebc48bd
MD5 a498e87dfb5abc8d6abf12aa440e1340
BLAKE2b-256 7d1c4521418d07c46ddd9968f3daee9cca82cff0d5454ca7e66ad3a50ede7190

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page