Skip to main content

PonyFlash Python SDK — Image, Video & Audio generation

Project description

PonyFlash Python SDK

AI-native image, video, speech, and music generation SDK.

Zero friction file handling — pass open() file objects, Path objects, URLs, bytes, or file_id strings. The SDK auto-uploads via presigned URLs and cleans up temp files when the task completes.

Installation

pip install ponyflash

如果你需要本地时间线合成能力:

pip install ponyflash[editor]

Quick Start

from ponyflash import PonyFlash

client = PonyFlash(api_key="rk_xxx")

# Text-to-image
gen = client.images.generate(
    model="nano-banana-pro",
    prompt="A sunset over mountains",
    resolution="2K",
)
print(gen.url)                         # first output URL
print(f"Credits used: {gen.credits}")  # credits consumed

本地视频编辑 ponyflash.editor

ponyflash.editor 是正式的一等能力,运行在本地 FFmpeg 上,不依赖云端生成接口,也不需要 API Key。

from ponyflash.editor import Timeline, Track, Clip, VideoAsset, Transition

track = Track()
track.add_clip(0, Clip(asset=VideoAsset("scene1.mp4"), duration=3.0))
track.add_clip(
    2.0,
    Clip(asset=VideoAsset("scene2.mp4"), duration=3.0),
    transition=Transition.DISSOLVE,
    transition_duration=1.0,
)

timeline = Timeline(aspect_ratio="16:9")
timeline.add_track(track)
timeline.render("output.mp4", resolution="1080p")

规则摘要:

  • Track.add_clip(start, clip) 使用绝对时间轴语义。
  • 主视频轨允许 gap,会按黑帧/静音保留时间线。
  • 主视频轨的 xfade 必须使用合法重叠窗口;例如前一个片段 3 秒、转场 1 秒,则下一个片段应从 2.0 秒开始,而不是 3.0 秒。
  • 显式 "WxH" 分辨率必须是偶数宽高。

Video Generation

from pathlib import Path

# Text-to-video
gen = client.video.generate(
    model="video-gen-1",
    prompt="A timelapse of a city at night",
    size="1920x1080",
    duration=8,
)
print(gen.url)

> `size`  `resolution` / `aspect_ratio` 互斥使用 `size` 不要再同时传 `resolution`  `aspect_ratio`。

# First-frame to video (local file)
with open("my_photo.jpg", "rb") as f:
    gen = client.video.generate(
        model="video-gen-1",
        first_frame=f,
        prompt="Camera slowly zooms in",
    )

# First-frame to video (public URL)
gen = client.video.generate(
    model="video-gen-1",
    first_frame="https://example.com/photo.jpg",
    prompt="Camera slowly zooms in",
)

# OmniHuman: portrait + audio → talking video
with open("portrait.jpg", "rb") as img, open("speech.wav", "rb") as audio:
    gen = client.video.generate(
        model="omnihuman-1.5",
        first_frame=img,
        audio=audio,
        prompt="Natural speaking with subtle hand gestures",
        size="1280x720",
    )

# OmniHuman with fast mode and seed
with open("portrait.jpg", "rb") as img, open("speech.wav", "rb") as audio:
    gen = client.video.generate(
        model="omnihuman-1.5",
        first_frame=img,
        audio=audio,
        seed=42,
        fast_mode=True,
    )

# Motion Transfer: person image + dance video → person performs the dance
with open("my_avatar.jpg", "rb") as img, open("dance_clip.mp4", "rb") as vid:
    gen = client.video.generate(
        model="motion-transfer-1",
        first_frame=img,
        motion_video=vid,
        size="1280x720",
    )

Image Generation

# Text-to-image
gen = client.images.generate(
    model="nano-banana-pro",
    prompt="A sunset",
    resolution="2K",
    aspect_ratio="16:9",
)

> `size`  `resolution` / `aspect_ratio` 互斥推荐优先使用 `resolution + aspect_ratio`,或直接使用一个明确的 `size`。

# Image-to-image (local file)
with open("source.png", "rb") as f:
    gen = client.images.generate(
        model="nano-banana-pro",
        prompt="Make it look like a watercolor painting",
        reference_images=[f],
    )

# Image-to-image (public URL)
gen = client.images.generate(
    model="nano-banana-pro",
    prompt="Make it look like a watercolor painting",
    reference_images=["https://example.com/source.png"],
)

# Inpainting with mask
with open("photo.jpg", "rb") as img, open("mask.png", "rb") as mask:
    gen = client.images.generate(
        model="nano-banana-pro",
        prompt="Replace the sky with aurora borealis",
        reference_images=[img],
        mask=mask,
    )

Speech Synthesis (TTS)

gen = client.speech.generate(
    model="speech-2.8-hd",
    input="Welcome to PonyFlash, this is a speech synthesis demo.",
    voice="English_Graceful_Lady",
    language="zh-CN",
)
print(gen.url)

# With emotion and pitch control
gen = client.speech.generate(
    model="speech-2.8-hd",
    input="What a beautiful day, I am so happy!",
    voice="English_Insightful_Speaker",
    emotion="happy",
    pitch=2,
    speed=1.1,
)

