Metadata-Version: 2.5
Name: allens-h3
Version: 1.0.0
Summary: Python SDK for Allen's MiniMax H3 video generation API
Project-URL: Homepage, https://github.com/AICAllenZhou/allens-h3-python
Project-URL: Repository, https://github.com/AICAllenZhou/allens-h3-python
Project-URL: Documentation, https://github.com/AICAllenZhou/allens-h3-python#readme
Project-URL: Changelog, https://github.com/AICAllenZhou/allens-h3-python/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/AICAllenZhou/allens-h3-python/issues
Author: Allen Zhou
License: MIT License
        
        Copyright (c) 2026 Allen Zhou
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: ai,h3,minimax,text-to-video,video-generation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx<1.0,>=0.24
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Description-Content-Type: text/markdown

# Allen's MiniMax H3 Python SDK

Text-to-video with synchronised audio, generated on a private RTX 3090.

You do not need to know anything about HTTP endpoints, job polling, ComfyUI or
workflow graphs — submit a prompt, get an MP4.

```python
from allens_h3 import H3Client

client = H3Client()
video = client.generate(prompt="A cinematic AI business school commercial",
                        duration=5)
video.download("video.mp4")
```

---

## Install

```bash
pip install allens-h3
```

From a local wheel:

```bash
pip install dist/allens_h3-1.0.0-py3-none-any.whl
```

Requires Python 3.9+. The only runtime dependency is `httpx`.

---

## Configure

Two values are needed. Neither is ever hard-coded in the SDK, because the
endpoint hostname can change.

| Variable | Meaning |
|---|---|
| `ALLENS_H3_BASE_URL` | HTTPS endpoint, e.g. `https://xxxx.trycloudflare.com` |
| `ALLENS_H3_API_KEY` | your credential |

```bash
# macOS / Linux
export ALLENS_H3_BASE_URL="https://xxxx.trycloudflare.com"
export ALLENS_H3_API_KEY="..."
```

```powershell
# Windows PowerShell
$env:ALLENS_H3_BASE_URL = "https://xxxx.trycloudflare.com"
$env:ALLENS_H3_API_KEY  = "..."
```

Or pass them explicitly:

```python
client = H3Client(api_key="...", base_url="https://xxxx.trycloudflare.com")
```

Explicit arguments win; otherwise the environment is used.

> The endpoint currently runs through a Cloudflare Quick Tunnel, whose
> hostname **changes whenever the tunnel restarts**. Ask for the current URL,
> or update `ALLENS_H3_BASE_URL` when it moves.

---

## Generate

```python
video = client.generate(
    prompt="A cinematic nighttime shot of downtown Vancouver after rain",
    width=608,        # multiple of 32
    height=352,       # multiple of 32
    duration=5,       # 1-10 seconds
    steps=20,         # 4-40
    seed=None,        # omit for the server default
    timeout=1800,
)

print(video.job_id)
video.download("output.mp4")
data = video.content()      # or get the bytes directly
```

`generate()` submits the job, polls until it finishes, and returns the result.
A 5-second clip takes roughly 4-5 minutes.

With a progress callback:

```python
video = client.generate(
    prompt="...",
    on_progress=lambda job: print(f"{job.status} {job.percent}%"),
)
```

---

## Job control

For long jobs you may not want to block:

```python
job = client.create_video(prompt="...", duration=5)
print(job.id, job.status)          # queued

job = client.get_job(job.id)       # poll whenever you like
print(job.status, job.percent)

job = client.wait(job.id)          # block until terminal
client.download(job.id, "out.mp4")
```

Cancel a queued or running job:

```python
client.cancel(job.id)
```

List your recent jobs (only ever your own):

```python
for job in client.list_jobs(limit=10):
    print(job.id, job.status)
```

---

## Service and GPU status

```python
health = client.health()
print(health.is_ok, health.comfyui, health.worker)

gpu = client.gpu()
print(gpu.name, gpu.temperature_c, gpu.hotspot_c, gpu.power_w, gpu.is_busy)
```

---

## Async

```python
import asyncio
from allens_h3 import AsyncH3Client

async def main():
    async with AsyncH3Client() as client:
        video = await client.generate(prompt="A cinematic commercial",
                                      duration=5)
        await video.download("output.mp4")

asyncio.run(main())
```

The async API mirrors the sync one method for method.

---

## Error handling

Every failure is a typed exception, so you never inspect a status code:

```python
from allens_h3 import (
    H3Error, H3AuthenticationError, H3RateLimitError,
    H3ValidationError, H3GPUUnavailableError, H3JobFailedError,
    H3TimeoutError,
)

try:
    video = client.generate(prompt="...")
except H3AuthenticationError:
    print("bad or revoked key")
except H3RateLimitError as e:
    print(f"slow down; retry after {e.retry_after}s")
except H3ValidationError as e:
    print(f"bad parameters: {e}")
except H3GPUUnavailableError:
    print("GPU busy or too hot; try later")
except H3JobFailedError as e:
    print(f"job {e.job_id} ended as {e.job_status}")
except H3TimeoutError:
    print("still running — poll get_job() to keep checking")
except H3Error as e:
    print(f"unexpected: {e}")
```

| Exception | HTTP |
|---|---|
| `H3ValidationError` | 400, 413, 422 |
| `H3AuthenticationError` | 401 |
| `H3PermissionError` | 403 |
| `H3NotFoundError` | 404 |
| `H3ConflictError` | 409 |
| `H3RateLimitError` | 429 |
| `H3GPUUnavailableError` | 502, 503, 504 |

---

## Command line

For colleagues who do not write Python:

```bash
allens-h3 health
allens-h3 gpu

allens-h3 generate \
  --prompt "A cinematic BBA AI commercial" \
  --duration 5 \
  --output output.mp4

allens-h3 jobs
allens-h3 status h3_abc123
allens-h3 cancel h3_abc123
allens-h3 download h3_abc123 -o video.mp4
```

The CLI reads credentials from the environment only — passing a key as a flag
would leave it in your shell history.

---

## Limits

Server-enforced, per credential:

| Limit | Default |
|---|---|
| API requests | 20 / minute |
| Generations | 12 / hour |
| Queued jobs | 3 |
| Prompt length | 2000 characters |
| Resolution | 256-1280 × 256-720, multiples of 32 |
| Duration | 1-10 seconds |
| Steps | 4-40 |

Only one job runs on the GPU at a time; the rest queue.

---

## Security

- TLS verification is always on and **cannot** be disabled.
- The API key travels in the `Authorization` header, never in a URL.
- The key is never written to disk or to any log by this SDK.
- Exception messages are scrubbed of anything credential-shaped.
- `base_url` is validated; embedded credentials are rejected.
- Plain `http://` to a remote host is refused.
- Failed reads and 502/503/504 are retried with exponential backoff;
  generation requests are **never** retried automatically, to avoid
  producing a duplicate video.

---

## Version

1.0.0 — see `CHANGELOG.md`.
