Metadata-Version: 2.4
Name: presenter-json
Version: 0.1.0
Summary: Pydantic models and JSON helpers for presentation timing format, shared across projects
License: MIT
Keywords: propresenter,presentation,json,pydantic,timing
Author: scaperoth
Author-email: scaperoth@berkeley.edu
Requires-Python: >=3.11,<4.0
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Multimedia :: Sound/Audio
Requires-Dist: pydantic (>=2.0,<3.0)
Project-URL: Homepage, https://github.com/scaperothian/presenter-json
Project-URL: Issues, https://github.com/scaperothian/presenter-json/issues
Project-URL: Repository, https://github.com/scaperothian/presenter-json
Description-Content-Type: text/markdown

# presenter-json

Pydantic models and JSON helpers for  **presentation
timing format** — a shared library for the various projects that read and
generate these JSON files (training data, playback, benchmarking, …).

The JSON shape resembles the ProPresenter `/v1/presentation/{uuid}` API response,
with extra metadata on `presentation.id` (audio source, timing method, file
version) and per-slide timing lists (`trigger time`, `start time`, `stop time`).
Any ProPresenter field not explicitly modelled passes through untouched.

## Install

```bash
pip install presenter-json
```

Or with Poetry, as a path/develop dependency from a sibling project:

```toml
[tool.poetry.dependencies]
presenter-json = { path = "../presenter-json", develop = true }
```

## Reading a file

```python
from presenter_json import load_presentation, cues, slide_texts

pres = load_presentation("sermon.json")

print(pres.presentation.id.name)
print(slide_texts(pres))            # text of every slide, flattened

for cue in cues(pres):              # sorted playback cues
    print(f"{cue.time:7.3f}  [{cue.group_name}]  {cue.text}")
```

## Generating a file

```python
from presenter_json import (
    new_presentation, add_group, add_slide,
    set_trigger_times, set_metadata, save_presentation,
)

pres = new_presentation(name="My Song", audio_path="audio/my-song.wav")
set_metadata(pres, method="model", method_description="forced alignment", version="1.0")

verse = add_group(pres, "Verse 1")
s1 = add_slide(verse, "First line of the verse")
set_trigger_times(s1, [0.0])
add_slide(verse, "Second line")          # untriggered — no timing written

save_presentation(pres, "my-song.json")
```

## API overview

**IO** (`presenter_json.io`)
- `load_presentation(path)` / `loads_presentation(text)` → `PresentationFile`
- `save_presentation(model, path)` / `dumps_presentation(model)`
- `load_raw(path)` → unvalidated `dict`

**Reading** (`presenter_json.helpers`)
- `iter_groups`, `iter_slides`, `group_name`, `slide_text`, `slide_texts`, `slide_field`
- `get_trigger_times` / `get_start_times` / `get_stop_times` / `get_timing`
- `detect_timing_key`, `cues` (sorted `Cue` list)

**Generating / mutating**
- `new_presentation`, `add_group`, `add_slide`
- `set_trigger_times` / `set_start_times` / `set_stop_times` / `set_timing`, `clear_timing`
- `set_metadata`, `from_api_response`

**Models** (`presenter_json.models`)
- `PresentationFile`, `Presentation`, `PresentationId`, `Group`, `Slide`
- Constants: `METHOD_MANUAL`, `METHOD_CAPTIONS`, `METHOD_MODEL`, `TRIGGER_TIME_KEY`, …

## Development

```bash
poetry install
poetry run pytest
```

Tests run in GitHub Actions across Python 3.11–3.13 (`.github/workflows/ci.yml`).
Tagging a release (`vX.Y.Z`) publishes to PyPI via Trusted Publishing
(`.github/workflows/publish.yml`).

All changes go through a branch off `main` and land via pull request.

