====== Olive Video Editor: an insight of the OVEXML file format ====== **[[https://www.olivevideoeditor.org/|Olive Video Editor]]** is the most open video editor in the world. From its completely configurable render pipeline to its open source codebase, every aspect of it is designed to provide users with as much control as possible over both their work and their workflow. ===== The project can be saved as an XML file ===== A feature that I really apreciated is the ability to save the project file into an XML file (with the **.ovexml** extension). Being addicted to the **GNU/Linux command** line and **ffmpeg** I immediately tried to convert an Olive project into an ffmpeg script. ===== A walk inside the OVEXML ===== Here I explain some findings on an **OVEXML** file created with **Olive v.0.2**. Beware that the project I worked on is a **really simple** one! Only two tracks (one video and one audio), video is always locked with the audio, **the clips are just concatenated** without transition effects, gaps, etc. Parsing the OVEXML of such a project is feasible, any extra feature could make the job too challenging. My goal was to print **the sequence of clips** used into a project, showing for each clip the footage filename, the start frame and the length. The aim is to make a list of unused footages to trash, and perhaps to build a timeline script to make a rendering using ffmpeg on the Linux command line. The first challenge was to find the link from the top level node of the project (the **org.olivevideoeditor.Olive.sequence**) down to the lower level nodes **org.olivevideoeditor.Olive.footage** (e.g. the media files on the computer disk). In this walk I had to figure out how to get the clip starting frame and its length. The nodes to walk into the XML structure are the following: **Olive.sequence** => **Olive.track** => **Olive.transform** => **Olive.footage** On each step we must relay to the **%%%%** tag of the parent node, to find the **ptr** attribute of the child, something like: 140198067323392 140198067446864 When following an audio track, you have to search for a **volume** node instead of the **transform**. Starting frame and length of the clip is into the **clip** node, something like this: 1001/200 0/1 As you can see the frame numbers are represented as rational numbers. Being my footages shot at 29.97 FPS (i.e. 30000/1001) the math is as follow: **1001 / 200 * 30000 / 1001 = 150** (i.e. 150 frames clip length). Beware to perform always the multiplications before the divisions, so that you surely get a whole number, without approximation. The most challenging part was to understand how the clips are ordered into the timeline. Unfortunately the **%%%%** nodes into the track are listed rougly in the order they are added to the project, the order does not correspond to the timeline order. We have instead to look at the **%%%%** tag of the track: AwAAAAgAAAAFAAAABwAAAAYAAAA= The ASCII string **%%AwAAAAgAAAAFAAAABwAAAAYAAAA=%%** is actually a base64 encoded binary string that you can decode on the command line into a binary file: echo 'AwAAAAgAAAAFAAAABwAAAAYAAAA=' | base64 -d > arraymap_in And then open it with an hex editor: 03 00 00 00 │ 08 00 00 00 │ 05 00 00 00 │ 07 00 00 00 │ 06 00 00 00 Hence the timeline sequence of clip elements: #3, #8, #5, #7 and #6 (32 bit unsigned integers, little endian). ===== Proof of concept program ===== Here you can find my Python script that I used to parse an Olive Editor project file, the output is the ordered list of all the clips used, with the **footage filename**, the **start frame** and the **length** of the clip (in frames). **{{.:olive:olive-ovexml-list-clips-in-project.py.txt|olive-ovexml-list-clips-in-project.py}}**