Metadata-Version: 2.4
Name: auditorium
Version: 1!3.3.0
Summary: Python-scripted live slide framework
Author-email: Alejandro Piad <apiad@apiad.net>
License: MIT
Requires-Python: >=3.12
Requires-Dist: fastapi>=0.110
Requires-Dist: markdown>=3.6
Requires-Dist: rich>=15.0.0
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn[standard]>=0.29
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: record
Requires-Dist: playwright>=1.40; extra == 'record'
Requires-Dist: tqdm>=4.67.3; extra == 'record'
Description-Content-Type: text/markdown

# 🎓 Auditorium

[<img alt="PyPI - License" src="https://img.shields.io/pypi/l/auditorium.svg">](https://github.com/apiad/auditorium/blob/master/LICENSE)
[<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/auditorium.svg">](https://pypi.org/project/auditorium/)
[<img alt="PyPI" src="https://img.shields.io/pypi/v/auditorium.svg">](https://pypi.org/project/auditorium/)

**The presentation framework for people who think in code.**

Auditorium lets you build live technical presentations as Python scripts. Each slide is an `async def` function. Animate algorithms step by step, render live-computed plots, run numerical demos — anything Python can do, your slides can do. No PowerPoint. No Markdown. Just code.

```python
from auditorium import Deck

deck = Deck(title="My Talk")

@deck.slide
async def sorting_demo(ctx):
    """Explain how the algorithm builds the sorted prefix."""
    await ctx.md("## Bubble Sort, Step by Step")
    data = [5, 3, 8, 1, 2]
    for i in range(len(data)):
        for j in range(len(data) - 1 - i):
            if data[j] > data[j + 1]:
                data[j], data[j + 1] = data[j + 1], data[j]
            await ctx.md(f"`{data}`")
            await ctx.sleep(0.5)
    await ctx.step()
    await ctx.md("**Sorted!**")
```

```bash
pip install auditorium
auditorium run talk.py
```

---

## ✨ Why Auditorium?

Most presentation tools treat slides as static documents. Auditorium treats them as **programs**.

- 🐍 **Run algorithms live** — sort arrays, traverse graphs, train models, all animated on stage
- 📊 **Compute content** — generate plots, tables, or LaTeX from data, not screenshots
- 📦 **Use any Python library** — numpy, matplotlib, pandas, whatever you import works
- 🌍 **Share with students worldwide** — presenter mode syncs your slides to every connected browser in real time
- 🔗 **Go public** — `--public` gives you an instant shareable URL, no deployment needed
- 📤 **Export everywhere** — record to video, export to PDF, or share as a self-contained HTML that replays your talk with original timing

If you've ever wished you could `await` inside a PowerPoint slide, this is for you.

---

## 🚀 Quick Start

```bash
pip install auditorium    # or: uv add auditorium
```

Create `talk.py`:

```python
from auditorium import Deck

deck = Deck(title="My Talk")

@deck.slide
async def intro(ctx):
    """Notes for the presenter — only visible in presenter view."""
    await ctx.md("# Welcome!")
    await ctx.md("*Press right arrow to continue*")

@deck.slide
async def demo(ctx):
    """Show progressive reveals and timed content."""
    await ctx.md("## Key Points")
    await ctx.step()
    await ctx.md("- First point")
    await ctx.step()
    await ctx.md("- Second point")
    await ctx.sleep(1)
    await ctx.md("*(that one appeared automatically)*")
```

Run it:

```bash
auditorium run talk.py
```

---

## 📋 Features

| | Feature | Description |
|---|---------|-------------|
| 🐍 | **Imperative Python slides** | Each slide is an `async def` — loops, conditionals, imports, anything |
| 👁️ | **Progressive reveals** | `await ctx.step()` pauses for keypress, `await ctx.sleep(n)` auto-advances |
| 🧮 | **LaTeX math** | KaTeX bundled — `$inline$` and `$$display$$` in any markdown |
| 💻 | **Syntax highlighting** | Fenced code blocks with highlight.js (bundled) |
| 📐 | **Flexible layouts** | `columns`, `rows` with `"auto"` sizing, arbitrarily nested |
| 🎤 | **Presenter mode** | `--presenter` — notes, timer, slide mirror, next-slide preview |
| 🔄 | **Shared navigation** | Presenter drives all audience tabs — students see what you show |
| 🌍 | **Public sharing** | `--public` bridges to a relay — instant shareable URL, no deployment |
| 🕐 | **Late-join sync** | New viewers see the full slide state immediately |
| 📄 | **PDF / HTML / PNG export** | Vector PDF, self-contained interactive HTML, or PNG per slide |
| 🎬 | **Video recording** | Headless or live recording via Playwright |
| 🔀 | **Step-by-step export** | Each reveal as a separate frame with original timing |
| ♻️ | **Hot reload** | Edit your `.py` and the browser updates instantly |
| 📡 | **Offline** | All assets bundled — zero CDN, zero internet required |
| 🔌 | **Auto-reconnect** | Survives server restarts without losing your place |

---

## 🌍 Share Publicly

Present from your laptop, share with the world:

```bash
auditorium run talk.py --public
```

```
╭───────────────────────── Auditorium ─────────────────────────╮
│ Deck:   My Talk                                               │
│ Slides: 15                                                    │
│ URL:    http://127.0.0.1:8000                                 │
│ Mode:   independent (per-tab)                                 │
╰──────────────────────────────────────────────────────────────╯

Public URL: http://vps.apiad.net:4243/r/my-talk/
```

Anyone with the link sees your presentation in real time. No deployment, no hosting — your laptop runs the deck, a lightweight relay forwards it.

```bash
# Choose your own URL slug
auditorium run talk.py --public --name my-talk

# Use your own relay server
auditorium run talk.py --public --relay myserver.com:4243
```

**Self-host a relay** (it's one command):

```bash
auditorium relay                    # run directly
make relay-install                  # install as systemd service
make relay-update                   # pull + sync + restart
```

---

## 🎤 Presenter Mode

Start with `--presenter` to sync all audience tabs to your navigation:

```bash
auditorium run talk.py --presenter
```

Two tabs open: your **presenter view** (notes + timer + slide mirror + next-slide preview) and the **audience view**. Navigate from the presenter tab — every connected browser follows in real time.

- 📝 Docstrings become **speaker notes** (never shown to the audience)
- ⚡ Late-joining tabs catch up instantly (full slide state replayed)
- 🔒 Audience keyboards are locked — only the presenter navigates

Without `--presenter`, each tab navigates independently.

---

## 📐 Layouts

```python
@deck.slide
async def layout_demo(ctx):
    """Layouts nest freely."""
    await ctx.md("## Two Columns")
    left, right = await ctx.columns([2, 1])

    async with left:
        await ctx.md("Main content (2/3 width)")

    async with right:
        await ctx.md("Sidebar (1/3)")
```

Use `"auto"` for natural-size regions:

```python
header, body, footer = await ctx.rows(["auto", 1, "auto"])
```

---

## 🎬 Recording & Export

Requires `pip install auditorium[record]` and `playwright install chromium`.

```bash
# Record to video
auditorium record talk.py -o talk.webm

# Export to PDF (vector), HTML (interactive), or PNG
auditorium export talk.py -f pdf -o talk.pdf
auditorium export talk.py -f html -o talk.html
auditorium export talk.py -f png -o slides/

# Step-by-step: one frame per reveal, with original timing in HTML
auditorium export talk.py -f html --step-by-step -o talk.html
```

---

## ⌨️ Navigation

| Key | Action |
|-----|--------|
| → / Space | Advance step or next slide |
| Page Down | Skip to next slide |
| ← | Previous slide |
| `r` | Restart current slide |
| Digits + Enter | Jump to slide N |

---

## 📚 Example

See [`examples/demo_deck.py`](examples/demo_deck.py) for a full 11-slide deck exercising every feature.

```bash
auditorium run examples/demo_deck.py
```

---

## 📜 License

MIT
