<!-- SPDX-FileCopyrightText: 2021-2022 Julius Künzel <julius.kuenzel@kde.org> SPDX-FileCopyrightText: 2015-2023 Jean-Baptiste Mardelle <jb@kdenlive.org> SPDX-License-Identifier: CC0-1.0 -->
Kdenlive 文件格式
Kdenlive 的工程文件(.kdenlive 文件)使用一种基于 MLT 格式的 XML 格式(参见 MLT 的 XML 文档 (opens in a new tab)和 MLT 的 DTD/文档类型定义 (opens in a new tab)),用于描述工程中所使用的源媒体,以及这些媒体在时间线中的使用方式。
对于大多数媒体(如视频、音频、图像),Kdenlive 在工程中只存储引用,而不存储媒体本身。只有少数媒体会直接存储在 Kdenlive 的工程文件内部,最典型的是 Kdenlive 标题片段和颜色片段。
这一文件格式决策的重要方面包括:
- MLT 能够直接渲染 Kdenlive 工程文件。 MLT 会简单地忽略所有额外的 Kdenlive 专属工程数据,只专注于它自己的渲染信息。Kdenlive 专属数据就像是锦上添花的额外糖霜,让处理工程比在(更底层的)渲染层面编辑容易得多。
- Kdenlive 可以直接包含并使用 MLT 渲染文件, 就像处理其他媒体一样。事实上,Kdenlive 的库片段就是 MLT 渲染文件,仅此而已。
历史与代际
根据你所使用的 Kdenlive 版本不同,存在不同的文件格式代际。
第 1 代
第 1 代(gen-1)工程是在最高到 0.9.10 版本的 Kdenlive 中创建和最后编辑的。这些是为 KDE 4.x 开发的 Kdenlive 版本。(虽然这并不完全严格成立,但我们不会讨论 Kdenlive 早期的 KDE 3.x 版本。)
gen-1 工程包含大量工程数据,这些数据需要被复制一份到外层的 MLT XML 数据中,MLT 才能知道它需要做什么。作为这种数据双重存储的不幸后果,gen-1 工程常有这样一种"习惯":外层 MLT 数据与内层 Kdenlive 工程数据失去同步。例如有时实际渲染出的效果,与在 Kdenlive 用户界面中设置的效果参数不一致。针对这种情况,Kdenlive 开发者们采取的恰当补救措施,是在把 Kdenlive 移植到 KDE Frameworks 5(KF5)的过程中切换到第 2 代。
第 2 代:KF5
用于 Kdenlive 15.04 至 17.08 版本
在 KF5/Qt5 版本的 Kdenlive 中,我们现在通过 MLT 的 xml 模块存储所有 Kdenlive 数据,以消除 Kdenlive 工程文件结构中的数据双重存储。这种修正后的工程数据模型带来了稳定得多的 Kdenlive 工程行为。另一个积极的副作用是:现在从 Kdenlive 外部手动编辑或创建 Kdenlive XML 工程文件容易得多了。
轻微不合法的 XML?
当你需要使用 XML 工具处理 Kdenlive 工程文件时,对于 gen-2 工程文件,有一个坑(gotcha)需要注意。一旦工程使用了整轨效果,Kdenlive 写出的工程 XML 就会变得不合法。如果只在 Kdenlive 内部编辑 Kdenlive 工程文件并用 MLT 渲染,你察觉不到这一点;只有使用标准 XML 工具编辑时才会发现。
原因是 gen-2 工程文件在一个独立的 "kdenlive" 命名空间内使用了它们自己的属性。不幸的是,Kdenlive 忘记在每个 XML 工程文档开头声明它所使用的这个额外命名空间。一个简单的修复方法是:在用 XML 工具处理 Kdenlive 工程文件之前,自行补上缺失的命名空间声明:
<?xml version='1.0' encoding='utf-8'?>
<mlt xmlns:kdenlive="http://www.kdenlive.org/project" ...>
...
</mlt>第 3 代:Timeline 2
用于 Kdenlive 19.04.0 至 20.04.3 版本
第 3 代工程是指使用搭载新 Timeline 2 引擎的 Kdenlive 版本创建或编辑的工程。
第 4 代:逗号 / 句点
用于 Kdenlive 20.08.0 至 22.12.3 版本,Kdenlive 文档版本:1.00
在 20.08.0 版本中,对工程文件的一次重大重构修复了一个长期存在的小数分隔符 (opens in a new tab)(逗号/句点)冲突问题——该问题曾导致许多崩溃。用 20.08 及之后版本创建的工程不向后兼容。
为支持新功能,还做了一些小的更新,例如:
- 20.12.0:引入了同轨混合(Mixes,即同轨转场 in-track-transitions)
第 5 代:当前格式
用于 Kdenlive 23.04.0 起的版本,Kdenlive 文档版本:1.1
Kdenlive 23.04.0 引入了一项重要变化:多时间线序列(multiple sequences)。每个时间线序列片段都嵌入在一个 MLT tractor(牵引器)中。 "main_bin" 播放列表(playlist)以*条目(entries)*的形式列出工程中使用的所有片段和时间线序列。
工程文件中最后一个 tractor 只是最近打开的时间线序列的一个包装器,这样当通过 melt 命令行播放工程文件时,它会播放最后激活的序列片段。
此前,所有时间线属性都以 kdenlive:documentproperty. 的形式存储在 "main_bin" 播放列表中。在新格式下,所有时间线属性都存储在各自的时间线序列内部,形如 kdenlive:sequenceproperty.,而 "main_bin" 中只存储全局工程设置。
工程 XML 结构
Kdenlive 工程文件内部 XML 数据的总体结构大致如下图所示:
<mlt producer="main_bin" ...>
<!-- the profile - definition of the project profile (frame size, aspect ration, etc) -->
<profile frame_rate_num="25" .../>
<!-- definition of master and timeline clips used in the first sequence clips -->
<producer id="producer0" .../>
<producer id="producer1" .../>
<!-- then comes the playlist definition - a list of the empty spaces and clips on a track -->
<playlist id="playlist0">
<!-- entries linking to the producers defined above -->
<entry producer="producer0" in="00:00:00.000" out="00:00:04.960">
<property name="kdenlive:id">3</property>
</entry>
<blank length="00:00:03.720"/> <!-- space between clips -->
<entry producer="producer1" />
...
<playlist id="playlist1"/>
<!-- After that we have the tracks embedded in a tractor. Each Kdenlive timeline track is made of 2 *tracks* to allow mixes-->
<tractor id="tractor0" in="00:00:00.000" out="00:02:20.840">
<property name="kdenlive:..">...</property>
...
<track hide="audio" producer="playlist0"/> <!-- hide audio, because this is a video track -->
<track hide="audio" producer="playlist1"/>
</tractor>
<!-- After the tracks definition, we have the first timeline sequence tractor that has a kdenlive:uuid attribute, and transitions between the tracks -->
<tractor id="tractor6" ...>
<property name="kdenlive:uuid">...</property>
<track hide="audio" producer="tractor0"/>
<track hide="audio" producer="tractor1"/>
<!-- all transitions -->
<transition id="transition0"/> <!-- user transitions -->
<transition id="transition1"> <!-- internally added transition (for example audio mix) -->
<property name="internal_added">237</property>
</transition>
</tractor>
<!-- If we have multiple timeline sequence clips, we repeat the above steps -->
<producer id="producer3" .../>
<playlist id="playlist3" ../>
<tractor id="tractor7" .../>
<tractor id="tractor11" ...>
<property name="kdenlive:uuid">...</property>
<track hide="audio" producer="tractor7"/>
<track hide="audio" producer="tractor8"/>
</tractor>
<!-- The *main bin* playlist, keeping all project settings, and a list of all project bin clips, including the sequence clips -->
<playlist id="main_bin">
<property name="kdenlive:documentproperty...">...</property>
<entry producer="producer0" .../>
<entry producer="producer1" .../>
<entry producer="tractor6" .../>
<entry producer="tractor11" .../>
</playlist>
<!-- the last tractor of the xml file only contains one producerm is a the main tractor, containing the default sequence clip that will be played -->
<tractor id="tractor23" in="00:00:00.000" out="00:00:45.000">
<property name="kdenlive:projectTractor">1</property>
<track producer="tractor11" in="00:00:00.000" out="00:00:45.000"/>
</tractor>
</mlt>我们避免存储任何在外层 MLT 数据层中已经存在的内层 Kdenlive 工程数据,这意味着所有信息都必须存储在 MLT 对象中,如 Tractor、Playlist、Producer 等。
为了把这些属性与其他 MLT 属性区分开,我们给它们加上 kdenlive: 前缀。本页列出了我们在新文件格式中使用的这些属性。
应用于工程片段(MLT Producer 对象)的属性:
| 名称 | 描述 |
|---|---|
| kdenlive:clipname | 存储该片段在工程素材箱(Project Bin)中显示的名称。 |
| kdenlive:folderid | 存储一个字符串,包含该片段所在文件夹的 id(若片段位于根文件夹则为空)。 |
| kdenlive:zone_in | 存储为该片段定义的播放区域的 "in"(入点)。 |
| kdenlive:zone_out | 存储为该片段定义的播放区域的 "out"(出点)。 |
| kdenlive:originalurl | 存储片段的原始 url。在片段被代理(proxy)后,可用于取回原始 url。 |
| kdenlive:proxy | 存储代理片段的 url;若该片段不应使用代理,则为 "-"。 |
| kdenlive:clip_type | |
| kdenlive:id | |
| kdenlive:file_size | |
| kdenlive:file_hash | |
| kdenlive:audio_max1 |
素材箱(Project Bin)
(工程)素材箱(bin)由一个具有众所周知 id "main_bin" 的 MLT <playlist> 元素表示。该元素保存工程专属的(元)数据、素材箱文件夹及其层级结构、片段组,以及其他一些内容。
注意
尽管 Kdenlive 现在提到早先的"project bin(工程箱)"时主要使用"bin(素材箱)"一词,但早期形成的内部名称 "name bin" 自 Kdenlive 创建之初就一直沿用至今。
应用于素材箱播放列表(MLT Playlist 对象 "main_bin")的属性:
| 名称 | 描述 |
|---|---|
| kdenlive:folder.xxx.yyy | 此属性存储在工程素材箱中创建的文件夹名称。xxx 是父文件夹的 id(根文件夹为 -1),yyy 是该文件夹自身的 id。此属性的值即文件夹的名称。 |
| kdenlive:docproperties.* | 有一系列带此前缀的属性,持有与当前工程相关的设置,例如代理尺寸 |
| kdenlive:documentnotes | |
| kdenlive:docproperties.groups | 此属性持有一个 json 结构,表示时间线上的片段组 |
时间线轨道
时间线轨道的布局由一个 MLT <tractor> 元素表示,这个 "maintractor" 可以通过它是文件中最后一个 <tractor> 来识别。其内部的元素就是各个时间线轨道:这些轨道以引用的形式出现,而实际轨道则是 MLT 生产器(producer)。
各个 Kdenlive 时间线轨道以持有 <playlist> 元素的 MLT <tractor> 元素的形式存在。它们也很容易按其 "tractor#"/"playlist#" 的 id 命名方案来识别;其中 "#" 是 Kdenlive 内部维护的一个编号。这些轨道还带有额外的属性,描述其标题、锁定状态以及其他一些信息。之所以多出 <playlist> 元素这一层结构,是为了支持混合(mixes,见下文)。
这里有一条半内部性质的轨道,即内置的 "black_track"。从这里可以看到,它虽然内置于 Kdenlive,却并不内置于 MLT。对 MLT 而言,这只是又一条恰好由 Kdenlive 创建的轨道。Kdenlive 从不会在时间线上把这条背景轨道作为单独轨道显示出来。但你可以在转场(transition)中引用它(指 composite 合成类转场)。
字幕轨道
对用户而言,这条字幕轨道感觉上就像一条音频或视频轨道,但事实上它并不是。它是一条"假"轨道,内部其实是一个滤镜(filter),更确切地说是 avfilter.subtitles (opens in a new tab) 滤镜(另见 这份 ffmpeg 文档 (opens in a new tab))。如果检测到内部的 avfilter.subtitles,字幕轨道就会被启用。
字幕存储在项目旁边的一个 *.srt 文件中。如果你的工程名为 mymovie.kdenlive,字幕文件就是 mymovie.kdenlive.srt。只有在保存工程时该文件才会更新;而在编辑工作期间,仅靠内部字幕模型是不够的,因为 avfilter.subtitles 需要一个 *.srt 文件才能在监视器中始终呈现最新的工作状态。因此在临时目录(Linux 上为 /tmp)中还有另一个 *.srt 文件。
字幕轨道在 kdenlive xml 中的表示方式如下:
<filter id="filter9">
<property name="mlt_service">avfilter.subtitles</property>
<property name="internal_added">237</property>
<property name="av.filename">/tmp/1654509160006.srt</property>
<property name="kdenlive:locked">1</property>
</filter>转场(Compositions)
转场有两(三)种风味,但一律以 MLT <transition> 元素表示:
- 用户转场(user transitions)是由——你猜到了——用户添加的转场。它们就是目前在时间线轨道及其片段之上略微下移、叠加显示的那些转场。
- 内部添加的转场(internally added transitions)基本上是一种便利机制,让时间线能够在多条轨道间自动进行音频混合,以及(在较新的 Kdenlive 版本中)实现透明轨道。
同轨转场(Mixes)
TODO
滤镜(效果)
TODO
未展示部分
- 素材箱片段生产器(bin clip producers)
- 代理片段(proxy clips)
延伸阅读
- Kdenlive Project Analyzer (opens in a new tab)(Kdenlive 工程分析器)有点像一位(疯狂的)简易 Kdenlive 医生:给定一个 Kdenlive gen-2 工程文件,它会展示一些统计信息和细节。你甚至可以用 Chrome/Chromium 或 Firefox 在线 (opens in a new tab)试用 Kdenlive Project Analyzer。源码可在 GitHub 上获取。 (opens in a new tab)