Music Generation

gen = client.music.generate(
    model="suno-v4.5",
    prompt="A melancholic indie folk ballad with acoustic guitar",
    title="Autumn Leaves",
    duration=180,
)

# Extend from reference audio
with open("my_song_clip.mp3", "rb") as f:
    gen = client.music.generate(
        model="suno-v4.5",
        prompt="Continue with an energetic chorus",
        reference_audio=f,
        continue_at=60.0,
    )

Downloading Results

import httpx

gen = client.images.generate(
    model="nano-banana-pro",
    prompt="A cat wearing sunglasses",
    resolution="2K",
)

# Download the generated image
resp = httpx.get(gen.url)
with open("output.png", "wb") as f:
    f.write(resp.content)

# Multiple outputs
for i, url in enumerate(gen.urls):
    resp = httpx.get(url)
    with open(f"output_{i}.png", "wb") as f:
        f.write(resp.content)

File Input Types

Every file parameter (reference_images, mask, first_frame, audio, motion_video, reference_audio, ...) accepts:

Input Example Behavior
Open file object open("photo.jpg", "rb") Recommended. Auto-uploaded, auto-cleaned.
Path object Path("photo.jpg") Same as above.
bytes image_bytes Same as above.
(filename, bytes) tuple ("photo.jpg", data) Same as above.
URL string "https://example.com/photo.jpg" Passed directly to backend. No upload.
file_id string "file_abc123" Reuses a previously uploaded file.

generate() auto-cleans temp files after the task completes. submit() does not — use it when you need request_id for manual polling.

普通本地字符串路径(例如 "./photo.jpg"不支持。本地文件请使用 Path("photo.jpg")open("photo.jpg", "rb")

Non-blocking: submit() + generations.wait()

task = client.images.submit(model="nano-banana-pro", prompt="A sunset")
print(task.request_id)           # "req_img_001"
print(task.estimated_credits)    # 20

# ... do other work ...

gen = client.generations.wait(task.request_id)
print(gen.url)

Async

from ponyflash import AsyncPonyFlash

client = AsyncPonyFlash(api_key="pf_xxx")

gen = await client.images.generate(model="nano-banana-pro", prompt="A sunset")
print(gen.url)

Configuration

client = PonyFlash(
    api_key="pf_xxx",                           # or PONYFLASH_API_KEY env var
    base_url="https://custom.example.com/v1",    # or PONYFLASH_BASE_URL env var
    max_retries=3,
)

# Polling timeout is per-resource, not per-client:
gen = client.video.generate(
    model="video-gen-1",
    prompt="...",
    timeout=900.0,     # wait up to 15 min for the task to complete (default: 900s)
)

Two kinds of timeout:

  • PonyFlash(timeout=...) — per-HTTP-request timeout (default 300s). Only affects individual API calls.
  • generate(timeout=...) — polling timeout, how long to wait for the task to finish. Defaults vary by resource: images 120s, video 900s, music 600s, speech 300s.

Advanced: Manual File Management

The file API is available for advanced use cases:

from pathlib import Path

# Upload explicitly (useful when reusing across multiple requests)
file_id = client.files.upload(Path("large_video.mp4"))

# Use the file_id in multiple requests without re-uploading
gen1 = client.video.generate(model="video-gen-1", video=file_id, prompt="Style A")
gen2 = client.video.generate(model="video-gen-1", video=file_id, prompt="Style B")

# Clean up when done
client.files.delete(file_id)

# List and inspect files
files = client.files.list()
info = client.files.get(file_id)
print(info.status, info.expires_at)

Editor Docs

  • 编辑器完整示例:见 examples/editor_demo.py
  • 如果你在使用 ponyflash-skill,请同步查看对应的 reference/editor.md

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

ponyflash-0.2.2.tar.gz (41.6 kB view details)

Uploaded Source

Built Distribution

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

ponyflash-0.2.2-py3-none-any.whl (56.2 kB view details)

Uploaded Python 3

File details

Details for the file ponyflash-0.2.2.tar.gz.

File metadata

  • Download URL: ponyflash-0.2.2.tar.gz
  • Upload date:
  • Size: 41.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for ponyflash-0.2.2.tar.gz
Algorithm Hash digest
SHA256 0b6ad11400181092b626de30290e84680f8de364f88c88ac27d92283d6faacf4
MD5 f4b6de7bce2996f5534dda6d5c8d1f12
BLAKE2b-256 8d7e2bb530ea740be5327771175eda33f6cf8e502cb724aaef05ebf7430273ac

See more details on using hashes here.

File details

Details for the file ponyflash-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: ponyflash-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 56.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for ponyflash-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b049828ece64d7ce8a3f159e8fd878da6ec7a403b061ab8db7b54547aaf3f175
MD5 974d525bf5fc93c0556502c9a897a4a6
BLAKE2b-256 7b76f0ac50f6a035de45092d86b203939507a16e7276199f8fc90a5c3a0670d7

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