# The Bridge

Turn a Claude documentary outline (or any markdown with timecodes, or any SRT)
into a DaVinci Resolve timeline you can edit immediately. No more hunting for
timecodes.

## What you get

A `.fcpxml` file you drag into Resolve via **File → Import → Timeline**.
Inside the timeline:

- One named placeholder clip per beat. The clip name reads
  `BEAT NAME — first line of description` (truncated to ~90 chars) so the
  full storytelling cue is visible in the timeline's clip name column.
- A storytelling-role marker at the start of each beat, named
  `[HERO]` / `[VILLAIN]` / `[CRESCENDO]` / `[VALLEY]` / `[EXPOSITION]` /
  `[RELEASE]` / `[BEAT]`. The markers row above the timeline ruler in
  Resolve's Edit page shows these at a glance.
- Beats are sequential and contiguous — Resolve places them on V1 as named
  empty regions you fill in.

Your job: open Resolve, look at the labelled placeholders, drop the right
shots underneath each one.

## Setup (one minute)

```bash
# nothing to install. Python 3.9+ standard library only.
python3 --version    # must be 3.9 or newer
```

That's it. No pip, no venv, no API key, no internet.

## Use it

```bash
# Markdown outline (heading-with-timecode form)
python3 bridge.py outline.md --fps 24

# Markdown outline (bracketed form)
python3 bridge.py outline.md --fps 25

# SRT subtitle file
python3 bridge.py transcript.srt --fps 23.976

# Custom output path + project name
python3 bridge.py outline.md --fps 24 --project "Architect Doc v2" --out architect.fcpxml

# Just preview parsed beats without writing anything
python3 bridge.py outline.md --list
```

Then in DaVinci Resolve:

1. Open or create a project
2. **File → Import → Timeline**
3. Pick the `.fcpxml` file
4. Resolve creates a new timeline with all your beats already placed

## Input formats

The Bridge accepts any of these. Pick whichever matches the way Claude
gives you the outline.

### Format A — markdown headings with timecodes (recommended)

```markdown
## 00:00:00 — Exposition opening
Wide drone shot over the construction site at dawn.

## 00:00:18 — Hero introduction
Cut to the architect walking through the foundations.

## 00:00:42 — Villain pressure
Smash to the developer's glass tower.
```

The Bridge picks up any heading level (`#`, `##`, `###`...) that starts with
a timecode. Everything until the next heading becomes the clip's note.

### Format B — bracketed timecodes

```markdown
[00:00:00] EXPOSITION — Wide drone over construction site
[00:00:18] HERO — Architect walks through foundations
[00:00:42] VILLAIN — Developer's glass tower, money
```

Use ` — `, ` - `, or `: ` to separate the label from the description.

### Format C — standard SRT

```
1
00:00:00,000 --> 00:00:18,000
EXPOSITION
Wide drone over construction site

2
00:00:18,000 --> 00:00:42,000
HERO
Architect walks through foundations
```

The first non-empty line after the timecode becomes the clip label. The rest
becomes the note body. Durations come from the cue end-times.

## Beat classification (marker colours)

The Bridge scans each beat's **label** for storytelling keywords and assigns
a marker tag:

| Keyword (in the label)        | Marker tag       |
|-------------------------------|------------------|
| `hero`                        | `[HERO]`         |
| `villain`                     | `[VILLAIN]`      |
| `crescendo`, `climax`         | `[CRESCENDO]`    |
| `exposition`, `opening`       | `[EXPOSITION]`   |
| `valley`, `release`, `ending` | `[VALLEY]`       |
| anything else                 | `[BEAT]`         |

In Resolve you can quickly recolour markers by selecting them and using
the marker colour menu — but the tag names in the marker text make the
storytelling role obvious at a glance regardless of colour.

## Frame rates supported

`--fps 23.976`, `24`, `25`, `29.97`, `30`, `50`, `59.94`, `60`.

Match this to your Resolve project's timeline FPS. Mismatched FPS will still
import but Resolve will conform the timing.

## Resolution

Default 1920x1080. Override with `--width` and `--height` if you're working
in 4K or vertical:

```bash
python3 bridge.py outline.md --width 3840 --height 2160 --fps 24
python3 bridge.py outline.md --width 1080 --height 1920 --fps 30   # vertical
```

## Worked example

There are three sample inputs in `examples/` — all three produce the same
6-beat timeline:

```bash
python3 bridge.py examples/sample-outline.md --fps 24
python3 bridge.py examples/sample-bracketed.md --fps 25
python3 bridge.py examples/sample-claude.srt --fps 23.976
```

Open any of the generated `.fcpxml` files in DaVinci to see what it looks
like before you run it on a real outline.

## Tips for Claude

If you're using Claude.ai, set this up once as a **Project** (paid Claude.ai
feature — Projects live in the left sidebar, give them custom instructions
and persistent files). Paste this into the project's custom instructions:

> You are helping me structure a documentary using BBC-Earth-style narrative
> beats — hero, villain, crescendo, valley, exposition, release. When I give
> you raw material, output the timeline as markdown headings in this exact
> shape:
>
>     ## HH:MM:SS — [BEAT NAME]
>     1–3 sentences of shot description.
>
> Beat names must be one of: EXPOSITION, HERO, VILLAIN, VALLEY, CRESCENDO,
> RELEASE. No other formatting. The Bridge CLI converts this directly into
> a DaVinci Resolve timeline.

Now every conversation in that Project gives you Bridge-ready output. Paste
into a `.md` file, run `bridge.py`, drag into Resolve.

## Troubleshooting

**"No beats parsed"** — Your file doesn't match any of the three formats.
Run `--list` to see what was parsed. If the list is empty, check that
your timecodes are `HH:MM:SS` (not `MM:SS`).

**Markers don't show in Resolve** — In Resolve, open the Edit page,
check that the Markers row is visible above the timeline ruler
(View → Show Markers Row).

**Frame rate mismatch warning** — Set your Resolve project FPS to match
the `--fps` you passed. Project Settings → Master Settings → Timeline
frame rate.

**XML is well-formed but import fails** — Try downgrading the duration
math by using whole-second beat starts in your outline (timecodes ending
in `.000`).
