Skip to content

About

Read Adobe Premiere Pro project files (.prproj) in Python: sequences, tracks, clips, media paths, markers, with an OpenTimelineIO adapter

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

premiere-prproj-reader

ci PyPI License: MIT

Read Adobe Premiere Pro project files (.prproj) without Premiere: sequences, tracks, clips, in and out points, media paths, markers and the bin tree, as typed Python data. Convert any sequence to an OpenTimelineIO timeline.

It is for developers of tools that need to open a Premiere project: subtitle editors, asset managers, conform and archive scripts, other editors importing a Premiere edit. Read only, no runtime dependency, Python 3.9 and later.

Install

pip install premiere-prproj-reader
pip install "premiere-prproj-reader[otio]"   # with the OpenTimelineIO adapter

Quick start

The package ships two small projects saved by Premiere Pro 26.3, so this runs as written:

import premiere_prproj_reader as prproj

project = prproj.read(prproj.samples.path("markers"))
print(project.version)  # 45, the project format of Premiere Pro 26.3

for sequence in project.sequences:
    print(sequence.name, sequence.frame_rate, f"{sequence.width}x{sequence.height}")
    for track in sequence.tracks:
        for item in track.items:
            start = prproj.timecode(item.start_ticks, sequence.frame_rate)
            end = prproj.timecode(item.end_ticks, sequence.frame_rate)
            print(" ", track.label, start, end, item.name)
Seq A 30000/1001 64x36
  V1 00:00:00:00 00:00:04:29 red_64x36.bmp
  A1 00:00:04:29 00:00:05:28 tone_440_1s.wav
Seq B 30000/1001 64x36
  V1 00:00:00:00 00:00:05:28 Seq A
  A1 00:00:00:00 00:00:05:28 Seq A

read() takes a path, the file's bytes or a binary file object, gzip-compressed or plain XML.

Media paths (relink, collect, archive)

import premiere_prproj_reader as prproj

project = prproj.read(prproj.samples.path("markers"))
for media in project.media:
    print(media.title, media.path, media.relative_path, "offline" if media.offline else "")

path is the absolute path Premiere last resolved, relative_path the one relative to the project file. Generated media (Black Video, color mattes, bars and tone) has generated=True and no path.

Clips, source ranges and nested sequences

import premiere_prproj_reader as prproj

project = prproj.read(prproj.samples.path("markers"))
outer = project.find_sequence("Seq B")
item = outer.video_tracks[0].items[0]
print(item.in_point_ticks, item.out_point_ticks, item.speed, item.enabled)
if item.sequence_id is not None:
    nested = project.sequence_by_id(item.sequence_id)
    print("nests", nested.name)

Every time is an integer count of Premiere ticks (254,016,000,000 per second), so nothing is lost to rounding. ticks_to_seconds, ticks_to_frames and timecode convert them; frame rates are exact Fractions (29.97 is 30000/1001). in_point_ticks and out_point_ticks are in the source's own time, so for a clip at 50 percent speed the source range is half the timeline length.

Markers

import premiere_prproj_reader as prproj

project = prproj.read(prproj.samples.path("markers"))
for marker in project.find_sequence("Seq A").markers:
    seconds = prproj.ticks_to_seconds(marker.start_ticks)
    print(f"{seconds:.2f}s", marker.type, marker.name, marker.comment, marker.url or "")

Sequence markers and clip markers carry name, comment, start, duration, type (Comment, Chapter, Segmentation, WebLink, FlashCuePoint) and the URL of a web link.

The bin tree

import premiere_prproj_reader as prproj

project = prproj.read(prproj.samples.path("markers"))
for entry in project.root.walk():
    kind = "bin" if isinstance(entry, prproj.Bin) else "clip"
    print(kind, entry.name)

OpenTimelineIO

With the otio extra installed:

import opentimelineio as otio
import premiere_prproj_reader as prproj
from premiere_prproj_reader.otio import to_timeline

project = prproj.read(prproj.samples.path("markers"))
timeline = to_timeline(project.find_sequence("Seq A"), project)
print(otio.adapters.write_to_string(timeline, "otio_json")[:80])

Installing the otio extra also registers a prproj adapter, so OpenTimelineIO tools read projects directly:

import opentimelineio as otio

timeline = otio.adapters.read_from_file("edit.prproj")

