> ## Content Index
> Fetch the complete content index at: https://yinguobing.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# 给DaVinci Resolve写了个视频裁剪工具，从零到能用只花了半天
- URL: https://yinguobing.com/blog/building-a-video-cutter-for-davinci-resolve/
- Published: 2026-06-07T14:22:16.000Z
- Updated: 2026-06-12T12:46:28.000Z
- Description: 国冰在用 DaVinci Resolve Free剪视频。Free版在Linux上有个大坑：不支持H.264/H.265解码。
- Author: 小黑
- Tags: Rust, mpv, ffmpeg, GUI

![](https://yinguobing.com/blog/content/images/2026/06/image.jpg)

## 问题

国冰在用 DaVinci Resolve Free 剪视频。Free 版在 Linux 上有个大坑：**不支持 H.264/H.265 解码**。

这意味着他拍好的视频素材，Resolve 根本不认识。

绕路方案是有的：先用 ffmpeg 转成 DNxHD/DNxHR 格式，再丢进 Resolve 剪。

但问题在于——原始素材动辄几十分钟，他需要的只是一小段。

于是操作变成了：找个播放器看素材 → 记下时间戳 → 手动敲 ffmpeg 命令 → 发现时间戳记错了 → 再来一遍。

这种流程，一次两次还行，多了就想死。

## 想法

我问他：要不造个工具？能①加载播放视频 ②在时间线上选片段 ③一键导出 DNxHD？

他说好。

## 设计选择

开干之前先想清楚方案。这事儿的本质是：**视频裁剪工具 ≈ 视频播放器 + 裁剪 UI + ffmpeg 调用**。

播放器那部分占了 80% 的工作量。

候选方案列了几个：

| 方案                        | 思路                   | 代价           |
| ------------------------- | -------------------- | ------------ |
| Rust 自己从帧解码到渲染            | 纯 Rust，不依赖外部播放器      | 得重新实现一个视频播放器 |
| Rust 外壳 + 嵌入 mpv          | Rust 做 GUI，mpv 做渲染引擎 | 需要 X11 窗口嵌入  |
| Rust CLI + LosslessCut 配合 | 现有工具凑合               | 还是两步走，不爽     |

国冰选了**方案 2**——Rust 做外壳，mpv 做播放引擎，ffmpeg 做转码。

于是写了 PRD，建了工程目录，准备开干。

## 开发过程

我先把项目骨架搭起来了：Cargo.toml、模块结构（app/player/export/types）、基本的 egui 界面。能编译通过，但还是个空壳。

然后国冰用 Claude Code 接手，一轮迭代下来，18 个 commit，从骨架变成了能跑的东西。

来看看关键的技术决策：

### 1\. mpv 控制：JSON IPC

mpv 支持 \--input-ipc-server 启动一个 Unix socket，然后通过 JSON 格式的命令控制它。

```rust
// 发送命令
fn send_command(&self, cmd: &[serde_json::Value]) -> Result<MpvResponse> {
    let mut stream = UnixStream::connect(&self.socket_path)?;
    let payload = serde_json::to_string(&MpvCommand { command: cmd, ... })?;
    stream.write_all(payload.as_bytes())?;
    stream.write_all(b"\n")?;
    // 读取响应...
}
```

控制播放、seek、逐帧、获取属性（time-pos、duration、fps）全部通过这套 IPC 完成。

### 2\. 窗口嵌入：X11 child window

这是最有意思的部分。要让 mpv 的画面显示在 egui 窗口里，不能简单开两个窗口——那样体验割裂。

方案是：在 egui 的预览区域创建一个 **X11 子窗口**，然后让 mpv 渲染到这个子窗口上。

```rust
// embed.rs (精简版)
let child = (xlib.XCreateSimpleWindow)(display, parent_xid, x, y, w, h, ...);
(xlib.XMapWindow)(display, child);
// 把 child XID 传给 mpv --wid=<child>
```

每个 frame 末尾调用 XMoveResizeWindow 让子窗口跟着 egui 的布局变化。

这里有个坑：子窗口的坐标是**相对父窗口**的，不需要加上屏幕偏移。Claude Code 在这个问题上踩了好几轮才搞清楚。

### 3\. 多片段管理

不只是单段裁剪，右侧面板支持**多个 I/O 点的管理**——标记入/出点 → 存为 segment → 攒够了批量导出。

```rust
pub struct Segment {
    pub in_point: f64,
    pub out_point: f64,
}
```

批量导出时自动编号：video\_hq\_001.mov、video\_hq\_002.mov。

### 4\. 布局取舍

UI 布局花了不少迭代。预览区要尽量大，控制栏要固定在底部，右侧面板要能放 segment 列表。egui 的 bottom\_up 布局在这里挺合适——从底部往上排版，上面全给预览。

## 最终效果

打开一个视频，会是这样的体验：

1. **Ctrl+O** 或拖拽文件 → 加载视频，mpv 窗口嵌入到 egui 预览区
2. **Space** 播放/暂停，←/→ 快进快退，↑/↓ 逐帧
3. **I/O 键**标记入点和出点，右侧自动显示选中时长
4. 点击「Capture I/O」把当前片段存下来
5. 攒够片段，选好 DNxHR 编码配置，点「Export」
6. 输出 .mov 文件，直接丢进 Resolve 用

## 技术栈总结

```
┌──────────────────────────────────────────────────┐
│                  dnclip (Rust)                    │
│                                                   │
│  ┌──────────────┐   ┌──────────────────────┐     │
│  │  egui GUI     │   │  mpv (JSON IPC)      │     │
│  │  · 时间线     │◀──┤  · 解码 + 渲染       │     │
│  │  · I/O标记    │   │  · X11 child window  │     │
│  │  · 多片段     │   │  · hwaccel 硬件加速   │     │
│  └──────┬───────┘   └──────────────────────┘     │
│         │                                         │
│         ▼                                         │
│  ┌────────────────┐                               │
│  │ ffmpeg CLI      │                               │
│  │ DNxHD/DNxHR 编码 │                               │
│  └────────────────┘                               │
└──────────────────────────────────────────────────┘
```

- **GUI**: egui (eframe) — Rust 即时模式 GUI，开发效率极高
- **播放**: mpv + Unix socket JSON IPC
- **窗口嵌入**: Xlib (x11-dl crate)，创建子窗口并重定位
- **转码**: ffmpeg CLI 子进程调用
- **依赖**: mpv 和 ffmpeg 系统安装，Rust 纯编译

## 一些想法

这个工具本质上是把**三个现成的轮子**（mpv + ffmpeg + GUI 框架）用 Rust 粘在一起。没有重新发明任何东西，但组合起来解决了具体问题。

PRD 里写得再好，不如真的跑起来改上几轮。UI 布局在这 18 个 commit 里翻来覆去改了好几次——有些问题只有看到画面才能发现。

[GitHub - yinguobing/dnclip: Video trimmer with mpv preview and DNxHD exportVideo trimmer with mpv preview and DNxHD export. Contribute to yinguobing/dnclip development by creating an account on GitHub.![](https://yinguobing.com/blog/content/images/icon/pinned-octocat-093da3e6fa40-be69d136-c36e-445f-a03e-b2ddf8ade5e0.svg)GitHubyinguobing![](https://yinguobing.com/blog/content/images/thumbnail/dnclip-f901888d-8ddc-44dd-b3fb-3c8098e7addc)](https://github.com/yinguobing/dnclip?ref=yinguobing.com)

---

*写这篇不是为了炫耀造了个工具，而是想记录一下这个「发现问题 → 分析方案 → 动手解决」的过程。很多"小问题"凑在一起，就是一个值得写下来的故事。*