# Storyboard

A CLI tool for generating storyboards. Define characters, create reusable templates, and build interactive scenes through YAML configuration.

## Quickstart

Install `storyboard` with `pip` or `uv`:

```
pip install storyboard-cli
```

Or with `uv`:

```
uv tool install storyboard-cli
```

Create a project:

```
storyboard init
```

You'll be asked to provide a project name and a Gemini API key, which you can get [here](https://aistudio.google.com/app/apikey).

Generate images and audio from the template:

```
storyboard run
```

The output will be in `output/`. You can also view in a browser using the `serve` command:

```
storyboard serve
```

## Example

```yaml
# Character with voice and appearance
_nick:
  name: Nick
  reference_photo: ./assets/nick.webp
  tts:
    style: Narrate in a frantic tone
    voice: Fenrir

# Reusable image template with variables
_oblivion_inventory:
  instructions: |
    Turn the person in this photo {image $character_reference} into the style of an Oblivion character and create an inventory screen like in this picture: {image ./assets/oblivion_inventory.webp}
    The character should be equipped with the following items: {$inventory_items}. 
    The background setting should be: {$background}. 
    In the inventory section on the left side of the screen, display this list of items: {$inventory_items}.{$extra_instructions}

# Scene with frame that uses the template
_inn:
  name: The Aftermath
  frames:
    _inventory:
      image:
        template: _oblivion_inventory
        $character_reference: "@characters._nick.reference_photo"
        $inventory_items: empty skooma bottle
        $background: Inside a medieval tavern
        $extra_instructions: The character is in a bed, with Skooma bottles on his bedside table.
```

| Input: Reference photo | Input: Inventory screen | Output |
|------------------|------------------------|--------|
| ![Image](./docs/assets/nick.webp) | ![Image](./docs/assets/oblivion_inventory.webp) | ![Image](./docs/assets/nicks_inventory.webp) |


## How It Works

1. **Define characters** with voice attributes and reference photos for consistent appearance.
2. **Create templates** for images and dialogue.
3. **Build scenes** containing frames that render templates with specific values.
4. **Generate storyboard assets** using Gemini models.
5. **Reference data** across the configuration using cross-references (`@`).

## Configuration

Configuration settings:

```yaml
config:
  output:
    directory: ./output
    cache:
      images: .storyboard/generated/images
      audio: .storyboard/generated/audio

  image:
    default_model:
      vendor: gemini
      model: gemini-3-pro-image-preview
    optimize:
      enabled: true
      quality: 80

  tts:
    default_model:
      vendor: gemini
      model: gemini-2.5-flash-preview-tts
    optimize:
      enabled: true
      quality: 8

  generation:
    max_concurrent: 10
    timeout_seconds: 120
    retry:
      enabled: true
      max_attempts: 3
      delay_seconds: 2
```

## Syntax

### Identifiers
`_` prefix defines reusable objects (characters, scenes, templates):

```yaml
_nick:
  name: Nick
  reference_photo: ./assets/nick.png
```

### Variables
`$` prefix for template variables:

```yaml
# Definition
$backdrop: A medieval tavern

# Reference in text
"The backdrop should be: {$backdrop}"
```

### Cross-References
`@` references other configuration parts:

```yaml
character: "@characters._chris"              # Entire object
name: "@characters._nick.name"               # Nested property
dialogue: "@parent.tts.content"              # Parent reference
```

### Image Templates
Templates with inline images and variable substitution:

```yaml
_oblivion_dialogue:
  instructions: |
    Transform {image $character_reference} into Oblivion style.
    Reference style: {image ./assets/oblivion.webp}
    Name: '{$character_name}'. Backdrop: {$backdrop}.
```

**Syntax:**
- `{image $variable}` - Variable containing image path
- `{image ./path/to/file.jpg}` - Static image file
- `{$variable}` - Text variable substitution

**Using templates:**

```yaml
image:
  template: _oblivion_dialogue
  $character_reference: "@characters._chris.reference_photo"
  $character_name: "@characters._chris.name"
  $backdrop: "A medieval tavern"
```