From there, OpenTimelineIO and its adapter plugins write the timeline to the other formats they support (Final Cut Pro XML, CMX 3600 EDL and more).

Command line

prproj info edit.prproj          # versions, sequences, tracks
prproj json edit.prproj          # the whole project as JSON
prproj otio edit.prproj edit.otio --sequence "Main edit"

From another language (C#, Rust, JavaScript)

Editors and subtitle tools written in other languages can call the CLI and read its JSON instead of keeping their own .prproj parser:

prproj json edit.prproj > edit.json
{"version": 45, "build": "26.3.0x93 - 20/07/2026 14:03:26",
 "sequences": [{"id": "9c19c828-...", "name": "Seq A", "frame_rate": "30000/1001",
   "width": 64, "height": 36,
   "video_tracks": [{"kind": "video", "index": 0, "muted": false, "locked": false,
     "items": [{"name": "red_64x36.bmp", "start_ticks": 0, "end_ticks": 1262874412800,
       "in_point_ticks": 914456685542400, "out_point_ticks": 915719559955200,
       "speed": 1.0, "enabled": true, "sequence_id": null, "markers": [],
       "media": {"title": "red_64x36.bmp", "path": "C:\\...\\red_64x36.bmp",
                 "relative_path": "..\\assets\\red_64x36.bmp", "offline": false,
                 "generated": false}}]}],
   "audio_tracks": [], "markers": [{"name": "chapter", "type": "Chapter",
     "start_ticks": 254016000000, "duration_ticks": 0, "comment": "", "url": null}]}],
 "media": [], "root": {"name": "", "children": []}}

(Shortened.) Ticks divide by 254,016,000,000 for seconds. A subtitle editor that needs the marker list, or an editor importing a Premiere timeline, maps sequences[].markers and sequences[].video_tracks[].items[] directly; an editor that already reads OpenTimelineIO can use prproj otio edit.prproj edit.otio instead.

Which Premiere versions

The tests read projects saved by Premiere Pro from 2.0 (project format 18, 2006) to 26.3 (format 45, 2026): format 18, 19 (CS3), 35 (11.1), 38 (14.0), 42 (24.4), 43 (25.2) and 45 (26.3). The element names this reader follows are the same across all of them. Older formats are skeletons reduced from real projects by scripts/reduce_fixture.py (every name and path replaced); the format 45 projects are the py-premiere sample set (MIT), and the test suite checks this library against the values Premiere's own ExtendScript reported for them (tests/fixtures/truth/).

If a project of yours does not read, python scripts/drift_check.py DIR reports what failed, and scripts/reduce_fixture.py makes a shareable copy for a bug report.

Why this one

premiere-prproj-reader py-premiere prproj-parser otio-premiereproject prproj-rs
Scope read only, plain data read and write, ExtendScript-shaped object model read only OpenTimelineIO adapter Rust parser
Formats tested 18 to 45 (Premiere Pro 2.0 to 26.3) Premiere Pro 26.3 samples 2023 to 2026, per its README not stated one project in test_files/
Checked against Premiere's ExtendScript values yes (tests/fixtures/truth/) yes, per its README not stated not stated not stated
OpenTimelineIO to_timeline and an adapter plugin no no yes no
Markers, bin tree, source in and out points yes yes not in its API table in and out points only no
Last change 2026 2026 2026 2021 2023

The other columns come from each project's README and source as read on 2026-11-02.

Pick py-premiere when you need to write projects or read effects, keyframes and masks. Pick this one when you want a small dependency-free reader whose output is plain frozen dataclasses, exact ticks, and an OpenTimelineIO timeline, tested across twenty years of Premiere versions.

Safety

Projects come from users. The reader refuses XML carrying a DOCTYPE or ENTITY declaration (including one hidden by a UTF-16 or UTF-32 encoding), caps the decompressed size (read(..., max_bytes=...), 1 GiB by default) and bin nesting, and raises PrprojError on malformed numbers or references instead of crashing with another exception.

License

MIT. The sample projects in src/premiere_prproj_reader/samples/ and tests/fixtures/v45_* come from py-premiere (MIT, Copyright (c) 2026 Aurore Delaunay); its licence is kept beside them.

About

Read Adobe Premiere Pro project files (.prproj) in Python: sequences, tracks, clips, media paths, markers, with an OpenTimelineIO adapter

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages