FilmGraph
A structured data format for film analysis.
Install · Quick Start · Schema · Importers · Exporters · Docs
Why FilmGraph?
The film industry relies on dozens of incompatible formats — CCSLs in Word documents, Dialogbücher, SRT subtitles, EDLs, XML timelines, proprietary pipeline outputs. Building tools that work across these formats means spending more time parsing than analyzing.
FilmGraph is a single JSON schema that captures shots, scenes, dialogue, cinematography, characters, locations, and narrative events. Zero dependencies beyond Pydantic. One format for your entire pipeline.
{
"schema_version": "filmgraph/v1",
"meta": { "title": "Lost Killers", "duration": 5731.2 },
"scenes": [{
"id": 1, "title": "Opening", "start_time": 0, "end_time": 142.5,
"shots": [{
"id": "sh-001", "order": 1, "start_time": 0, "end_time": 8.3,
"cinematography": { "shot_size": "WS", "camera_movement": "static" },
"visual": { "description": "Wide establishing shot of Berlin skyline at dusk" },
"audio": { "dialogue": [{ "speaker": "narrator", "text": "Berlin, 1998.", "start_time": 2.1, "end_time": 4.5 }] }
}]
}]
}
Install
pip install filmgraph
With importers for .docx files (CCSL, Dialogbuch, AD scripts):
pip install filmgraph[docx]
With OpenTimelineIO support (EDL, FCP XML, AAF):
pip install filmgraph[otio]
Quick Start
from pathlib import Path
from filmgraph import FilmGraph, Scene, Shot, ShotSize, CameraMovement
# Load
fg = FilmGraph.from_json(Path("movie.filmgraph.json").read_text())
# Traverse
for scene in fg.scenes:
print(f"{scene.title} ({scene.shot_count} shots)")
for shot in scene.shots:
print(f" {shot.cinematography.shot_size} {shot.visual.description}")
# Save
Path("movie.filmgraph.json").write_text(fg.to_json(indent=2))
Schema
FilmGraph
├── meta: FilmMeta # title, duration, resolution, data sources
├── entities: Entities # characters, locations (referenced by ID)
├── scenes: [Scene] # narrative segments
│ ├── shots: [Shot] # atomic visual units (cut to cut)
│ │ ├── cinematography # shot_size, camera_movement, camera_angle
│ │ ├── visual # description, colors, lighting
│ │ ├── audio # dialogue lines, music cues, SFX
│ │ └── editorial # transitions, confidence, thumbnail
│ └── dialogue: [DialogueLine]
└── events: [Event] # plot turning points
Controlled Vocabularies
Every categorical field uses a controlled enum with an OTHER fallback for extensibility.
| Enum | Values |
|---|---|
| ShotSize | ECU · BCU · CU · MCU · MS · MLS · MWS · WS · EWS · INSERT · AERIAL · OTHER |
| ShotType | single · two-shot · group · over-the-shoulder · point-of-view · reaction · establishing · insert · cutaway · master · other |
| CameraMovement | static · pan · tilt · dolly · truck · tracking · handheld · crane · drone · zoom · whip-pan · push-in · pull-out · arc · rack-focus · steadicam · other |
| CameraAngle | eye-level · high-angle · low-angle · birds-eye · worms-eye · dutch-angle · overhead · ground-level · other |
| Transition | cut · dissolve · fade-in · fade-out · fade-to-black · wipe · match-cut · jump-cut · j-cut · l-cut · smash-cut · other |
Importers
Convert industry formats into FilmGraph with a single function call:
from filmgraph.importers.ccsl import ccsl_to_filmgraph
from filmgraph.importers.srt import srt_to_filmgraph
fg = ccsl_to_filmgraph("FTR3_BloodyTennis.docx")
fg = srt_to_filmgraph("movie.srt", title="My Film")
| Importer | Function | Input | Extra |
|---|---|---|---|
| CCSL | ccsl_to_filmgraph() |
.docx shot lists |
pip install filmgraph[docx] |
| Dialogbuch | dialogbuch_to_filmgraph() |
German dubbing scripts .docx |
pip install filmgraph[docx] |
| AD Script | ad_to_filmgraph() |
Audio description scripts .docx |
pip install filmgraph[docx] |
| SRT/VTT | srt_to_filmgraph() |
Subtitle files | — |
| Pipeline | timeline_to_filmgraph() |
Pipeline JSON output | — |
| OTIO | otio_to_filmgraph() |
EDL, FCP XML, AAF | pip install filmgraph[otio] |
Each importer also works as a CLI:
python -m filmgraph.importers.ccsl input.docx -o output.filmgraph.json
python -m filmgraph.importers.srt movie.srt -o subs.filmgraph.json
Exporters
Go the other direction — render a FilmGraph as the industry format of your choice:
from filmgraph.exporters.srt import filmgraph_to_srt
from filmgraph.exporters.ccsl import filmgraph_to_ccsl
Path("movie.srt").write_text(filmgraph_to_srt(fg))
filmgraph_to_ccsl(fg, "movie_ccsl.docx")
| Exporter | Function | Output | Extra |
|---|---|---|---|
| SRT/VTT | filmgraph_to_srt() / filmgraph_to_vtt() |
Subtitles | — |
| CCSL | filmgraph_to_ccsl() |
.docx shot list |
pip install filmgraph[docx] |
| Dialogbuch | filmgraph_to_dialogbuch() |
German dubbing script .docx |
pip install filmgraph[docx] |
| AD Script | filmgraph_to_ad() |
Audio description .docx |
pip install filmgraph[docx] |
| Pipeline | filmgraph_to_timeline() |
Pipeline JSON | — |
| Ground Truth | filmgraph_to_ground_truth() |
Bloody Tennis-style JSON fixture | — |
| OTIO | filmgraph_to_otio() |
EDL, FCP XML, AAF, .otio |
pip install filmgraph[otio] |
| CSV | filmgraph_to_csv() |
Flat shot-list CSV | — |
| Markdown | filmgraph_to_markdown() |
Human-readable report | — |
Every exporter also works as a CLI:
python -m filmgraph.exporters.srt movie.filmgraph.json -o movie.srt
python -m filmgraph.exporters.ccsl movie.filmgraph.json -o movie_ccsl.docx
python -m filmgraph.exporters.otio_export movie.filmgraph.json -o edit.edl
python -m filmgraph.exporters.markdown movie.filmgraph.json -o report.md
Build a FilmGraph Programmatically
from filmgraph import *
fg = FilmGraph(
meta=FilmMeta(title="My Film", duration=5400.0),
entities=Entities(characters=[
Character(id="alice", name="Alice"),
Character(id="bob", name="Bob"),
]),
scenes=[
Scene(
id=1,
title="Opening",
summary="Alice meets Bob",
start_time=0,
end_time=120,
shots=[
Shot(
id="sh-001",
order=1,
start_time=0,
end_time=8.5,
cinematography=Cinematography(
shot_size=ShotSize.WS,
camera_movement=CameraMovement.STATIC,
),
visual=Visual(description="Wide shot of a café"),
audio=Audio(dialogue=[
DialogueLine(
speaker="alice",
text="Is this seat taken?",
start_time=3.0,
end_time=5.2,
),
]),
),
],
),
],
)
print(fg.to_json(indent=2))
JSON Schema
Generate the full JSON Schema for validation or code generation:
import json
from filmgraph import FilmGraph
schema = FilmGraph.model_json_schema()
print(json.dumps(schema, indent=2))
Contributing
Contributions welcome. Please open an issue first to discuss what you'd like to change.
License
Metadata
Release files for filmgraph 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| filmgraph-0.1.2.tar.gz | 85.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| filmgraph-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 135.5 kB
Release files / filmgraph-0.1.2.tar.gz
| Download URL | filmgraph-0.1.2.tar.gz |
|---|---|
| Size | 85.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6fd1cc3402562ddef478559ab565a290903bc6fcefee1b860290450e1c41282b
|
|
BLAKE2b-256 checksum How to use checksums |
eb50532c7621349ac01f4a65b9303b96ee7d54bb998e25369ab7b8fa5ce96fca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 28, 2026.
Transparency logRelease files / filmgraph-0.1.2-py3-none-any.whl
| Download URL | filmgraph-0.1.2-py3-none-any.whl |
|---|---|
| Size | 49.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
74991bc4820467e39a9a534312e2e5c636e5bbb1da5e7519a1a6420083a33c67
|
|
BLAKE2b-256 checksum How to use checksums |
c99562cd2a044d9713efd9990e8e95630063cf12da412360b4e96140dff3636f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 28, 2026.
Transparency log