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.1.tar.gz (41.2 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.1-py3-none-any.whl (55.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ponyflash-0.2.1.tar.gz
  • Upload date:
  • Size: 41.2 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.1.tar.gz
Algorithm Hash digest
SHA256 449982b39b7ba0f910a0fd7cdb80d7e35a1e36fef7af8d21420fc21b0caa9ac7
MD5 7e962167e0fb5c5eb55cd0092a0e566b
BLAKE2b-256 1ce834f9ad34909648eb475928d17eb421d83637fea5ccc0268b6dca118cc69a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ponyflash-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 55.7 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5e3cf50724c052a431eaaa964b655fd2ca7e94f70519b0b16427d45e197a1211
MD5 a10bc436f1aced2cc3359c5f0adf07b8
BLAKE2b-256 78a452f217158963d4cf666f6fcb0ce0875d8d8f488e201b22427f5a590170c8

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