首页
/ Kdenlive CLI-Anything 接线器实战:用 JSON 项目状态驱动 MLT XML 的命令行非线性剪辑工作流

Kdenlive CLI-Anything 接线器实战:用 JSON 项目状态驱动 MLT XML 的命令行非线性剪辑工作流

2026-09-08 22:24:30作者:幸俭卉

Kdenlive 是知名的开源非线性视频编辑器,而 CLI-Anything 生态的做法是给它套一层"Agent 原生"的命令行外壳:本项目中的 Kdenlive CLI harness 把"建项目、导素材、排时间线、加特效、做转场、标记向导、导出工程"全流程收敛为一组有状态、可撤销的 CLI 命令,并把工程状态持久化为 JSON、在导出阶段生成 Kdenlive/MLT 可识别的 XML。读完本文你将掌握:如何零 GUI 依赖地建立剪辑工程、如何用命令流完成从素材入库到渲染导出的完整 SOP,以及其底层 JSON 模型、撤销机制与 MLT XML 生成原理,从而把视频剪辑接入自动化脚本或 Agent 流水线。

本文以 KDENLIVE.md(Standard Operating Procedure)为骨架,并结合该目录下 cli_anything/kdenlive 包的真实源码、README.mdsetup.py 做纵深展开。

一、项目定位与整体架构

Kdenlive CLI harness 提供一个有状态(stateful) 的命令行接口,用于非线性视频剪辑。与一次性工具不同,它在你与终端交互过程中始终维护一个"当前工程"的会话状态,每一次变更都以 JSON 形式落在工程对象上,最终能够输出合法的 Kdenlive/MLT XML 供渲染或进一步加工。

从其源码结构与 README.md 的架构图可以归纳出以下设计要点:

  • JSON 工程格式:所有剪辑状态(素材库 bin、轨道、剪辑片段、特效、转场、向导、元数据)都以 JSON 存储,易于查看、diff 与程序化生成;
  • MLT XML 导出:由 JSON 生成带 Kdenlive 元数据的合法 MLT XML(.kdenlive 文件),可被 Kdenlive 或 melt 打开渲染;
  • 零二进制依赖:剪辑工程编辑与 XML 生成不需要安装 Kdenlive 或 melt,仅依赖 Python 标准库与 click;
  • Undo/Redo:所有修改操作通过会话历史与深拷贝快照实现完整撤销/重做;
  • 时间码支持:底层提供秒(float)与 HH:MM:SS.mmm 时间码的互转,并进一步支持秒与帧的换算。

二、环境准备与安装

按照 KDENLIVE.md 的说明,进入 harness 目录并安装依赖即可:

cd /root/cli-anything/kdenlive/agent-harness
pip install click

需要指出的是,这只满足"编辑工程 + 生成 XML"的最小需求。若要以包的方式安装并获得命令行入口,可使用该目录下的 setup.py

pip install -e .

setup.py 中明确了运行前提:Python >= 3.10,运行时依赖 click>=8.0.0prompt-toolkit>=3.0.0,并注册了控制台入口:

cli-anything-kdenlive=cli_anything.kdenlive.kdenlive_cli:main

安装后有两种等价的调用方式:

调用方式 场景
cli-anything-kdenlive <子命令>... 已安装包后的标准入口
python3 -m cli_anything.kdenlive <子命令>... 在源码树中直接运行(__main__.py 透传 main()

提示:Kdenlive/melt 只有在"打开并渲染 XML"环节才需要;仅做工程编辑、导入导出时完全不需要,这也正是该 harness 适合服务器端与 Agent 调用的原因。

三、核心工作流:从零到导出的七步 SOP

下面把 KDENLIVE.md 的核心工作流逐步展开,并补充源码可验证的参数细节。

第 1 步:创建工程(project new)

cli-anything-kdenlive project new --name "MyProject" --profile hd1080p30 -o project.json

--profile 缺省时不会报错——project.pycreate_project() 允许以 --width/--height/--fps-num/--fps-den 直接定义自定义分辨率与帧率。若传入 --profile,则整组宽高、帧率、逐行/隔行与显示宽高比都会被预设覆盖;传入未知 profile 名会抛出 ValueError 并列出可用项。

KDENLIVE.md 列出的可用 profile 在 project.pyPROFILES 字典中逐一落地,展开后如下表:

Profile 分辨率 帧率(fps) 扫描方式 宽高比
hd1080p30 1920×1080 30 逐行 16:9
hd1080p25 1920×1080 25 逐行 16:9
hd1080p24 1920×1080 24 逐行 16:9
hd1080p60 1920×1080 60 逐行 16:9
hd720p30 1280×720 30 逐行 16:9
hd720p25 1280×720 25 逐行 16:9
hd720p60 1280×720 60 逐行 16:9
4k30 3840×2160 30 逐行 16:9
4k60 3840×2160 60 逐行 16:9
sd_ntsc 720×480 30000/1001(≈29.97) 隔行 4:3
sd_pal 720×576 25 隔行 4:3

创建成功后,工程对象包含 versionnameprofilebintrackstransitionsguidesmetadata 八个顶层字段(详见下文"JSON 工程格式"一节)。

第 2 步:导入素材到素材库(bin import)

cli-anything-kdenlive --project project.json bin import /path/to/video.mp4 --name "Main" -d 120.0
cli-anything-kdenlive --project project.json bin import /path/to/audio.wav --name "Music" -d 180.0 --type audio

bin import 支持 clip 类型(--type)为:video、audio、image、color、titlekdenlive_cli.py),其中:

  • --name/-n:素材在 bin 中的显示名,缺省会基于 source 推导;
  • --duration/-d:素材时长(秒),供 XML 生成时计算 producer/chain 的 lengthout
  • 未指定 source 的抽象类型(如 color/title)也可通过该命令登记,XML 侧会按类型选择 mlt_service(如 color 类型映射为 color producer,见 mlt_xml.py)。

