Skip to content

kevinmcaleer/scriptmd2pdf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

scriptmd2pdf

Convert a screenplay‑flavoured Markdown file into a properly formatted PDF (monospaced US Letter layout) using a lightweight Python script (no LaTeX / no external formatter required).

Features

  • Scene headings (### INT. LOCATION - TIME)
  • Action paragraphs (plain text)
  • Character cues (@CHARACTER)
  • Parentheticals inside dialogue lines ((whispering))
  • Dialogue (lines following a character cue until a blank line)
  • Transitions (>> CUT TO:) – right aligned
  • Shot headings (! CLOSE ON)
  • Forced page breaks (---) – always start a new page
  • Bold scene headings (auto bold font variant; simulated if bold face missing)
  • Block comments starting with // are ignored
  • Block quotes / notes starting with single > are ignored (except >> transitions)
  • Adjustable font, size, and transition right margin
  • Optional shot list export (--shot-list markdown|csv) capturing scenes & shot headings with a first action summary snippet
  • Shot list PDF export (--shot-list-pdf) including optional landscape layout
  • Entity inventory (characters, locations, objects) appended to shot list outputs (--entities)
  • Landscape shot list PDF option for wider columns (--shot-list-landscape)
  • Razor‑sharp vector screenplay PDF rendering (--vector via ReportLab) instead of raster images
  • Final Cut Pro timeline export (FCPXML) with scene markers & shot keyword ranges (--fcpxml)

Installation

Requires Python 3.8+ and Pillow.

python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install Pillow

(If Pillow is already installed you can skip.)

Command Line Usage

python screenmd2pdf.py INPUT.md OUTPUT.pdf [options]

Options

Option Default Description
--title "My Title" (Derived from input filename) Title printed centered on each page.
--font /path/to/mono.ttf Auto-detected / built-in default Use a specific TTF monospace font (e.g., DejaVuSansMono.ttf, Courier).
--size 12 12 Font size (points).
--break-style page page (Currently page breaks for --- are always forced; this remains for forward compatibility.)
--transition-right 1.0 1.0 Right margin in inches for right‑aligned transitions. Smaller values pull transitions further left.
--shot-list markdown (none) Write a shot list beside the PDF. Pass markdown (table) or csv. Filename auto-derived next to output PDF.
--shot-list-pdf shots.pdf (none) Generate a shot list as a PDF (table layout).
--shot-list-landscape off Use landscape orientation for shot list PDF (more horizontal room, less wrapping).
--entities off Include entity inventory (characters, locations, objects) in shot list (text/CSV/PDF).
--vector off Use vector text PDF rendering (requires reportlab) for crisp non-blurry output.
--fcpxml script.fcpxml (none) Export a minimal Final Cut Pro XML with scene markers & shot keyword ranges.
--wpm 160 160 Words per minute reading rate to estimate timing for FCPXML.
--fps 25 25 Frame rate used for FCPXML timecode (24/25/30 etc).

Example

python screenmd2pdf.py example_screenplay.md script.pdf

Shot List Export

Generate a structured list of all scene headings and shot headings (lines starting with !) in script order. Each row includes:

  • Type: SCENE or SHOT
  • Heading: The raw heading text (e.g. INT. KITCHEN - DAY, CLOSE ON)
  • Summary: First non-empty action line following that heading (trimmed to ~120 chars)

Markdown / CSV / PDF Variants

python screenmd2pdf.py example_screenplay.md script.pdf --shot-list markdown
# or CSV
python screenmd2pdf.py example_screenplay.md script.pdf --shot-list shots.csv
# or PDF (table rendered with wrapping)
python screenmd2pdf.py example_screenplay.md script.pdf --shot-list-pdf shots.pdf

Produces (example):

| Type  | Heading               | Summary                           |
| ----- | --------------------- | --------------------------------- |
| SCENE | INT. KITCHEN - DAY    | The sun burns through the mist... |
| SHOT  | CLOSE ON              | A detail description.             |

Landscape PDF & Entities

Add --shot-list-landscape to widen columns (less wrapping) and --entities to append an inventory section:

python screenmd2pdf.py example_screenplay.md script.pdf --shot-list-pdf shots.pdf --shot-list-landscape --entities

Entity inventory groups: Characters, Locations (slugline location portion), and Objects/Props (heuristic uppercase tokens from action/shot text minus stop words).

Filenames:

  • Markdown: <output>_shots.md
  • CSV: <output>_shots.csv
  • PDF: custom path you supply (e.g. shots.pdf)

If no descriptive action follows a heading, the summary cell is left blank.

Including Entities in Markdown / CSV

Pass --entities with --shot-list to append an "Entity Inventory" section (Markdown) or extra rows (CSV) after the table.

Final Cut Pro (FCPXML) Export

Generate a lightweight FCPXML you can import into Final Cut Pro to bootstrap your edit with chapter markers for scenes and searchable keyword ranges for shots.

python screenmd2pdf.py example_screenplay.md script.pdf --fcpxml script.fcpxml

What you get:

  • Each scene heading becomes a marker at its estimated start time (uses cumulative estimated durations of preceding blocks).
  • Each shot heading (! ...) becomes a keyword range labeled SHOT:HEADING spanning its estimated duration.
  • Durations are heuristically estimated from word counts at a configurable words-per-minute rate (--wpm, default 160). Minimum 1s per text block.
  • Timecode is expressed at the chosen frame rate (--fps, default 25) for compatibility with your project settings.

Usage with custom pacing & frame rate:

python screenmd2pdf.py example_screenplay.md script.pdf --fcpxml script.fcpxml --wpm 180 --fps 24

Importing:

  1. In Final Cut Pro choose File > Import > XML… and select the generated .fcpxml.
  2. A new Event containing a Project named after the script title appears; markers & keyword ranges are visible in the timeline / index.

Notes / Limitations:

  • The export represents the entire script as a single gap clip with markers/keywords (no media). Replace sections with actual footage as you assemble.
  • Timing is approximate; adjust by moving markers once you have real durations.
  • Only scene and shot headings are exported; dialogue/action aren’t broken into ranges (could be extended in future).

Markdown Syntax Reference

### INT. KITCHEN - DAY        # Scene heading

Plain action text forms action paragraphs.

@ALEX                         # Character cue (leading '@' is stripped)
(whispering)                  # Optional parenthetical
We can't keep pretending...

@JORDAN
We stopped being normal...

>> CUT TO:                    # Transition (auto uppercased + colon if missing)

! CLOSE ON                    # Shot heading
A detail description.

---                           # Forced page break

Notes

  • Blank line separates blocks (scene, action, dialogue groups, etc.).
  • Dialogue ends at the first blank line after a character cue (excluding parentheticals).
  • Multiple consecutive parentheticals are allowed.
  • Lines starting with // are removed before parsing.
  • Lines starting with > (single) are treated as notes and removed; >> is reserved for transitions.

Output Formatting (Approx.)

  • Paper: US Letter 8.5" × 11".
  • Margins / indents (approx):
    • Scene & Action: Left 1.5", Right 1".
    • Character: Left 3.5".
    • Dialogue: Left 2.5", Right 2.5".
    • Parenthetical: Left 3.0".
    • Transition: Right aligned (right margin adjustable with --transition-right).
  • Monospaced layout using chosen / detected font.
  • Scene headings rendered in bold (if a bold TTF variant of the chosen font is found; otherwise a simulated bold via overdraw).

Bold Scene Headings

The script tries to locate a bold variant of the supplied (or auto-detected) font using common filename patterns (e.g. replacing Regular with Bold). If it cannot find one, it simulates bold by drawing the heading text twice with a very slight horizontal offset. This keeps dependencies minimal while giving headings visual weight.

Page Breaks

--- always forces a new page regardless of --break-style. The option is retained for future flexibility (line / space rendering modes could be re-enabled later).

Vector Rendering (Crisp Text)

By default pages are rasterized images (simple, but fonts can look slightly soft depending on viewer scaling). Use --vector to enable a pure text PDF (via ReportLab) for razor‑sharp rendering and selectable/copyable text:

pip install reportlab
python screenmd2pdf.py example_screenplay.md script.pdf --vector

Notes:

  • Bold scene headings use a detected bold TTF variant if available, else regular weight.
  • Vector mode currently ignores --break-style (page breaks always forced) just like raster mode.
  • Raster mode remains the default to avoid extra dependency.

Example Minimal Script

### INT. KITCHEN - DAY

@ALEX
(quietly)
Morning.

@JORDAN
Morning.

>> CUT TO:

### EXT. GARDEN - LATER

The sun burns through the mist.

---

### INT. OFFICE - DAY

@ALEX
We made it.

Run:

python screenmd2pdf.py sample.md sample.pdf

Troubleshooting

Issue Cause Fix
PDF shows @ before names Cached old PDF / not re-run Re-run command; ensure you saved the Markdown.
Transition missing Line started with single > not >> Use >> CUT TO:.
Font looks different System font not found Supply explicit --font pointing to a monospace TTF.
Page break not happening Used ---- (4 dashes) or spaces Use exactly --- on its own line.

Extending

Ideas you can add:

  • Scene numbering
  • Title page (detect first heading / metadata block)
  • Automatic continued markers (CONT'D)
  • Fountain format import
  • Revision colors / A-pages

License

MIT (add a LICENSE file if distributing).

Quick One-Liner

python screenmd2pdf.py my_script.md my_script.pdf --font /Library/Fonts/Courier\ New.ttf --size 12 --transition-right 1.0

Enjoy writing!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors