# Deck reference (YAML or JSON)

Quick reference for top-level deck keys, sections, verses, and video export. Use `.yaml`, `.yml`, or `.json` with the same schema; `praisonaippt -i deck.json` runs the same validation and pipeline as YAML. HeyGen variant outputs remain `.yaml` after `sync-variants`.

For layout-specific fields see [Standard slide layouts](slide-layouts.md), [Avatar layouts](avatar-layouts.md), and [Deck layouts](deck-layouts.md).

Source: `praisonaippt/schema.py`, `praisonaippt/yaml_validate.py`, `praisonaippt/video_exporter.py`, `praisonaippt/deck_pipeline.py`.

---

## Top-level keys

| Key | Required | Description |
|-----|----------|-------------|
| `presentation_title` | recommended | Opening title slide |
| `presentation_subtitle` | optional | Title slide subtitle |
| `sections` | yes (auto `[]` if omitted) | List of section objects |
| `slide_style` | optional | Colours, typography, `layouts.*` — see [Slide style reference](slide-style-reference.md) |
| `slide_size` | optional | e.g. `widescreen` |
| `template` | optional | Named theme template |
| `extends` | optional | Parent template chain |
| `auto_upload_gdrive` | optional | Upload after build |
| `video_export` | optional | MP4 compositor options — see [Video export](video-export.md) |
| `pipeline` | optional | CI gates, sync, and orchestration — see below |
| `avatar_calibration` | optional | PiP framing — see below |
| `slide_timestamps` | optional | Wall-clock start (seconds) per slide for video timing |

Keys starting with `x-` are ignored (YAML anchors). Unknown keys log a warning; invalid enum values (e.g. `narration_mode`, `color_scheme`, `layouts.pip.shape`) raise `SchemaError` at load time via `validate_verses()` / `load_verses_from_file()`.

---

## Section object

| Key | Description |
|-----|-------------|
| `section` | Section title (creates a section slide when non-empty) |
| `section_subtitle` | Optional subtitle on section slide |
| `verses` | List of verse/slide objects |

---

## Verse keys (shared)

| Key | Type | Description |
|-----|------|-------------|
| `slide_type` | string | Renderer choice (`table`, `avatar_headline`, `deck_agenda`, …) |
| `reference` | string | Footline, caption, or subtitle depending on layout |
| `text` | string | Body, list items (`\n`-separated), or headline |
| `notes` | string | Presenter notes (also used for captions / TTS) |
| `highlights` | list | Rich text highlights — [Formatting](formatting.md) |
| `font_size` | int | Body pt size (overrides `typography.body_size_pt`) |
| `alignment` | string | `left`, `center`, `right` |
| `avatar_video_path` | string | HeyGen MP4 or other avatar file |
| `avatar_poster_path` | string | Still frame for PiP |
| `media_path` | string | Image or video for media regions |
| `media_fit` | string | `contain`, `cover`, `fill` |
| `duration_sec` | float | Video slide duration override |
| `audio_start_sec` | float | Offset into shared audio/avatar file |
| `audio_path` | string | External narration MP3 |
| `narration_mode` | string | `fixed`, `audio_file`, `avatar`, `tts`, `auto` |
| `audio_source` | string | Optional alias: `heygen_video`, `external`, `tts` (used when `narration_mode` omitted) |
| `sync_mode` | string | `avatar_lead`, `notes_lead`, `longest` |
| `color_scheme` | string | Deck colour preset name (`deck_*` slides) |

Additional keys depend on `slide_type` — see the layout pages above.

---

## `video_export` block

```yaml
video_export:
  backend: compositor
  narration_mode: fixed          # fixed | audio_file | avatar | tts | auto
  output_path: output/deck.mp4
  preset: standard               # draft | standard | high | 4k
  resolution: { width: 1920, height: 1080 }
  fps: 30
  dpi: 192
  slide_duration_sec: 5
  avatar_timeline: auto          # per_slide | continuous | auto
  avatar:
    fit: cover
    shape: circle
    crop_y_ratio: 0.06
    zoom_ratio: 1.45
    loop_if_shorter: true
  tts:
    provider: edge
    voice: en-GB-RyanNeural
  captions:
    enabled: true
  slide_cache: true
```