对应 bin 组的完整子命令为:importremovelistget,分别负责入库、移除、列表与详情查询。

第 3 步:搭建时间线(timeline)

先添加轨道,再把 bin 中的素材按位置放到轨道上:

# 添加轨道
cli-anything-kdenlive --project project.json timeline add-track --type video
cli-anything-kdenlive --project project.json timeline add-track --type audio

# 放置片段:轨道 0 上放 clip0,起点 0s,出点 30s
cli-anything-kdenlive --project project.json timeline add-clip 0 clip0 --position 0 --out 30.0

# 裁剪 / 切割 / 移动
cli-anything-kdenlive --project project.json timeline trim 0 0 --in 5.0 --out 25.0
cli-anything-kdenlive --project project.json timeline split 0 0 10.0
cli-anything-kdenlive --project project.json timeline move 0 0 5.0

kdenlive_cli.py 可以看到各子命令的完整签名:

  • add-track--type 只能取 video|audio,另有 --name--mute--hide--locked 用于设置轨道属性,这些属性在 XML 导出的 tractor hide 属性中被体现;
  • add-clip <track_id> <clip_id>--position(时间轴位置,秒,默认 0)、--in/--out(剪辑片段自身的入出点,秒);
  • trim <track_id> <clip_index>:修改某一片段的 --in/--out
  • split <track_id> <clip_index> <split_at>:在给定时间点把片段一分为二;
  • move <track_id> <clip_index> <new_position>:平移片段;
  • remove-trackremove-cliplist 对应删除与查看。

注意所有 position/in/out/split_at 均以为单位的浮点数录入工程对象。

第 4 步:添加滤镜与特效(filter)

# 亮度提升 30%
cli-anything-kdenlive --project project.json filter add 0 0 brightness -p level=1.3
# 双向模糊
cli-anything-kdenlive --project project.json filter add 0 0 blur -p hblur=5 -p vblur=5

KDENLIVE.md 列出的可用滤镜为:brightness、contrast、saturation、blur、fade_in_video、fade_out_video、fade_in_audio、fade_out_audio、volume、crop、rotate、speed、chroma_key。这 13 个滤镜并非空壳,在 filters.pyFILTER_REGISTRY 中每个都定义了 MLT 底层服务、分类与参数规格(类型/默认值/范围),add_filter 会先做参数白名单与取值范围校验(越界即抛 ValueError),然后把带默认值的完整参数写入片段。各滤镜参数展开如下:

