Skip to content

.drp and Project.db

Observed with DaVinci Resolve Studio 21.1.1. Nothing here comes from official documentation.

A Resolve project exists in two forms that hold the same records:

Form What it is drpkit
.drp File → Export Project: a zip archive of XML files read, write, compose
Project.db a project inside a disk-database project library: one SQLite file per project read only

.drp: the zip archive

Entry Holds
project.xml project settings and the LocableBlobSet (sic) of lockable blobs: clip colors (Sm2TiItemLockableBlob) and timeline markers (Sm2SequenceLockableBlob)
MediaPool/<folder path>/MpFolder.xml one per media-pool folder: media-pool items (Sm2MpAudioClip, …) and timelines (Sm2MpTimelineClip → Sm2Timeline → Sm2Sequence)
SeqContainer/<uuid>.xml one per timeline: Sm2SequenceContainer with the tracks (Sm2TiTrack) and their items
Gallery.xml color page stills (not read)

Element names in the XML are the database table names (Sm2…, Bt…); each record carries a DbId attribute (a UUID) that other records reference.

Timeline records (MpFolder.xml)

Element Field Meaning
Sm2Timeline Name timeline name
Sequence DbId of its Sm2Sequence
FrameRate timeline frame rate, hex of a little-endian double (the first 16 hex digits)
Sm2Sequence FieldsBlob hex of a QDataStream QVariantMap (below) — holds FLStudioModelBA, the Fairlight mixer
MediaExtents hex of two little-endian doubles: start seconds and span seconds. Start × fps = Timeline.GetStartFrame()

Tracks and items (SeqContainer/*.xml)

Sm2SequenceContainer
 ├ VideoTrackVec / AudioTrackVec
 │   └ Element → Sm2TiTrack   Type (1 = audio), UserDefinedName, Sequence, Items
 │        └ Items → Element → Sm2TiAudioClip | Sm2TiTransition | …
 └ Sequence  (DbId of the Sm2Sequence, links the container to its timeline)

The fields of clips and transitions are listed in Clips & edits.

Project.db: the SQLite database

drpkit opens it with file:<path>?mode=ro&immutable=1 (no lock, no write, no journal). The same records are tables; column names match the XML element names.

Table Columns used Meaning
Sm2Timeline Name, Sequence, FieldsBlob timelines. FieldsBlob is empty here
Sm2Sequence Sm2Sequence_id, FieldsBlob the timeline's sequence; FieldsBlob holds FLStudioModelBA
Sm2TiTrack Sm2TiTrack_id, Sequence, Type, UserDefinedName tracks of a sequence
Sm2TiItem Sm2TiItem_id, Sm2TiTrack_id, DbType, Name, PrettyType, Start, Duration, In, AlignmentType, Position, EffectFiltersBA, FieldsBlob clips and transitions; DbType is the XML element name (Sm2TiAudioClip, Sm2TiTransition)
BtLockableBlob BlobOwner, FieldsBlob clip colors and timeline markers (one table for both)

Joins:

-- mixer: timeline name + its Fairlight model
SELECT t.Name, s.FieldsBlob
  FROM Sm2Sequence s JOIN Sm2Timeline t ON t.Sequence = s.Sm2Sequence_id;

-- clips and transitions of one timeline, in track order
SELECT k.Type, k.UserDefinedName, i.DbType, i.Sm2TiItem_id, i.Name, i.PrettyType, i.Start, i.Duration,
       i."In", i.AlignmentType, i.Position, i.EffectFiltersBA, i.FieldsBlob
  FROM Sm2TiItem i JOIN Sm2TiTrack k ON i.Sm2TiTrack_id = k.Sm2TiTrack_id
 WHERE k.Sequence = :sequence ORDER BY k.rowid, i.Start;

-- colors (BlobOwner = Sm2TiItem_id) and markers (BlobOwner = Sm2Sequence_id)
SELECT FieldsBlob, BlobOwner FROM BtLockableBlob WHERE FieldsBlob IS NOT NULL;

Project.db has no frame rate in the tables drpkit reads, so --edits from a database reports frames only (no timecode, no absolute marker frames).

Encodings

Four container formats appear inside these fields.

QDataStream QVariantMap (FieldsBlob)

Qt's big-endian serialization:

u32 version | u32 count | count × ( key: QString, value: QVariant )
QString  = u32 byte length (0xFFFFFFFF = null) + UTF-16BE
QVariant = u32 type id + u8 null flag + value
Type id Value
1 bool (1 byte)
2 / 3 int32 / uint32 (BE)
4 / 5 int64 / uint64 (BE)
6 double (BE)
8 nested QVariantMap (u32 count + entries)
9 QVariantList (u32 count + QVariants)
10 QString
11 QStringList
12 QByteArray (u32 length, 0xFFFFFFFF = null, + bytes)

The Sm2Sequence FieldsBlob has keys such as FLStudioModelBA, SeqRef, ModTimeInSecs, FirstMainBusFormat, Thumbnail.

qCompress (FLStudioModelBA)

FLStudioModelBA is a QByteArray produced by Qt's qCompress: a 4-byte big-endian uncompressed size followed by a zlib stream. Its content is described in Fairlight model.

Versioned blob (EffectFiltersBA, clip FieldsBlob, media Clip / FieldsBlob)

u32BE 2 (version) | u32BE length (includes the flag byte) | u8 flag | payload
flag 0x80 = payload stored as-is, 0x81 = payload compressed with zstd

The payload is a protobuf message (field numbers and wire types, no schema). Resolve writes most of these zstd-compressed; drpkit writes 0x80, which Resolve accepts. Reading 0x81 needs Python 3.14+ (compression.zstd) or the zstandard package.

Lockable blob (Sm2…LockableBlob / BtLockableBlob)

FieldsBlob is a QVariantMap with one key, BlobData (a QByteArray):

u32BE 0x00002711 | u32BE length (includes the flag byte) | u8 flag (0x80 raw / 0x81 zstd) | protobuf

Clip colors store a fixed 3-byte payload (80 28 <code>), markers a protobuf list — see Clips & edits.

Protobuf

Standard protobuf wire format: varint keys field << 3 | wiretype; wire type 0 = varint, 1 = 8 bytes, 2 = length-delimited, 5 = 4 bytes. Signed positions use zigzag encoding. Inside the length-delimited fields Resolve mixes little-endian values (doubles of scalar knobs, keyframe records) and big-endian ones (fade curve points, nested length headers) — each is noted where it occurs.