Metadata-Version: 2.5
Name: visionstory
Version: 0.0.10
Summary: Official Python SDK for the VisionStory API - AI talking-avatar video generation.
Project-URL: Homepage, https://developers.visionstory.ai
Project-URL: Documentation, https://developers.visionstory.ai/guides/sdk
Author-email: VisionStory <register@visionstory.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: ai,avatar,talking-avatar,text-to-video,video-generation,visionstory
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# VisionStory Python SDK

Official Python SDK for the [VisionStory API](https://developers.visionstory.ai) — generate AI talking-avatar videos from text or audio.

- **Zero dependencies** — Python standard library only, Python 3.10+.
- **Blocking semantics built in** — `generate_video()` submits the job and polls until the video is ready: one call in, a finished video out.
- **Agent-friendly** — auth via environment variable, actionable error messages, idempotent retries.
- **CLI-compatible** — `pip install visionstory-cli` adds a `visionstory` command over the same operations.

## Installation

```bash
pip install visionstory
```

Interactive SDK sessions check for new releases quietly and show an actionable notice at most once per week. Checks are cached, never install anything, and fail silently offline. For an explicit machine-readable check:

```python
from visionstory import check_for_updates

print(check_for_updates())
```

Set `VISIONSTORY_UPDATE_CHECK=0` to disable passive notices.

## Command line

Install `visionstory-cli` to get a `visionstory` command that covers the **same surface as the SDK** — no code required:

```bash
pip install visionstory-cli
```

```bash
export VISIONSTORY_API_KEY="sk-vs-xxxxxxxxxxxxxxxxxxx"

# Discover resources
visionstory models
visionstory avatars --is-public
visionstory voices
visionstory credits
visionstory assets

# Talking-avatar video
visionstory create-video --avatar-id 4321918387609092991 --text "Hello from VisionStory." --voice-id Alice --output result.mp4
visionstory status --video-id 7241059991822401536

# Avatars / voices / assets
visionstory create-avatar --image-url https://your.site/face.jpg
visionstory update-avatar-framing --avatar-id <id> --aspect-ratio 9:16 --zoom 1.2 --offset-x 0 --offset-y -0.25
visionstory clone-voice --audio-url https://your.site/sample.mp3
visionstory upload-asset --url https://your.site/clip.mp4

# Text-to-speech, transcription, alignment, and image generation (beta)
visionstory tts --text "Hello" --voice-id Alice --locale en-GB --output speech.mp3
visionstory transcribe --audio-file interview.mp3 --diarize --srt --output interview.srt
visionstory align --audio-url https://your.site/speech.mp3 --text "Hello"
visionstory create-image --model-id <model> --prompt "a corgi surfing at sunset"

# AI video (Seedance, Wan, Kling) (beta)
visionstory ai-video-models
visionstory ai-video-cost --model-id seedance-2.0 --duration-sec 8 --resolution 1080p
visionstory create-ai-video --model-id seedance-2.0 --prompt "a corgi surfing at sunset" --output ai.mp4

# Delete
visionstory delete-video --video-id 7241059991822401536
```

Every subcommand prints JSON and maps 1:1 to a client method. `create-video` / `create-ai-video` block until the video is ready and, with `--output`, download it (add `--no-wait` to return the task immediately). The `create-image` / `create-ai-video` commands also accept `--json '<body>'` to pass a full request body for advanced media references. Run `visionstory --help` (or `visionstory <command> --help`) for every command and option. The key is read from `VISIONSTORY_API_KEY` and never passed on the command line.

## Quick start

Create an API key on the [VisionStory API keys page](https://developers.visionstory.ai/api-keys) and export it:

```bash
export VISIONSTORY_API_KEY="sk-vs-xxxxxxxxxxxxxxxxxxx"
```

Text in, talking-avatar video out — five lines:

```python
from pathlib import Path
from visionstory import VisionStoryClient, build_video_payload

client = VisionStoryClient.from_env()  # reads VISIONSTORY_API_KEY
video = client.generate_video(build_video_payload(avatar_id="4321918387609092991", text="Hello World, this is my first test video.", voice_id="Alice"))
client.download(video["video_url"], Path("result.mp4"))
```

`generate_video()` blocks until the task reaches a terminal state (default timeout 600s, polling every 5s) and returns the finished video object, including `video_url`. Completed videos are retained for **7 days** — download the file if you need permanent storage.

Before building a production integration, discover current IDs instead of hardcoding them:

```python
client.list_models()   # GET /api/v1/models
client.list_avatars(limit=20)                  # owned avatars
client.list_avatars(is_public=True, limit=20)  # public avatar library
client.list_voices(locale="en-GB", limit=20)   # GET /api/v1/voices
```

Avatar responses contain `avatars` and `next_cursor`; pass the latter back as `cursor=`. To change one saved crop on an owned avatar, call `client.update_avatar_framing(avatar_id=..., aspect_ratio="9:16", zoom=1.2, offset_x=0, offset_y=-0.25)`. Public avatars cannot be reframed.

All public channels carry the same generated contract fingerprint. Use it in diagnostics or release
checks to confirm the SDK, CLI, and MCP server were built from the same OpenAPI contract:

```python
from visionstory import get_contract_info

print(get_contract_info())
# {'contract_version': '1.0.0', 'contract_hash': 'sha256:...', 'operation_count': 28}
```

Transcribe audio or align known text with word-level timestamps from a local WAV/MP3 file, public URL, or reusable asset:

```python
transcript = client.transcribe_audio(audio_file=Path("interview.mp3"), diarize=True, srt=True)
alignment = client.align_audio(text="Hello", asset_id="YOUR_AUDIO_ASSET_ID")
speech = client.create_speech(text="Hello", voice_id="YOUR_VOICE_ID", locale="en-GB")
```

To use your own audio instead of text, pass `audio_url=` or `audio_file=` (a local file, base64-encoded automatically) to `build_video_payload()` in place of `text=` — exactly one source is allowed.

### Non-blocking mode

Prefer to manage polling yourself? Submit and poll separately:

```python
created = client.generate_video(payload, wait=False)   # returns {"video_id": ...} immediately
video = client.wait_for_video(created["video_id"])      # or client.get_video(video_id) manually
```

## Idempotent retries (`client_request_id`)

Video creation charges credits, so retrying a request that may have already succeeded is risky. Add a `client_request_id` (an idempotency key of your choice) to make resubmission safe — within 24 hours, the same key returns the original task instead of creating and charging a new one:

```python
payload = build_video_payload(avatar_id="4321918387609092991", text="Hello!", voice_id="Alice")
payload["client_request_id"] = "order-42-intro-video"  # ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$
video = client.generate_video(payload)                  # safe to retry on network errors
```

If the first submission is still in flight, a retry gets HTTP 409 with a hint to retry shortly.

## Error handling

All API failures raise `VisionStoryAPIError`. The message embeds the API's error body, which carries an `error.hint` field — a one-sentence, actionable next step (e.g. out of credits → top up at the pricing page). Print it as-is or feed it to your agent:

```python
from visionstory import VisionStoryAPIError

try:
    video = client.generate_video(payload)
except VisionStoryAPIError as e:
    print(e)  # e.g. POST /api/v1/video failed with HTTP 403: {"error": {"code": ..., "message": ..., "hint": "..."}}
```

Failed generations are refunded automatically; `generate_video()` raises with that context instead of returning a failed task.

## Configuration

| Environment variable | Purpose | Default |
|---|---|---|
| `VISIONSTORY_API_KEY` | API key (required for `from_env()`) | — |
| `VISIONSTORY_API_BASE` | API base URL override | `https://openapi.visionstory.ai` |

You can also construct the client explicitly: `VisionStoryClient(api_key, base_url=..., request_timeout=...)`.

## More resources

- [API documentation](https://developers.visionstory.ai) — full reference, guides, and error codes.
- [Quick start guide](https://developers.visionstory.ai/guides/quick-start)
- [For agents](https://developers.visionstory.ai/guides/for-agents) — MCP server, Agent Skill package, and llms.txt.

## Development

This is a zero-dependency client (Python standard library only). The
`visionstory/_core.py` module is generated and kept in sync with the
VisionStory API — do not edit it by hand.

## Structured media extraction and speech rate

Use `understand_media` for schema-constrained JSON from images, audio, or video. It takes required `prompt`, `inputs`, and `schema`, waits synchronously for up to 180 seconds, and returns `output`, `usage`, and `cost_credit`.

```python
from visionstory import VisionStoryClient

client = VisionStoryClient.from_env()
result = client.understand_media(
    prompt="Identify the subject",
    inputs=[{"asset_id": "YOUR_ASSET_ID"}],
    schema={"type": "object", "properties": {"subject": {"type": "string"}}, "required": ["subject"]},
)
print(result["output"])

speech = client.create_speech(text="Hello", voice_id="YOUR_VOICE_ID", speech_rate="slow")
# Save speech["audio"] as MP3. Omit speech_rate to keep normal speed.
```

`speech_rate` accepts `slow`, `normal`, or `fast`; `None` leaves the field out. See [Media Understanding](https://developers.visionstory.ai/guides/media-understanding) for input limits, billing, and timeout handling, and [Text to Speech](https://developers.visionstory.ai/guides/text-to-speech) for binary responses.