滤镜 MLT 服务(mlt_service) 参数(类型,默认值,范围)
brightness brightness level(float,1.0,0~5)
contrast brightness level(float,1.0,0~5)
saturation avfilter.eq saturation(float,1.0,0~3)
blur boxblur hblur/vblur(int,2,0~100)
fade_in_video brightness(kdenlive_id=fade_from_black) duration(float,1.0,0.01~60)
fade_out_video brightness(kdenlive_id=fade_to_black) duration(float,1.0,0.01~60)
fade_in_audio volume(kdenlive_id=fadein) duration(float,1.0,0.01~60)
fade_out_audio volume(kdenlive_id=fadeout) duration(float,1.0,0.01~60)
volume volume gain(float,1.0,0~10)
crop crop left/right/top/bottom(int,0,0~9999)
rotate affine angle(float,0.0,-360~360)
speed timewarp(kdenlive_id=speed) speed(float,1.0,0.01~100)
chroma_key frei0r.select0r color(str,#00ff00)、variance(float,0.15,0~1)

命令层同时提供 filter remove <track> <clip> <index>filter set <track> <clip> <index> <param> <value>(对已有滤镜改参数并复校验范围)、filter listfilter available [--category]

第 5 步:添加转场(transition)

# 在轨道 0 与轨道 1 之间加 dissolve 转场,位置 5s、持续 2s
cli-anything-kdenlive --project project.json transition add dissolve 0 1 -p 5.0 -d 2.0

可用转场类型为:dissolve、wipe、slide、composite、affine。由 transitions.pyTRANSITION_TYPES 可见其底层实现与服务绑定:

类型 MLT 服务 说明与关键参数
dissolve luma 叠化;duration(默认 1s)、softness(0~1)
wipe luma 擦拭;resource(擦除图资源)、softness
slide affine 滑动;direction(默认 left)
composite composite 合成叠加;fill/aligned(0/1)
affine affine 仿射变换;distort(0/1)

transition add 内部会校验:轨道必须存在、track_a != track_b、position 非负、duration 为正,未知参数会直接拒绝(transitions.py)。配套命令还有 transition remove <id>transition set <id> <param> <value>(其中 position/duration 是顶层字段,可单独设置)、transition list

第 6 步:添加向导/标记(guide)

cli-anything-kdenlive --project project.json guide add 30.0 --label "Scene 2"

在 30 秒处放置一个带标签的向导点。guide add 的完整参数还包括 --typedefault|chapter|segment,默认 default)与 --comment(附加注释)。删除与查看对应 guide remove <guide_id>guide list。向导在导出 XML 时会被序列化到 sequence 的 kdenlive:sequenceproperties.guides 属性中(mlt_xml.py),回到 Kdenlive 时间轴上依然可见。

第 7 步:导出 XML 并渲染

# 生成供 Kdenlive/melt 使用的 MLT XML
cli-anything-kdenlive --project project.json export xml -o output.kdenlive

# 本机装有 Kdenlive 时直接打开
kdenlive output.kdenlive

export xml 把 JSON 工程转换为 XML 字符串,指定 -o 则落盘并回显路径与字节大小;不指定时直接打印到标准输出(便于管道处理)。渲染预设信息可用 export presets 查看,export.py 内置了 8 种常见目标:

预设名 视频/音频编码 容器
h264_hq libx264 / aac(8M/192k) mp4
h264_fast libx264 / aac(4M/128k) mp4
h265_hq libx265 / aac mp4
webm_vp9 libvpx-vp9 / libvorbis webm
prores prores_ks / pcm_s16le mov
lossless ffv1 / flac mkv
gif gif(无音频) gif
audio_only 无视频 / pcm_s16le wav

说明:当前仓库的 CLI 完成"工程 JSON → XML 工程文件"的职责;真正渲染仍需借助 Kdenlive/melt 打开产物执行(这也是 setup.py 描述中注明 "Requires: melt" 的原因),渲染预设则服务于后续自动化调用的编码选择。

四、会话管理:Undo/Redo 与自动保存

所有修改类操作(import、add-track、add-clip、trim、split、move、filter、transition、guide)在执行前都会先 sess.snapshot(...),因此整条工作流天然可回退:

cli-anything-kdenlive --project project.json session undo
cli-anything-kdenlive --project project.json session redo
cli-anything-kdenlive --project project.json session history
cli-anything-kdenlive --project project.json session status

session.py 的实现要点(可作为工程事实引用):

  • 深拷贝快照snapshot()copy.deepcopy 保存当前工程的完整状态,附带操作描述与 ISO 时间戳压入 _undo_stack
  • 容量上限MAX_UNDO = 50,超出时从队首弹出最旧快照;
  • redo 语义:执行新的修改会清空 _redo_stackundo() 会把当前态作为 redo 点,redo() 与之对称;
  • 锁定的原子写盘_locked_save_json() 在 POSIX 下通过 fcntl.flock 加独占锁后 seek(0)+truncate()+dump,避免多进程并发写坏工程文件(session.py);
  • 一次性命令自动保存cli 组通过 result_callback(auto_save_on_exit,见 kdenlive_cli.py)在每次一次性命令结束后,若会话被修改且配置了 --project 路径,就自动落盘——无需手动 project save。这一行为也可用全局开关 --dry-run 关闭,便于预览不落盘。

