# Golpo Python SDK

Python SDK for [Golpo](https://video.golpoai.com) — generate AI-powered explainer videos and podcasts from text and documents.

## Installation

```bash
pip install golpo
```

## Quick start

```python
from golpo import Golpo

client = Golpo(api_key="your-api-key")

# Generate a video
result = client.create_video(prompt="Explain quantum computing in 2 minutes")
print(result.url)       # Video URL
print(result.script)   # Generated script
print(result.video_id) # Use for edit_video, get_frame_animations, etc.
```

---

## Client setup

```python
from golpo import Golpo

client = Golpo(api_key="your-api-key")
```

| Parameter   | Type | Description |
|------------|------|-------------|
| `api_key`  | `str` | Your Golpo API key (required). |

---

## API reference

### 1. `create_podcast` — Generate a podcast

Creates an AI-generated podcast from a prompt and optional documents. The call blocks until the podcast is ready and returns its URL, script, and ID.

**Returns:** `GenerationResult` (`.url`, `.script`, `.video_id`)

**Example**

```python
from golpo import Golpo, GenerationResult

client = Golpo(api_key="your-api-key")

# Prompt only
result: GenerationResult = client.create_podcast(
    prompt="Create a 5-minute podcast about climate change and renewable energy."
)
print(result.url)       # Podcast audio URL
print(result.script)    # Script text
print(result.video_id)  # Job ID (e.g. for tracking)

# With document URLs (no upload)
result = client.create_podcast(
    prompt="Summarize this document and discuss key points.",
    uploads=["https://example.com/document.pdf"],
)

# With local files (uploaded to S3 automatically)
result = client.create_podcast(
    prompt="Turn this into an explainer podcast.",
    uploads=["./my-doc.pdf", Path("./other-doc.pdf")],
    style="solo-female-3",
    bg_music="lofi",
    poll_interval=5,
)
```

**Parameters**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `prompt` | `str` | required | Topic or instructions for the podcast. |
| `uploads` | `str` \| `Path` \| iterable | `None` | Document URL(s) or local file path(s). Local files are uploaded in parallel. |
| `add_music` | `bool` | `False` | Add background music. |
| `voice_instructions` | `str` | `None` | Instructions for voice style. |
| `personality_1`, `personality_2` | `str` | `None` | Host personality hints. |
| `do_research` | `bool` | `False` | Whether the AI should research the topic. |
| `tts_model` | `str` | `"accurate"` | TTS model (`"accurate"` or `"fast"`). |
| `language` | `str` | `None` | Language code (e.g. `"hindi"`, `"english"`). |
| `style` | `str` | `"conversational"` | `"conversational"`, `"solo-male-3"`, `"solo-male-4"`, `"solo-female-3"`. |
| `bg_music` | `str` | `None` | `"jazz"`, `"lofi"`, `"dramatic"`, `"whimsical"`, `"engaging"`, `"hyper"`, `"inspirational"`, `"documentary"`. |
| `poll_interval` | `int` | `2` | Seconds between status polls. |
| `max_workers` | `int` | `8` | Max parallel uploads for local files. |
| `output_volume` | `float` | `1.0` | Output volume. |
| `no_voice_chunking` | `bool` | `False` | Disable voice chunking. |
| `new_script` | `str` | `None` | Use this script instead of generating one. Auto-estimates `timing` from word count. |
| `bg_volume` | `float` | `1.0` | Background music volume. |
| `timing` | `str` or `float` | `"1"` | Duration in minutes. Auto-calculated when `new_script` is provided. |

---

### 2. `create_video` — Generate a video

Creates an AI-generated explainer video from a prompt and optional documents. Blocks until the video is ready.

**Returns:** `GenerationResult` (`.url`, `.script`, `.video_id`)

**Example**

```python
from golpo import Golpo, GenerationResult

client = Golpo(api_key="your-api-key")

result: GenerationResult = client.create_video(
    prompt="Create a 2-minute explainer on how photosynthesis works.",
)
print(result.url)       # Video MP4 URL
print(result.script)    # Narration script
print(result.video_id)  # Use with edit_video, get_frame_animations

# Golpo Canvas style
result = client.create_video(
    prompt="How solar panels convert sunlight to electricity",
    use_2_style=True,
    image_style="modern_minimal",
    pen_style="stylus",
    timing="2",
)

# Golpo Sketch style
result = client.create_video(
    prompt="Explain blockchain technology step by step",
    use_lineart_2_style="true",
    pacing="normal",
    timing="2",
)

# With user-provided images and videos
result = client.create_video(
    prompt="Create a product showcase video",
    user_images=["~/product_photo_1.png", "~/product_photo_2.png"],
    user_images_descriptions=["Front view of the product", "Side view with packaging"],
    user_videos=["~/demo_clip.mp4"],
    user_videos_description=["App walkthrough demo"],
    user_audio_in_video=[False],
    timing="2",
)

# Script only (no video)
result = client.create_video(
    prompt="Explain recursion in programming",
    just_return_script=True,
)
print(result.script)  # Script text (result.url will be empty)
```

**Parameters**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `prompt` | `str` | required | Topic or instructions for the video. |
| `uploads` | `str` \| `Path` \| iterable | `None` | Document URL(s) or local file path(s). |
| `voice_instructions` | `str` | `None` | Voice style instructions. |
| `personality_1`, `personality_2` | `str` | `None` | Personality hints. |
| `do_research` | `bool` | `False` | Enable research. |
| `tts_model` | `str` | `"accurate"` | TTS model (`"accurate"` or `"fast"`). |
| `language` | `str` | `None` | Language code (e.g. `"hindi"`, `"english"`). |
| `style` | `str` | `"solo-female-3"` | `"solo-male-3"`, `"solo-male-4"`, `"solo-female-3"`. |
| `bg_music` | `str` | `"engaging"` | `"jazz"`, `"lofi"`, `"dramatic"`, `"whimsical"`, `"engaging"`, `"hyper"`, `"inspirational"`, `"documentary"`. |
| `bg_volume` | `float` | `1.0` | Background music volume. |
| `video_type` | `str` | `"long"` | `"short"` or `"long"`. |
| `include_watermark` | `bool` | `False` | Include watermark. |
| `new_script` | `str` | `None` | Override script; `timing` is auto-estimated from word count. |
| `just_return_script` | `bool` | `False` | Only generate script, no video. Returns empty `url`. |
| `logo` | `str` \| `Path` | `None` | Logo URL or local path. Auto-enables watermark. |
| `logo_placement` | `str` | `None` | Logo placement position. |
| `timing` | `str` or `float` | `"1"` | Duration in minutes (0.25–10). Must be ≥ 0.25. |
| `poll_interval` | `int` | `2` | Seconds between status polls. |
| `max_workers` | `int` | `8` | Max parallel uploads. |
| `output_volume` | `float` | `1.0` | Output volume. |
| `video_instructions` | `str` | `None` | Custom instructions for video generation and visual style. |
| `use_color` | `bool` | `True` | Create color videos instead of black-and-white. |
| `use_lineart_2_style` | `str` | `None` | Golpo Sketch style: `"false"` (classic), `"true"` (improved), or `"advanced"` (formal). **Do not combine with `use_2_style`.** |
| `use_2_style` | `bool` | `False` | Enable Golpo Canvas visual style. **Do not combine with `use_lineart_2_style`.** |
| `image_style` | `str` | `None` | Golpo Canvas image style: `"chalkboard_white"`, `"neon"`, `"whiteboard"`, `"modern_minimal"`, `"playful"`, `"technical"`, `"editorial"`, `"marker"`. Only with `use_2_style=True`. |
| `input_images` | `str`, `Path`, or `List` | `None` | Reference input images for Golpo Canvas. Only with `use_2_style=True`. |
| `pen_style` | `str` | `None` | Drawing pen style: `"stylus"`, `"marker"`, or `"pen"`. Auto-enables `show_pencil_cursor`. Only with `use_2_style=True`. |
| `show_pencil_cursor` | `bool` | `False` | Show a pencil cursor during drawing animation. Auto-enabled when `pen_style` is set. Only with `use_2_style=True`. |
| `pacing` | `str` | `"normal"` | `"normal"` (15s max per frame) or `"fast"` (10s max per frame). |
| `audio_clip` | `str` \| `Path` | `None` | Audio or video file path or URL. The audio will be extracted and included in the video generation. |
| `is_public` | `bool` | `None` | Set video visibility to public or private. |
| `use_as_is` | `str` or `List[bool]` | `None` | Per-frame flags to use generated images as-is without animation. |
| `skip_animation` | `str` or `List[bool]` | `None` | Per-frame flags to skip the drawing animation. |
| `user_images` | `str`, `Path`, or `List` | `None` | User-provided images (file paths or URLs). Local files are auto-uploaded to S3. |
| `user_images_descriptions` | `str` or `List[str]` | `None` | Descriptions for each user image. Strongly recommended for best visual results. |
| `user_videos` | `str`, `Path`, or `List` | `None` | User-provided video clips (file paths or URLs). Local files are auto-uploaded to S3. |
| `user_videos_description` | `str` or `List[str]` | `None` | Descriptions for each user video. |
| `user_audio_in_video` | `str` or `List[bool]` | `None` | Per-video flags for whether to use original audio from user videos. |

---

### 3. `edit_video` — Edit specific frames

Edits selected frames of an existing video using text prompts, then regenerates the video. Optionally combines all frames into one final video.

**Returns:** `VideoEditResult` (`.video_url`, `.job_id`; also supports `result["video_url"]`, `result.get("job_id")`)

**Example**

```python
from golpo import Golpo, VideoEditResult

client = Golpo(api_key="your-api-key")

# Use video_id from create_video result
result: VideoEditResult = client.edit_video(
    video_id="your-video-id",
    frame_ids=["0", "2", "5"],
    edit_prompts=[
        "Add a chart showing growth",
        "Change background to blue",
        "Add a callout to this section",
    ],
    video_url="https://..../original-video.mp4",
)
print(result.video_url)
print(result.job_id)

# With auto_combine: merge all frames into one video with audio
result = client.edit_video(
    video_id="your-video-id",
    frame_ids=["1"],
    edit_prompts=["Make the diagram larger"],
    video_url="https://..../original-video.mp4",
    auto_combine=True,
    poll_interval_ms=3000,
)
```

**Parameters**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `video_id` | `str` | required | Video/job ID (e.g. from `create_video`). |
| `frame_ids` | `List[str]` | required | Frame indices to edit. |
| `edit_prompts` | `List[str]` | required | One prompt per frame; length must match `frame_ids`. |
| `video_url` | `str` | required | URL of the original video. |
| `reference_images` | `List[str]` | `None` | Optional reference image URLs. |
| `user_id` | `str` | `None` | Optional user ID. |
| `poll_interval_ms` | `int` | `2000` | Polling interval in milliseconds. |
| `auto_combine` | `bool` | `False` | If `True`, combine all frames into one video with audio. |

---

### 4. `combine_videos` — Combine multiple videos

Combines several MP4 URLs into a single video. Useful for merging frame-level animations (e.g. after editing) with optional audio from an original video.

**Returns:** `CombinedVideoResult` (`.url`)

**Example**

```python
from golpo import Golpo, CombinedVideoResult

client = Golpo(api_key="your-api-key")

result: CombinedVideoResult = client.combine_videos(
    mp4_urls=[
        "https://..../frame-0.mp4",
        "https://..../frame-1.mp4",
        "https://..../frame-2.mp4",
    ],
    video_url="https://..../original-with-audio.mp4",  # Optional: use for audio
    poll_interval_ms=2000,
)
print(result.url)  # Combined video URL
```

**Parameters**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `mp4_urls` | `List[str]` | required | At least one MP4 URL. |
| `video_url` | `str` | `None` | Optional source video URL for audio. |
| `poll_interval_ms` | `int` | `2000` | Polling interval in milliseconds. |

---

### 5. `get_frame_animations` — Get frame animation URLs

Returns a mapping of frame index → animation URL for a video. Use this to inspect frame-level outputs or to pass URLs into `combine_videos`.

**Returns:** `Dict[str, str]` (frame index → animation URL)

**Example**

```python
from golpo import Golpo

client = Golpo(api_key="your-api-key")

animations = client.get_frame_animations(video_id="your-video-id")
# e.g. {"0": "https://.../frame-0.mp4", "1": "https://.../frame-1.mp4", ...}

for frame_id, url in animations.items():
    print(f"Frame {frame_id}: {url}")

# Use with combine_videos
urls = list(animations.values())
combined = client.combine_videos(mp4_urls=urls, video_url=original_video_url)
```

**Parameters**

| Parameter | Type | Description |
|-----------|------|-------------|
| `video_id` | `str` | Video/job ID (e.g. from `create_video`). |

---

### 6. `update_video` — Update video metadata

Updates video metadata such as prompt, context, scenes, video URL, and frame animations. Requires JWT authentication.

**Returns:** `Dict[str, Any]`

**Example**

```python
from golpo import Golpo

client = Golpo(api_key="your-api-key")

result = client.update_video(
    video_id="your-video-id",
    prompt="Updated prompt text",
    scenes=8,
    jwt_token="your-jwt-token",
)
```

**Parameters**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `video_id` | `str` | required | The ID of the video to update. |
| `prompt` | `str` | `None` | New prompt. |
| `context` | `str` | `None` | New context. |
| `scenes` | `int` | `None` | Number of scenes. |
| `video_url` | `str` | `None` | New video URL. |
| `frame_animations` | `Dict[str, Any]` | `None` | Frame animations dictionary. |
| `jwt_token` | `str` | required | JWT token for authentication. |

---

## Result types

Import from `golpo`:

```python
from golpo import GenerationResult, VideoEditResult, CombinedVideoResult
```

| Type | Attributes | Used by |
|------|------------|--------|
| `GenerationResult` | `url`, `script`, `video_id` | `create_podcast`, `create_video` |
| `VideoEditResult` | `video_url`, `job_id` (and `["video_url"]`, `.get("job_id")`) | `edit_video` |
| `CombinedVideoResult` | `url` | `combine_videos` |

---

## Uploads (local files vs URLs)

- **URLs** (e.g. `https://...` or `s3://...`): Sent as-is in the `upload_urls` form field.
- **Local paths** (`str` or `pathlib.Path`): Uploaded to S3 via `/upload-url`, then the resulting URLs are sent. Uploads run in parallel (controlled by `max_workers`).

You can mix URLs and paths in a single list:

```python
client.create_video(
    prompt="...",
    uploads=[
        "https://example.com/doc.pdf",
        "./local-file.pdf",
        Path("~/Documents/other.pdf"),
    ],
)
```

---

## Errors

The SDK may raise:

- `ValueError` — Invalid arguments (e.g. empty prompt, mismatched `frame_ids`/`edit_prompts`, missing `video_url`, timing < 0.25).
- `FileNotFoundError` — A local path in `uploads` does not exist.
- `TimeoutError` — Edit/combine job did not complete within the allowed time.
- `requests.HTTPError` — API returned an error status (e.g. 4xx/5xx).

Handle these in your code as needed (retries, logging, user message).

---

## Links

- **Homepage:** [https://video.golpoai.com](https://video.golpoai.com)
- **Python:** Requires 3.8+