CLI overrides: `--video-output`, `--video-preset`, `--narration-mode`, `--video-options` (JSON), `--slide-range`, `--keep-temp`. See [Video export](video-export.md).

---

## Minimal deck skeleton

```yaml
presentation_title: My presentation
presentation_subtitle: June 2026

slide_style:
  background_color: "#1A1A2E"
  text_color: white

sections:
  - section: Introduction
    verses:
      - reference: Opening
        text: First point.

  - section: Main
    verses:
      - slide_type: table
        table_rows:
          - [A, B]
          - [1, 2]
        reference: Source line
        avatar_video_path: assets/speaker.mp4

video_export:
  backend: compositor
  preset: standard
  narration_mode: avatar
  avatar_timeline: auto
```

---

## `pipeline` (QA orchestration)

Optional in **YAML or JSON** (same keys). Drives `praisonaippt pipeline` and `validate-deck` (validate-only: no PPTX/MP4). Build and export are separate stages wired via protocols (`pipeline_protocols.py`); defaults call `create_presentation` and `convert_deck_to_video`.

| Key | Type | Description |
|-----|------|-------------|
| `content_master` | string | Master YAML for `sync-variants` / drift checks |
| `transcript_path` | string | Whisper JSON for timing / A-V sync gates |
| `auto_sync` | bool | Sync variants from master before build |
| `variant_prefix` | string | Filename prefix for variant YAMLs (default `heygen-50590`) |
| `validate_pip` | bool | Run PiP centring QA (multi-seek) |
| `strict_pip` | bool | All calibration seeks must pass |
| `golden_slide_dir` | string | Golden JPEG directory for slide hash gate |
| `require_rights_ack` | bool | Block until `rights_acknowledged` |
| `rights_acknowledged` | bool | Manual rights checklist clearance |
| `content_approved` | bool | Content sign-off |
| `plan_approved` / `plan_draft` | bool / string | Plan-slides workflow |
| `export_mp4` | bool | Export MP4 in `pipeline` command (or use CLI `--convert-video`) |
| `export_slide_jpegs` | bool | Export slide JPEGs after PPTX |
| `post_render_qc` | bool | ffprobe post-render checks (default true) |
| `strict_post_render` | bool | Fail pipeline when post-render QC fails |
| `fail_fast` | bool | Stop on first failed gate (default true) |
| `validate_plan` / `validate_rights` | bool | Toggle plan / rights gates |
| `seed_timing` | bool | Seed `audio_start_sec` from transcript |
| `report_path` | string | Override `report.json` path |

CLI flags override YAML where both are set. Full gate matrix: [Video → deck workflow](workflow-video-transcript-to-deck.md).

---

## `avatar_calibration` (PiP framing)

Optional top-level block. When `auto: true`, runs before PPTX/video build and merges `crop_x_ratio` / `crop_y_ratio` into `slide_style.layouts.pip`.

| Key | Type | Description |
|-----|------|-------------|
| `auto` | bool | Run calibration when building (default false if block omitted) |
| `method` | string | `hybrid`, `balance`, `mediapipe`, `fixed`, `yolo` |
| `crop_x_preferred` | float | Visual anchor (e.g. `0.53`) |
| `crop_x_window` | `[lo, hi]` | Allowed `crop_x` range |
| `crop_y_preferred` | float | Default vertical crop |
| `anchor_weight` | float | Penalty for drifting from `crop_x_preferred` |
| `detector` | string | `auto`, `mediapipe`, `yunet`, `yolo` |
| `min_detection_confidence` | float | Face detector threshold |
| `force` | bool | Ignore cache |

Cache directory: `.praisonaippt/avatar-framing/` beside the deck (gitignored). See [Avatar PiP calibration](avatar-calibration.md).

---

## HeyGen 50590 workflow

1. Edit `examples/heygen-50590-content.yaml`
2. `python examples/sync_heygen_variants.py`
3. `praisonaippt -i examples/<variant>.yaml -o examples/<variant>.pptx --convert-video`

Details: [HeyGen article examples](heygen-examples.md).

---

## Related

- [Layouts overview](layouts-overview.md)
- [Configuration file](configuration.md) — `~/.praisonaippt/config.yaml` (Drive, PDF defaults)