session status 会输出是否载入工程、工程路径、dirty 标记以及 undo/redo 栈深度,方便 Agent 在每一步确认状态。

五、机器可读输出:全局 --json

为便于脚本与 Agent 消费,所有命令都支持全局 --json 标志(在 cli 组上定义,kdenlive_cli.py):

cli-anything-kdenlive --json --project project.json bin list
cli-anything-kdenlive --json --project project.json timeline list

开启后,普通输出函数 output() 改为打印 json.dumps(data, indent=2, default=str);错误路径同样结构化——FileNotFoundErrorValueError/IndexError/RuntimeErrorFileExistsError 分别被包装为带 type 字段的 JSON error 对象(如 {"error": "...", "type": "file_not_found"},见 kdenlive_cli.py),在 REPL 中错误则不会导致进程退出。这让上层 Agent 可以用统一 schema 解析成功与失败结果,而无需抓取人类可读文案。

六、JSON 工程格式详解

工程文件本质是一个自描述的 JSON 文档。README.md 给出了结构样例,结合 project.py 可以确认各字段的取值语义:

{
  "version": "1.0",
  "name": "my_video",
  "profile": {
    "name": "hd1080p30", "width": 1920, "height": 1080,
    "fps_num": 30, "fps_den": 1, "progressive": true,
    "dar_num": 16, "dar_den": 9
  },
  "bin": [
    {"id": "clip0", "name": "Interview", "source": "/path/to/video.mp4",
     "duration": 120.5, "type": "video"}
  ],
  "tracks": [
    {"id": 0, "name": "V1", "type": "video", "mute": false, "hide": false,
     "locked": false, "clips": [
       {"clip_id": "clip0", "in": 0.0, "out": 30.0, "position": 0.0, "filters": []}
     ]}
  ],
  "transitions": [],
  "guides": [],
  "metadata": {}
}

各字段说明:

