ProPresenter 7 .proplaylist File Format Specification
Version: 1.0
Target Audience: AI agents, automated parsers, developers
Proto Source: greyshirtguy/ProPresenter7-Proto v7.16.2 (MIT License)
1. Overview
File Format
- Extension:
.proplaylist
- Container Format: ZIP64 archive (PKZIP 4.5+)
- Compression: Store only (no deflate compression)
- Binary Format: Protocol Buffers (Google protobuf v3)
- Top-level Message:
rv.data.Playlist (defined in playlist.proto)
- Proto Definitions: greyshirtguy/ProPresenter7-Proto v7.16.2 (MIT)
Container Structure
- Archive Type: ZIP64 with store compression (compression method 0)
- ZIP64 EOCD Quirk: 98-byte discrepancy between ZIP64 EOCD locator offset and actual EOCD position
- Entry Layout:
data file at root (protobuf binary)
.pro song files at root (filename only, no directory structure)
- Media files at original absolute paths (minus leading
/)
Known Limitations
- Binary Fidelity: Round-trip decode→encode fails on all reference files. Proto definitions are incomplete; unknown fields are lost during serialization.
- Workaround: Preserve original binary data if exact binary reproduction is required.
File Validity
- Empty files (0 bytes): Invalid. Throw exception.
- Playlists without items: Valid. Empty playlists are allowed.
- Deduplication: Same
.pro file stored once; media files deduplicated by path.
2. Playlist Structure
Hierarchy Diagram
PlaylistDocument (ZIP64 archive)
├── data (protobuf binary)
│ └── Playlist (rv.data.Playlist) ← Root container named "PLAYLIST"
│ ├── name (string, field 2) = "PLAYLIST"
│ ├── uuid (rv.data.UUID, field 1)
│ ├── type (rv.data.Playlist.Type, field 3) = TYPE_PLAYLIST (1)
│ └── playlists (rv.data.Playlist.PlaylistArray, field 12)
│ └── playlists[] (rv.data.Playlist) ← Actual named playlist
│ ├── name (string, field 2) ← User-defined name
│ ├── uuid (rv.data.UUID, field 1)
│ ├── type (rv.data.Playlist.Type, field 3) = TYPE_PLAYLIST (1)
│ └── items (rv.data.Playlist.PlaylistItems, field 13)
│ └── items[] (rv.data.PlaylistItem)
│ ├── uuid (rv.data.UUID, field 1)
│ ├── name (string, field 2)
│ └── ItemType (oneof)
│ ├── header (field 3) ← Section divider
│ ├── presentation (field 4) ← Song reference
│ ├── cue (field 5) ← Inline cue
│ ├── planning_center (field 6) ← PCO integration
│ └── placeholder (field 8) ← Empty slot
├── *.pro files (song files, deduplicated)
└── media files (images/videos at original absolute paths)
Navigation Paths
To access playlist items:
PlaylistDocument (ZIP)
→ data (protobuf)
→ Playlist (root "PLAYLIST")
→ playlists.playlists[0] (actual playlist)
→ items.items[]
→ ItemType (oneof)
To access presentation references:
PlaylistItem
→ presentation
→ document_path (URL)
→ arrangement (UUID)
→ arrangement_name (string)
→ user_music_key (MusicKeyScale)
To access header dividers:
PlaylistItem
→ header
→ color (Color)
→ actions[] (Action)
3. Fields Reference
Playlist (rv.data.Playlist)
| Field Path |
Protobuf Type |
Field Number |
Description |
uuid |
rv.data.UUID |
1 |
Unique identifier for the playlist |
name |
string |
2 |
Playlist name (root is always "PLAYLIST") |
type |
rv.data.Playlist.Type |
3 |
Playlist type (always TYPE_PLAYLIST = 1) |
expanded |
bool |
4 |
UI expansion state |
targeted_layer_uuid |
rv.data.UUID |
5 |
Target layer UUID |
smart_directory_path |
rv.data.URL |
6 |
Smart playlist directory path |
hot_key |
rv.data.HotKey |
7 |
Keyboard shortcut |
cues[] |
rv.data.Cue |
8 |
Array of cues (not used in observed files) |
children[] |
rv.data.Playlist |
9 |
Array of child playlists (deprecated) |
timecode_enabled |
bool |
10 |
Timecode synchronization enabled |
timing |
rv.data.Playlist.TimingType |
11 |
Timing type (NONE, TIMECODE, TIME_OF_DAY) |
playlists |
rv.data.Playlist.PlaylistArray |
12 |
Child playlists (oneof ChildrenType) |
items |
rv.data.Playlist.PlaylistItems |
13 |
Playlist items (oneof ChildrenType) |
smart_directory |
rv.data.Playlist.FolderDirectory |
14 |
Smart folder config (oneof LinkData) |
pco_plan |
rv.data.PlanningCenterPlan |
15 |
Planning Center plan (oneof LinkData) |
startup_info |
rv.data.Playlist.StartupInfo |
16 |
Startup trigger configuration |
Playlist.PlaylistArray
| Field Path |
Protobuf Type |
Field Number |
Description |
playlists[] |
rv.data.Playlist |
1 |
Array of child playlists |
Playlist.PlaylistItems
| Field Path |
Protobuf Type |
Field Number |
Description |
items[] |
rv.data.PlaylistItem |
1 |
Array of playlist items |
PlaylistItem (rv.data.PlaylistItem)
| Field Path |
Protobuf Type |
Field Number |
Description |
uuid |
rv.data.UUID |
1 |
Unique identifier for the item |
name |
string |
2 |
Item display name |
tags[] |
rv.data.UUID |
7 |
Array of tag UUIDs |
is_hidden |
bool |
9 |
Whether item is hidden in UI |
header |
rv.data.PlaylistItem.Header |
3 |
Section divider (oneof ItemType) |
presentation |
rv.data.PlaylistItem.Presentation |
4 |
Song reference (oneof ItemType) |
cue |
rv.data.Cue |
5 |
Inline cue (oneof ItemType) |
planning_center |
rv.data.PlaylistItem.PlanningCenter |
6 |
PCO integration (oneof ItemType) |
placeholder |
rv.data.PlaylistItem.Placeholder |
8 |
Empty slot (oneof ItemType) |
| Field Path |
Protobuf Type |
Field Number |
Description |
color |
rv.data.Color |
1 |
RGBA color (float values 0.0-1.0) |
actions[] |
rv.data.Action |
2 |
Array of actions (rarely used) |
PlaylistItem.Presentation
| Field Path |
Protobuf Type |
Field Number |
Description |
document_path |
rv.data.URL |
1 |
Path to .pro file (URL format) |
arrangement |
rv.data.UUID |
2 |
Arrangement UUID |
content_destination |
rv.data.Action.ContentDestination |
3 |
Content destination layer |
user_music_key |
rv.data.MusicKeyScale |
4 |
User-selected music key |
arrangement_name |
string |
5 |
Arrangement name (UNDOCUMENTED) |
PlaylistItem.PlanningCenter
| Field Path |
Protobuf Type |
Field Number |
Description |
item |
rv.data.PlanningCenterPlan.PlanItem |
1 |
PCO plan item reference |
linked_data |
rv.data.PlaylistItem |
2 |
Linked playlist item |
PlaylistItem.Placeholder
| Field Path |
Protobuf Type |
Field Number |
Description |
linked_data |
rv.data.PlaylistItem |
1 |
Linked playlist item |
4. ZIP64 Container Format
Archive Structure
- Format: ZIP64 (PKZIP 4.5+)
- Compression: Store only (compression method 0, no deflate)
- Entries:
data file at root (protobuf binary)
.pro song files at root (filename only)
- Media files at original absolute paths (minus leading
/)
ZIP64 EOCD Quirk
- Issue: 98-byte discrepancy between ZIP64 EOCD locator offset and actual EOCD position
- Observed Pattern: ZIP64 EOCD locator points to offset that is 98 bytes before actual EOCD record
- Workaround: Search backward from end of file for ZIP64 EOCD signature (
0x06064b50)
Entry Layout Example
data ← Protobuf binary
Test.pro ← Song file (filename only)
Oceans.pro ← Song file (filename only)
Users/me/Pictures/slide.jpg ← Media file (absolute path minus leading /)
Users/me/Videos/intro.mp4 ← Media file (absolute path minus leading /)
Deduplication Rules
- Song Files: Same
.pro file stored once (by filename)
- Media Files: Deduplicated by absolute path
- Example: If 3 playlist items reference
Oceans.pro, only 1 copy is stored in ZIP
5. Playlist Items
Definition
Playlist items represent individual entries in a playlist. Each item has a type (header, presentation, cue, planning_center, placeholder) defined by the ItemType oneof field.
Item Types
- Purpose: Section divider with color
- Usage: Visual separator in playlist UI
- Fields:
color (RGBA), actions[] (rarely used)
- Example: "Worship Set", "Announcements", "Offering"
Presentation (Field 4)
- Purpose: Reference to a
.pro song file
- Usage: Most common item type
- Fields:
document_path (URL) — Path to .pro file
arrangement (UUID) — Arrangement UUID
arrangement_name (string) — Arrangement name (e.g., "normal", "bene", "test2")
user_music_key (MusicKeyScale) — User-selected music key
content_destination (ContentDestination) — Target layer
- Example: Reference to "Oceans.pro" with arrangement "normal"
Cue (Field 5)
- Purpose: Inline cue (not observed in reference files)
- Usage: Embedded cue without external
.pro file
- Fields: Full
rv.data.Cue message
PlanningCenter (Field 6)
- Purpose: Planning Center Online integration
- Usage: Link to PCO plan item
- Fields:
item (PlanItem), linked_data (PlaylistItem)
- Note: Not in scope for this specification
Placeholder (Field 8)
- Purpose: Empty slot in playlist
- Usage: Reserve space for future item
- Fields:
linked_data (PlaylistItem)
Access Pattern
foreach ($playlist->getItems() as $item) {
$uuid = $item->getUuid();
$name = $item->getName();
if ($item->hasPresentation()) {
$presentation = $item->getPresentation();
$path = $presentation->getDocumentPath()->getAbsoluteString();
$arrangementName = $presentation->getArrangementName();
$arrangementUuid = $presentation->getArrangement()->getString();
} elseif ($item->hasHeader()) {
$header = $item->getHeader();
$color = $header->getColor();
} elseif ($item->hasPlaceholder()) {
// Empty slot
}
}
6. URL Format
URL Structure
ProPresenter uses rv.data.URL messages with root type and relative path components.
Root Types
- ROOT_USER_HOME (2): User home directory (
~/)
- ROOT_SHOW (10): ProPresenter library directory
Path Construction
- Format:
root_type + relative_path
- Example (ROOT_USER_HOME):
- Root:
ROOT_USER_HOME (2)
- Relative:
Music/ProPresenter/Oceans.pro
- Absolute:
file:///Users/username/Music/ProPresenter/Oceans.pro
- Example (ROOT_SHOW):
- Root:
ROOT_SHOW (10)
- Relative:
Oceans.pro
- Absolute:
file:///Users/username/Library/Application Support/RenewedVision/ProPresenter/Oceans.pro
Media File Paths
- Storage: Original absolute path minus leading
/
- Example:
- Original:
file:///Users/me/Pictures/slide.jpg
- ZIP entry:
Users/me/Pictures/slide.jpg
7. Protobuf Structure
Root Container
- Message:
rv.data.Playlist
- Name: Always "PLAYLIST"
- Type: Always
TYPE_PLAYLIST (1)
- Children:
playlists field (PlaylistArray)
Actual Playlist
- Location:
playlists.playlists[0]
- Name: User-defined (e.g., "Gottesdienst", "Sunday Service")
- Type: Always
TYPE_PLAYLIST (1)
- Children:
items field (PlaylistItems)
Nested Structure
Playlist (root "PLAYLIST")
→ playlists (PlaylistArray, field 12)
→ playlists[] (Playlist)
→ items (PlaylistItems, field 13)
→ items[] (PlaylistItem)
Example (TestPlaylist.proplaylist)
Playlist {
name: "PLAYLIST"
type: TYPE_PLAYLIST (1)
playlists: {
playlists: [
{
name: "TestPlaylist"
type: TYPE_PLAYLIST (1)
items: {
items: [
{ name: "Worship", header: { color: {...} } },
{ name: "Oceans", presentation: { document_path: {...}, arrangement_name: "normal" } },
{ name: "Amazing Grace", presentation: { document_path: {...}, arrangement_name: "bene" } },
]
}
}
]
}
}
8. Known Constants
Application Info
- Platform: macOS 14.8.3
- Application: ProPresenter v20
- Observed in: All reference files
Playlist Type
- Root Playlist: Always
TYPE_PLAYLIST (1)
- Child Playlists: Always
TYPE_PLAYLIST (1)
- Other Types:
TYPE_GROUP (2), TYPE_SMART (3), TYPE_ROOT (4) not observed in reference files
Root Name
- Value: Always "PLAYLIST"
- Purpose: Container for actual named playlists
Arrangement Name (Field 5)
- Status: UNDOCUMENTED in community proto
- Observed Values: "normal", "bene", "test2", "Gottesdienst", etc.
- Purpose: Human-readable arrangement name (complements arrangement UUID)
- Frequency: Present in every
PlaylistItem.Presentation in reference files
9. Edge Cases
Empty Playlists
- Items: 0 items
- Validity: Valid
- Behavior:
items.items[] is empty array
Playlists Without Presentations
- Items: Only headers and placeholders
- Validity: Valid
- Example: Template playlists with section dividers
Missing Arrangement Name
- Field:
arrangement_name (field 5)
- Behavior: Empty string or not set
- Validity: Valid (fallback to arrangement UUID)
Duplicate Song References
- Scenario: Same
.pro file referenced multiple times
- ZIP Storage: Single copy of
.pro file
- Playlist Items: Multiple
PlaylistItem.Presentation entries with same document_path
Media Files
- Storage: Original absolute paths (minus leading
/)
- Deduplication: By absolute path
- Example:
Users/me/Pictures/slide.jpg stored once even if referenced in multiple songs
10. Reverse-Engineering Evidence
Reference Files
- TestPlaylist.proplaylist: 4 ZIP entries, 3 items (1 header, 2 presentations)
- Gottesdienst.proplaylist: 14MB, 25+ items, multiple media files
- Gottesdienst 2.proplaylist: 10MB, similar structure
- Gottesdienst 3.proplaylist: 16MB, largest reference file
Key Discoveries
- ZIP64 EOCD Quirk: 98-byte offset discrepancy in all files
- Store Compression: No deflate compression (method 0)
- Arrangement Name: Field 5 on
PlaylistItem.Presentation is undocumented but present in all files
- Root Container: Always named "PLAYLIST" with
TYPE_PLAYLIST (1)
- Deduplication: Same
.pro file stored once, media files deduplicated by path
Observed Patterns
- Color Values: RGBA floats (e.g.,
[0.95, 0.27, 0.27, 1.0] for red)
- UUID Format: Standard UUID strings (e.g.,
A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6)
- Arrangement Names: User-defined strings (e.g., "normal", "bene", "test2", "Gottesdienst")
- Media Paths: Absolute file URLs (e.g.,
file:///Users/me/Pictures/slide.jpg)
Appendix: Proto Field Numbers Quick Reference
| Message |
Field |
Number |
| Playlist |
uuid |
1 |
| Playlist |
name |
2 |
| Playlist |
type |
3 |
| Playlist |
expanded |
4 |
| Playlist |
targeted_layer_uuid |
5 |
| Playlist |
smart_directory_path |
6 |
| Playlist |
hot_key |
7 |
| Playlist |
cues |
8 |
| Playlist |
children |
9 |
| Playlist |
timecode_enabled |
10 |
| Playlist |
timing |
11 |
| Playlist |
playlists |
12 |
| Playlist |
items |
13 |
| Playlist |
smart_directory |
14 |
| Playlist |
pco_plan |
15 |
| Playlist |
startup_info |
16 |
| PlaylistArray |
playlists |
1 |
| PlaylistItems |
items |
1 |
| PlaylistItem |
uuid |
1 |
| PlaylistItem |
name |
2 |
| PlaylistItem |
header |
3 |
| PlaylistItem |
presentation |
4 |
| PlaylistItem |
cue |
5 |
| PlaylistItem |
planning_center |
6 |
| PlaylistItem |
tags |
7 |
| PlaylistItem |
placeholder |
8 |
| PlaylistItem |
is_hidden |
9 |
| PlaylistItem.Header |
color |
1 |
| PlaylistItem.Header |
actions |
2 |
| PlaylistItem.Presentation |
document_path |
1 |
| PlaylistItem.Presentation |
arrangement |
2 |
| PlaylistItem.Presentation |
content_destination |
3 |
| PlaylistItem.Presentation |
user_music_key |
4 |
| PlaylistItem.Presentation |
arrangement_name |
5 |
| PlaylistItem.PlanningCenter |
item |
1 |
| PlaylistItem.PlanningCenter |
linked_data |
2 |
| PlaylistItem.Placeholder |
linked_data |
1 |
End of Specification