The producer’s real file format is a spreadsheet
Somewhere between “we have a script” and “we have a schedule” is a layer of work nobody outside production appreciates: somebody has to read the script, highlight every prop, every piece of wardrobe, every animal, every special effect, every cast member, every scene location, every time of day, and reconcile all of it across 110 pages.
That work happens in a spreadsheet. Or a scheduling app. Or, for worse, a printed stack of pages with a colour-coded highlighter system.
ScreenJSON makes that layer first-class data. The schema has a scene-level
taxonomy with dedicated arrays for animals, extra,
locations, moods, props,
sfx, sounds, tags, vfx,
and wardrobe — every breakdown category an experienced line
producer recognises. Once a script is in ScreenJSON, populating those
fields is a pass, not an archaeological dig.
What you get, concretely
A machine-readable cast list. Every character has a stable UUID and a
canonical name. Every scene has a cast array listing the
characters present. Day-out-of-days reports, cast availability projections,
and pay-day estimations become SELECT statements, not hand-counted
tallies.
Scene breakdowns as structured tags. When a scene contains a prop, it
goes in props. When a scene has a VFX plate, it goes in
vfx. These are slugs — short, URL-safe identifiers — which
means “revolver” in scene 3 is the same
“revolver” in scene 47. You can answer “how many scenes need
the revolver?” without reading the script.
Locations as a queryable set. The heading of every scene
carries a structured setting and context
(INT/EXT/POV), and the scene itself carries a locations tag
array for any additional location references inside the scene body. Your
location manager gets a clean list, grouped, counted, and linkable back to
the exact scenes that need each location.
Times of day that are enumerable. time is either one of
the industry standard enums — DAY, NIGHT,
DUSK, DAWN, LATER,
MOMENTS LATER, CONTINUOUS, MORNING,
AFTERNOON, EVENING, THE NEXT DAY —
or a conforming custom label. No more “is ‘dusk’ the same as ‘sundown’?”
A worked example
Say your writer sends you the script as draft-3.fdx. You run:
screenjson convert -i draft-3.fdx -o draft-3.json
You now have a structured document. Every scene has an id, a heading
with a parsed slugline, a body of typed elements, and empty tag arrays
waiting to be filled by a breakdown pass.
Your breakdown coordinator opens the file in their breakdown tool — which can now round-trip to ScreenJSON — and marks up:
{
"id": "7a1c0b4e-…",
"heading": { "context": "INT.", "setting": "GALLEY", "time": "NIGHT" },
"cast": ["8d2f-mara", "3b1a-ellis"],
"props": ["coffee-urn", "pistol", "jammed-radio"],
"wardrobe": ["uniform-naval-officer"],
"sfx": ["muzzle-flash"],
"sounds": ["radio-static", "distant-alarm"],
"meta": { "estimated-minutes": "2.5" }
}
…and now your schedule, your budget, your call sheets, your shot list, and your insurance submission can all read from the same file. No re-typing.
Scaling beyond one script
A single-film producer cares about one screenplay. A slate producer, a studio executive, or a streaming-platform commissioning team cares about hundreds — sometimes thousands — at the same time.
That’s where Greenlight comes in. It wraps the same CLI in a job queue with S3 ingestion and an admin UI. Point it at a bucket of incoming submissions; let it convert, validate, and index them overnight. The next morning, your development team has a searchable, queryable set of scripts, not a folder of PDFs.
Production reports you can actually run
Because every field is typed, every question you used to need a junior co-producer to answer in a spreadsheet becomes a one-liner:
# How many scenes are night exteriors?
jq '[.document.scenes[]
| select(.heading.context == "EXT" and .heading.time == "NIGHT")]
| length' screenplay.json
# How many speaking parts does MARA have?
jq --arg id "8d2f-mara" '[.document.scenes[].body[]
| select(.type == "dialogue" and .character == $id)] | length' screenplay.json
# Every location mentioned, with scene counts
jq '[.document.scenes[].heading.setting] | group_by(.)
| map({ location: .[0], scenes: length })' screenplay.json
These aren’t novelty demos. They are the actual reports that used to take somebody half a day.
On vendor lock-in
Everything a producer touches is licensable intellectual property. The last thing any production team needs is a format or a tool that holds the document hostage.
ScreenJSON’s schema is open. The reference CLI is MIT-licensed. Whenever
you want out, screenjson export gives you FDX, Fountain,
FadeIn, or PDF back. That’s not a promise — it’s baked into the tool’s
command list.
On encryption in active productions
Pre-release scripts leak. AES-256 encryption of text only — leaving structure, UUIDs, and metadata visible — means you can send an encrypted script to a scheduling tool, have the schedule produced, and never let the scheduling tool see a word of dialogue. That’s a posture most producers didn’t know they could ask for.