Skip to main content

PlayVideo SDK for Python

CI PyPI version PyPI downloads License: MIT Python 3.10+

Official Python SDK for the PlayVideo API - Video hosting for developers.

Installation

pip install playvideo

Requirements: Python 3.10+

Quick Start

Synchronous Client

from playvideo import PlayVideo

client = PlayVideo("play_live_xxx")

# List collections
collections = client.collections.list()

# Upload a video
response = client.videos.upload(
    "./video.mp4",
    "my-collection",
    on_progress=lambda p: print(f"{p.percent}%")
)

# Watch processing progress
for event in client.videos.watch_progress(response.video["id"]):
    print(event.stage, event.message)
    if event.stage == "completed":
        print("Video ready:", event.playlist_url)
        break

client.close()

Async Client

from playvideo import AsyncPlayVideo
import asyncio

async def main():
    async with AsyncPlayVideo("play_live_xxx") as client:
        # List collections
        collections = await client.collections.list()
        
        # Upload a video
        response = await client.videos.upload("./video.mp4", "my-collection")
        
        # Watch processing progress
        async for event in client.videos.watch_progress(response.video["id"]):
            print(event.stage)
            if event.stage == "completed":
                break

asyncio.run(main())

Resources

Collections

# List all collections
collections = client.collections.list()

# Create a collection
collection = client.collections.create("My Videos", description="Tutorial videos")

# Get a collection with videos
collection = client.collections.get("my-videos")

# Delete a collection
client.collections.delete("my-videos")

Videos

# List videos
videos = client.videos.list()

# Filter by collection or status
videos = client.videos.list(collection="my-collection", status="COMPLETED", limit=50)

# Get a video
video = client.videos.get("video-id")

# Upload with progress
def on_progress(progress):
    print(f"{progress.percent}% ({progress.loaded}/{progress.total})")

response = client.videos.upload("./video.mp4", "my-collection", on_progress=on_progress)

# Delete a video
client.videos.delete("video-id")

# Get embed information
embed_info = client.videos.get_embed_info("video-id")

# Watch processing progress
for event in client.videos.watch_progress("video-id"):
    match event.stage:
        case "pending":
            print("Waiting in queue...")
        case "processing":
            print("Transcoding...")
        case "completed":
            print("Done!", event.playlist_url)
        case "failed":
            print("Failed:", event.error)

Webhooks

# List webhooks
webhooks, available_events = client.webhooks.list()

# Create a webhook
webhook = client.webhooks.create(
    url="https://example.com/webhook",
    events=["video.completed", "video.failed"]
)
# Save webhook.secret - only shown once!

# Update a webhook
client.webhooks.update("webhook-id", events=["video.completed"], is_active=False)

# Test a webhook
result = client.webhooks.test("webhook-id")

# Delete a webhook
client.webhooks.delete("webhook-id")

Embed Settings

# Get embed settings
settings = client.embed.get_settings()

# Update embed settings
settings = client.embed.update_settings(
    primary_color="#FF0000",
    autoplay=True,
    muted=True
)

# Generate signed embed URL
embed = client.embed.sign("video-id")
print(embed.embed_url)
print(embed.embed_code["responsive"])

API Keys

# List API keys
api_keys = client.api_keys.list()

# Create an API key
key = client.api_keys.create("My App")
# Save key.key - only shown once!

# Delete an API key
client.api_keys.delete("key-id")

Account

# Get account info
account = client.account.get()

# Update allowed domains
account = client.account.update(
    allowed_domains=["example.com", "app.example.com"],
    allow_localhost=True
)

Usage

# Get usage statistics
usage = client.usage.get()

print(f"Plan: {usage.plan}")
print(f"Videos: {usage.usage.videos_this_month}/{usage.usage.videos_limit}")
print(f"Storage: {usage.usage.storage_used_gb} GB")

Webhook Signature Verification

from playvideo.webhook import verify_signature, construct_event
from playvideo.errors import WebhookSignatureError

# Flask example
@app.route("/webhook", methods=["POST"])
def webhook():
    payload = request.get_data()
    signature = request.headers.get("X-PlayVideo-Signature")
    timestamp = request.headers.get("X-PlayVideo-Timestamp")
    
    try:
        event = construct_event(payload, signature, timestamp, "whsec_xxx")
        
        match event["event"]:
            case "video.completed":
                print("Video ready:", event["data"])
            case "video.failed":
                print("Video failed:", event["data"])
        
        return "OK", 200
    except WebhookSignatureError as e:
        print("Invalid signature:", e)
        return "Invalid signature", 400

Error Handling

from playvideo import PlayVideo
from playvideo.errors import (
    PlayVideoError,
    AuthenticationError,
    NotFoundError,
    RateLimitError,
    ValidationError,
)

client = PlayVideo("play_live_xxx")

try:
    client.videos.get("invalid-id")
except AuthenticationError:
    print("Invalid API key")
except NotFoundError:
    print("Video not found")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except ValidationError as e:
    print(f"Invalid param: {e.param}")
except PlayVideoError as e:
    print(f"API error: {e.message} (code: {e.code})")

Error Types

Error Status Description
AuthenticationError 401 Invalid or missing API key
AuthorizationError 403 Insufficient permissions
NotFoundError 404 Resource not found
ValidationError 400/422 Invalid parameters
ConflictError 409 Resource conflict
RateLimitError 429 Too many requests
ServerError 5xx Server error
NetworkError - Connection failed
TimeoutError - Request timed out
WebhookSignatureError - Invalid signature

Configuration

client = PlayVideo(
    "play_live_xxx",
    # Custom base URL (for self-hosted)
    base_url="https://api.yourdomain.com/api/v1",
    # Request timeout in seconds (default: 30)
    timeout=60.0,
)

Context Managers

Both sync and async clients support context managers:

# Sync
with PlayVideo("play_live_xxx") as client:
    collections = client.collections.list()

# Async
async with AsyncPlayVideo("play_live_xxx") as client:
    collections = await client.collections.list()

Type Hints

The SDK includes full type hints for all methods and data classes:

from playvideo import PlayVideo, Video, Collection, VideoStatus

client = PlayVideo("play_live_xxx")

video: Video = client.videos.get("id")
status: VideoStatus = video.status  # Literal["PENDING", "PROCESSING", "COMPLETED", "FAILED"]

MCP Server

Use the PlayVideo MCP server to connect Claude/Desktop assistants to your account.

npm install -g @playvideo/playvideo-mcp

Repo: https://github.com/PlayVideo-dev/playvideo-mcp

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

License

MIT - see LICENSE for details.

Links

Metadata

Release files for playvideo-python 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for playvideo-python 1.0.0
File Size Uploaded
playvideo_python-1.0.0.tar.gz 22.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for playvideo-python 1.0.0
File Interpreter ABI Platform
playvideo_python-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 44.3 kB

Release files / playvideo_python-1.0.0.tar.gz

Download URL playvideo_python-1.0.0.tar.gz
Size 22.4 kB
Tags Source
SHA-256 checksum
How to use checksums
1f64b394b65892413243d1984c862e1c79ff5eab48499e720dfcb77e07a0f58e
BLAKE2b-256 checksum
How to use checksums
3533b12172eeb9bae65daab3d53aae0fbc22c629dc21fbaa044c8521a239f666
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 15, 2026.

Transparency log

Release files / playvideo_python-1.0.0-py3-none-any.whl

Download URL playvideo_python-1.0.0-py3-none-any.whl
Size 21.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
61bd5455f1dbc79e92df3c2fcf9c6720fe49dea16d57e9a8223ad72fe185ded4
BLAKE2b-256 checksum
How to use checksums
f030f6038841b65c43a789a87098088fbcec60309c950b2e8e8642edbda44aed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page