Files
oak-editor/docs/zh/project-file-reference.md
T
2026-01-05 16:22:26 +08:00

306 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Oak Video Editor 项目文件参考手册(详细版)
本文档基于当前源代码实现,描述 Oak Video Editor 的 XML 项目文件格式,目标是足够详细以实现兼容读写器。
> 代码来源:`app/node/project.cpp`、`app/node/node.cpp`、`app/node/value.*`、`app/node/keyframe.*`、`app/node/project/serializer/*`。
## 1. 根元素
```xml
<olive version="230220" url="/path/to/project.ove">
...
</olive>
```
- `version`:序列化版本号(`YYMMDD`)。
- `url`:可选的项目文件路径。
## 2. 项目容器
完整保存时,会有 `project` 容器:
```xml
<project>
<project>...</project>
<layout>...</layout>
</project>
```
- 内层 `<project>`:项目数据。
- `<layout>`:界面布局(`MainWindowLayoutInfo::fromXml`)。
## 3. 项目数据(`Project::Save`
```xml
<project version="1">
<uuid>...</uuid>
<plugins>...</plugins>
<nodes>...</nodes>
<settings>...</settings>
</project>
```
### 3.1 `uuid`
项目 UUIDQUuid 字符串)。
### 3.2 `plugins`
项目中使用的 OpenFX 插件列表,用于加载节点前补充插件搜索路径。
```xml
<plugins>
<plugin id="com.vendor.Plugin" major="1" minor="2"
bundle="/path/to/Plugin.ofx.bundle"
file="/path/to/Plugin.ofx.bundle/Contents/MacOS/Plugin" />
</plugins>
```
属性:
- `id`OFX 插件标识符(与节点 `id` 相同)。
- `major` / `minor`:插件版本。
- `bundle`:插件 bundle 目录路径(优先使用)。
- `file`:插件二进制路径(备用)。
加载策略:
- 若存在 `<plugins>`,先把 `bundle`(或 `file`)加入 OFX 搜索路径并扫描,然后注册插件节点,再进入 `<nodes>` 解析。
### 3.3 `nodes`
节点图,节点由 `Node::Save()` 写出:
```xml
<nodes version="1">
<node version="1" id="node.id" ptr="123456">
<label>...</label>
<color>...</color>
<input>...</input>
<links>...</links>
<connections>...</connections>
<hints>...</hints>
<context>...</context>
<caches>...</caches>
<custom>...</custom>
</node>
</nodes>
```
关键属性:
- `id`:节点类型标识。OpenFX 节点为插件标识符。
- `ptr`:序列化指针 ID,用于恢复连接与位置。
- `version`:当前为 `1`
### 3.4 `settings`
项目设置,键值对形式保存:
已知键:
- `cachesetting`
- `customcachepath`
- `colorconfigfilename`
- `defaultinputcolorspace`
- `colorreferencespace`
- `root`
## 4. 节点序列化(`Node::Save` / `Node::Load`
### 4.1 `label`
节点显示名。
### 4.2 `color`
节点覆盖颜色(整数索引)。
### 4.3 `input`
每个输入:
```xml
<input id="InputId">
<primary>...</primary>
<subelements count="N">
<element>...</element>
</subelements>
</input>
```
- `primary`:主元素(element = -1)。
- `subelements`:数组输入,`count` 为数组长度。
#### 4.3.1 立即值结构(`primary` / `element`
```xml
<keyframing>0|1</keyframing>
<standard>
<track>...</track>
</standard>
<keyframes>
<track>
<key ...>...</key>
</track>
</keyframes>
<csinput>...</csinput>
<csdisplay>...</csdisplay>
<csview>...</csview>
<cslook>...</cslook>
```
- `keyframing`:是否启用关键帧(仅在输入可关键帧时写出)。
- `standard`:默认值(每条 track 一份)。
- `keyframes`:仅当 `keyframing=1` 时写出。
- `cs*`:仅用于 `kColor`,保存色彩管理信息。
#### 4.3.2 Track 数量
`NodeValue::get_number_of_keyframe_tracks()` 决定:
| 类型 | Track 数量 |
| --- | --- |
| kVec2 | 2 |
| kVec3 | 3 |
| kVec4 | 4 |
| kColor | 4 |
| kBezier | 6 |
| 其他 | 1 |
#### 4.3.3 标准值编码
`NodeValue::ValueToString()` 写出,`NodeValue::StringToValue()` 读入:
- `kVec2`: `x:y`
- `kVec3`: `x:y:z`
- `kVec4`: `x:y:z:w`
- `kColor`: `r:g:b:a`
- `kBezier`: `x:y:cp1x:cp1y:cp2x:cp2y`
- `kRational`: `num/den`
- `kInt`: 整数文本
- `kBinary`: Base64
- `kText` / `kFont` / `kFile` / `kCombo` / `kStrCombo`: 纯文本
- `kTexture` / `kSamples` / `kNone`: 无文本
特殊情况:
- `kVideoParams` / `kAudioParams` 以子对象形式保存(见第 5/6 节)。
- `kSubtitleParams` 在加载时被跳过(避免覆盖实际字幕数据)。
#### 4.3.4 关键帧(`NodeKeyframe::save`
```xml
<key input="InputId" time="num/den" type="0" inhandlex="0" inhandley="0" outhandlex="0" outhandley="0">value</key>
```
- `input`:输入 ID。
- `time`:理性时间。
- `type`:关键帧类型枚举值。
- `inhandlex` / `inhandley` / `outhandlex` / `outhandley`:贝塞尔控制点。
文本值使用 `NodeValue::ValueToString(data_type, value, true)`
### 4.4 `links`
节点间的“块”链接:
```xml
<links>
<link>ptr</link>
</links>
```
### 4.5 `connections`
输入/输出连接:
```xml
<connections>
<connection input="InputId" element="-1">
<output>ptr</output>
</connection>
</connections>
```
### 4.6 `hints`(输入提示)
```xml
<hints>
<hint input="InputId" element="-1" version="1">
<types>
<type>...</type>
</types>
<index>0</index>
<tag>...</tag>
</hint>
</hints>
```
### 4.7 `context`(节点位置)
```xml
<context>
<node ptr="other_node_ptr">
<x>0</x>
<y>0</y>
<expanded>0|1</expanded>
</node>
</context>
```
### 4.8 `caches`
```xml
<caches>
<audio>uuid</audio>
<video>uuid</video>
<thumb>uuid</thumb>
<waveform>uuid</waveform>
</caches>
```
### 4.9 `custom`
节点自定义内容,默认实现为空;各子类可覆盖。
## 5. VideoParams
`kVideoParams` 输入以子对象保存:
```xml
<width>...</width>
<height>...</height>
<depth>...</depth>
<timebase>num/den</timebase>
<format>int</format>
<channelcount>int</channelcount>
<pixelaspectratio>num/den</pixelaspectratio>
<interlacing>int</interlacing>
<divider>int</divider>
<enabled>0|1</enabled>
<x>float</x>
<y>float</y>
<streamindex>int</streamindex>
<videotype>int</videotype>
<framerate>num/den</framerate>
<starttime>int64</starttime>
<duration>int64</duration>
<premultipliedalpha>0|1</premultipliedalpha>
<colorspace>string</colorspace>
<colorrange>int</colorrange>
```
## 6. AudioParams
`kAudioParams` 输入以子对象保存:
```xml
<samplerate>int</samplerate>
<channellayout>uint64</channellayout>
<format>string</format>
<enabled>0|1</enabled>
<streamindex>int</streamindex>
<duration>int64</duration>
<timebase>num/den</timebase>
```
## 7. 部分保存
序列化器支持写出部分数据:
- `<markers>`
- `<keyframes>`
- `<nodes>`(子集)
## 8. OpenFX 插件兼容
- OpenFX 节点 `id` 等于插件标识符。
- `<plugins>` 记录插件路径,加载时会先扫描并注册插件节点。
- 插件缺失时节点无法实例化并被跳过。
## 9. 版本兼容
- 根元素 `version` 决定使用哪个序列化器。
- 若缺少对应版本,会报 `kProjectTooNew``kProjectTooOld`