字段 含义 备注
version 工程格式版本 当前常量 "1.0"PROJECT_VERSION
profile 工程参数 name/width/height/fps_num/fps_den/progressive/dar_num/dar_den
bin 素材库列表 每个素材含 id/name/source/duration/type
tracks 时间线轨道 id/name/type(video
tracks[].clips[] 轨道上的剪辑实例 clip_id 引用 bin 中素材、in/out 为素材内裁剪区间、position 为时间轴位置、filters 为该实例专属特效链
transitions 轨道间转场 见第 3.5 节字段
guides 向导标记 position/label/type/comment
metadata 元信息 created/modified 时间戳与 software 标识,保存时自动刷新

这种"bin 只存一次素材、timeline 片段通过 clip_id 引用"的设计让 JSON 保持归一化、易 diff,也方便程序化批量修改。可用 project json 直接输出当前工程原始 JSON,或 project info 查看聚合摘要(profile 的 fps 计算、bin/tracks/transition/guide 计数等,见 project.py)。

七、交互式 REPL:无需反复敲 --project

除了逐条一次性命令,CLI 还支持交互式 REPL,加载工程后进入提示符逐行输入,省去每次都带 --project

cli-anything-kdenlive repl --project project.json
# 在 REPL 内直接输入:
#   bin list
#   timeline list
#   export xml -o out.kdenlive
#   quit

REPL 逻辑见 kdenlive_cli.py:它基于 prompt-toolkit 建立补全会话,用 shlex.split 解析输入行后以 standalone_mode=False 递归调用 cli.main(args);未加载工程时若执行 project new 亦可现场建工程。内置的 help 会打印各命令组速查表,quit/exit/q 退出,遇到 EOFError/KeyboardInterrupt 同样优雅退出。不传任何子命令直接运行 cli-anything-kdenlive 也会进入 REPL(kdenlive_cli.py)。

八、MLT XML 生成原理(源码级)

export xml 的底层是 mlt_xml.pybuild_mlt_xml(),它对 Kdenlive 生成器 5(Gen 5 / doc version 1.1)兼容文档有系统性地构建,值得关注的关键点包括:

  • profile 元素:把 JSON profile 换算为 MLT 的宽高、逐行标记、帧率与像素宽高比(SAR = DAR × height / width),colorspace 固定 709;
  • 轨道排序:音频轨在前、视频轨在后(audio_tracks + video_tracks),保证视频轨在 Kdenlive 中位于视觉上层(mlt_xml.py);
  • 一轨两 playlist:每个轨道用 chain(素材 producer)+ 双 playlist(一个放条目、一个预留空位给 mix)+ 包裹 tractor 的 Kdenlive 标准结构;轨道 hide 属性按音频/视频、mute/hide 状态推导为 both/video/audio
  • 滤镜落点:片段级滤镜直接挂在 playlist entry 的 <filter> 上,写入 mlt_service 与从 FILTER_REGISTRY 反查的 kdenlive_id(保证在 Kdenlive UI 中显示正确的特效名),参数逐个以 <property> 落盘(mlt_xml.py);
  • 内部转场:音频轨自动补 mix、视频轨自动补 qtblendalways_active 内部转场,用户添加的 dissolve/wipe 等则落在 sequence tractor 上并换算为帧坐标的 in/out/a_track/b_track
  • kdenlive 元数据:sequence 携带大量 kdenlive:sequenceproperties.*(时长、轨道数、缩放、zone、guides JSON 等),最终 project tractor 为 melt 播放的入口,并回写 kdenlive:docproperties.* 的 version/uuid/open sequences。

同时,时间换算工具 seconds_to_timecode() / timecode_to_seconds() / seconds_to_frames() / frames_to_seconds() 都集中在 mlt_xml.py:秒与 HH:MM:SS.mmm 时间码、秒与帧之间的转换被统一到这里,导出 XML 时所有时间点都以帧整数写入,保证与 profile 帧率一致、无浮点漂移。

九、测试与验证

harness 自带双层级测试,位于 cli_anything/kdenlive/tests

cd /root/cli-anything/kdenlive/agent-harness

# 运行全部测试
python3 -m pytest cli_anything/kdenlive/tests/ -v

# 仅单元测试(仓库文档标注 60+ 用例,覆盖核心状态模型)
python3 -m pytest cli_anything/kdenlive/tests/test_core.py -v

# 仅端到端测试(仓库文档标注 40+ 用例,覆盖完整建工程→导出链路)
python3 -m pytest cli_anything/kdenlive/tests/test_full_e2e.py -v

源码目录还附带 tests/TEST.md 与供 Agent 直接消费的 skills/SKILL.md,后者把命令组整理为面向 Agent 的分组速查(Project/Bin/Timeline/Filter/Transition/Guide/Export/Session),便于将 harness 能力一键接入 cli-anything 的技能体系。

十、关键文件索引

文件(仓库相对路径) 职责
kdenlive/agent-harness/KDENLIVE.md 官方 SOP 操作手册(本文骨架来源)
kdenlive/agent-harness/cli_anything/kdenlive/kdenlive_cli.py 主 CLI 入口(click 组、REPL、全局 --json/--project/--dry-run、自动保存)
kdenlive/agent-harness/cli_anything/kdenlive/main.py python3 -m cli_anything.kdenlive 模块入口
kdenlive/agent-harness/cli_anything/kdenlive/core/project.py 工程创建/打开/保存/信息/11 个 profile 预设
kdenlive/agent-harness/cli_anything/kdenlive/core/bin.py 素材库管理
kdenlive/agent-harness/cli_anything/kdenlive/core/timeline.py 轨道与片段(增删改/裁剪/分割/移动)
kdenlive/agent-harness/cli_anything/kdenlive/core/filters.py 13 个滤镜注册表与参数校验
kdenlive/agent-harness/cli_anything/kdenlive/core/transitions.py 5 类转场管理
kdenlive/agent-harness/cli_anything/kdenlive/core/guides.py 向导/标记管理
kdenlive/agent-harness/cli_anything/kdenlive/core/export.py XML 生成入口与 8 个渲染预设
kdenlive/agent-harness/cli_anything/kdenlive/core/session.py 会话/撤销重做/加锁保存
kdenlive/agent-harness/cli_anything/kdenlive/utils/mlt_xml.py MLT XML 构建器与时间码换算
kdenlive/agent-harness/setup.py 打包配置与 cli-anything-kdenlive 入口

结语:适合自动化与 Agent 的剪辑后端

KDENLIVE.md 的 SOP 可以看到,Kdenlive CLI harness 的价值不在于替代 GUI,而是把剪辑决策抽象成可审计、可撤销、可机器读取的命令序列:JSON 即工程真相,XML 导出即交付物,--json 即机器接口。无论是定时渲染流水线、批量字幕压制前处理,还是由 Agent 依据剧本脚本自动编排的多机位粗剪,都可以在完全不触碰图形界面的前提下完成工程搭建,再把 .kdenlive 交给 Kdenlive/melt 完成最终渲染。若需进一步把该 harness 注册为 Agent 技能,可参考同仓库 skills/README 与各 skill 目录的组织方式。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
927
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.89 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
602
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
396
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
526