Skip to content
xiabeePublic

About

本地自动化剪辑工具

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

🎬 XCut

本地优先的自动视频剪辑 / Local-first automatic video editing

用一条确定性流水线把原始素材变成高光成片: 探测 → 分析 → 事件 → 风格 → 时间线 → 渲染 无云端 · 无遥测 · 不依赖 AI

Release License Go Platform Status

English | 中文


✨ 亮点

🖱️ 双击即用 原生桌面窗口(WebView2)承载内嵌 Web UI——不需要 Node、没有构建步骤、没有额外文件
🎞️ 拖放导入 视频文件直接拖进页面,同名不覆盖;也支持本地路径导入
✂️ 可视化时间线 片段色块按时长比例渲染、缩略图、拖动排序、边缘手柄裁剪、转场徽标(cut / fade / xfade)、检查器编辑与快捷键
🏸 懂球的风格引擎 羽毛球 rally 模式:击球驱动的打分、球场 ROI 运动分析、多样性去重;每个片段都带"为什么入选"的解释
🎤 字幕与卡拉 OK 经 AI sidecar 语音转写 → SRT、样式化字幕 ASS,或逐字填充的卡拉 OK ASS,一键烧录进成片
⚡ GPU 加速渲染 render.encoder: auto 自动探测本机硬件编码器(NVENC/AMF/QSV/VAAPI),不可用自动回退 libx264;doctor 报告姿态
🌗 亮暗双主题 跟随系统(auto)/ 暗色 / 亮色手动可切,刷新后回到离开时的工程
🔒 本地优先 仅监听本机回环、无遥测;AI 是可选 sidecar 增强,永远不是地基
📦 资源有界 任务、进程、缓存、临时文件、日志全部有配置上限;空闲约 15 MB 内存、约 0% CPU

目标场景:羽毛球 · KTV · Vlog · 舞台演出 · 体育高光

🚀 快速开始

前置条件:FFmpeg + ffprobe(PATH 上有,或设置 XCUT_FFMPEG / XCUT_FFPROBE;或放在 exe 旁边;仓库 checkout 里 gate 同款的 .tools/ffmpeg 也会被兜底找到)。

方式一:下载预编译版本(推荐)

到 Releases 下载:

  • Windows 安装包 xcut-*-windows-setup.exe(约 6 MB)—— 双击安装, 含开始菜单/桌面快捷方式与卸载器;无人值守安装请显式选作用域: xcut-...-setup.exe /CURRENTUSER /VERYSILENT /DIR=D:\XCut (不给作用域时安装器会让你在"仅当前用户/所有用户"之间选,脚本会卡在那一步);
  • Windows 免安装 zip(含 QUICKSTART.txt)—— 解压后双击 xcut.exe;
  • Linux/macOS 下载对应平台的静态二进制。Linux 侧 FFmpeg 需自行安装 (一键安装目前只覆盖 Windows)。银河麒麟 V10 SP1 注意:该机自带的 FFmpeg 会把海思 OMX 解码插件日志写到 stdout,污染 ffprobe 的 JSON 输出, 导致导入失败;把 XCUT_FFMPEG / XCUT_FFPROBE 指向一个标准构建即可, 已在真机验证全链路(导入→分析→时间线→渲染)通过。该机 4.2.2 构建还 不含 xfade 滤镜,所以 generic_xfade 风格在它上面渲染不了——换 generic_highlight 或装完整构建(渲染失败信息里就是这么说的)。

首次启动会自动检测环境:若缺少 FFmpeg,界面顶栏提供一键安装 (官方构建,经校验和验证后装到 exe 旁的 bin 目录,不会静默捆绑)。 AI 字幕等能力由你自行配置本地后端(设置 workers.ai_bin 或把 xcut-ai 放到 PATH),应用只提供接口、绝不自行下载模型。

方式二:从源码构建

构建需要 Go 1.25+:

git clone https://github.com/xiabee/XCut.git && cd XCut
go build -o xcut ./cmd/xcut          # Windows 下产出 xcut.exe

# 环境自检
./xcut doctor

一条龙出片

./xcut auto my-video.mp4 --project first-run --style generic_highlight

# 比赛素材可以一条命令走完:--score-crop 是画面里记分牌的区域
# (0..1 归一化坐标,不是像素),analyze 时把比分变化量成得分点,
# 片段就正好在得分点结束。--duration 想要的成片秒数。
./xcut auto match.mp4 --project match --style badminton_highlight --duration 240 --score-crop 0.43,0.78,0.14,0.10
./xcut auto talk.mp4 --project talk --style beat_shortform --subs=on   # 先补时间线,再转写字幕(按前者的画布排版),最后渲染

# 成片落在工作区的工程目录里:
#   ~/.xcut/projects/<project-id>/render.mp4  (或你传的 --out 路径)

用任意播放器或 ffprobe 验证结果。

分步执行

./xcut init                                   # 创建 ~/.xcut 工作区
./xcut project create badminton-2026          # 新建工程
./xcut import badminton-2026 match.mp4        # 探测 + 指纹入库
./xcut analyze badminton-2026                 # 运动/音频特征 → 事件
./xcut roi badminton-2026 --asset <id> --set 0.1,0.1,0.5,0.6
#   可选:为单个素材框定球场运动区域(0..1 归一化坐标);羽毛球风格
#   生成时间线时按它裁掉场外干扰。`xcut roi <project>` 列出、`--clear`
#   清除;UI 侧栏"框选球场 ROI…"保存的是同一份数据
./xcut boundaries badminton-2026 --crop 0.43,0.78,0.14,0.10
#   可选:把画面里"烧录"的记分牌区域读成得分点边界(需要 AI sidecar,
#   见 `xcut doctor`)。存进该素材,时间线会让片段正好在得分点结束;
#   UI 侧栏把区域类型选成"记分牌区域"写入的是同一份数据,下一次
#   `analyze` 负责测量
./xcut timeline badminton-2026 --style badminton_highlight
#   重新生成会覆盖手动编辑——上一版文档保留为 timeline.backup.json;
#   `--restore-backup` 可以换回来
./xcut render badminton-2026 --out cut.mp4
./xcut jobs badminton-2026                    # 任务历史(崩溃安全)

🖥️ Serve(本地 Web UI + HTTP API)

./xcut client     # 原生桌面窗口(WebView2)承载内嵌 UI
./xcut serve      # 同一套 UI 跑在浏览器 http://127.0.0.1:8619

创建工程,把视频文件拖进页面(或用"选择文件…"按钮)或填本地路径导入, 然后带着实时任务进度跑 分析 → 时间线 → 渲染——渲染出的 MP4 直接在 页面里播放。编辑工作区是一条真正的时间线:片段按时长比例渲染成色块并带 客户端截取的缩略图,接缝显示可编辑的转场徽标(cut / fade / xfade), 色块可拖动排序,边缘手柄可裁剪,检查器编辑所选片段的裁剪、速度、音量、运镜与 转场(Delete 移除、Space 播放、Ctrl+S 保存)。逐片段预览跟随标尺播放头。 文档声明了卡点网格时(beat_bpm+beat_phase,音乐床胜出或唯一素材网格),标尺会画出节拍刻度——位置由服务端按每个片段自身的裁剪与速度映射到输出时间,可点击跳转;文档没声明网格就不画,绝不从 BPM 编造相位。 工程还能通过 AI sidecar 把语音转写成字幕并烧录进成片(普通 SRT 或 卡拉 OK 式逐字填充的 ASS),球场 ROI 直接在帧上框选。UI 是内嵌进二进制 的原生 HTML/JS(go:embed):不需要 Node、没有构建步骤、没有额外文件。 设计文档:docs/CLIENT_DESIGN.md。

xcut web UI:一个已导入素材的工程、四个成功任务,渲染的高光正在 结果面板中播放

HTTP API 一览(/api/v1,仅本机回环)
curl http://127.0.0.1:8619/api/v1/health
curl http://127.0.0.1:8619/api/v1/projects
curl -X POST http://127.0.0.1:8619/api/v1/projects -d '{"name":"new-project"}'
curl -X POST http://127.0.0.1:8619/api/v1/projects/<id>/assets -d '{"path":"D:/videos/clip.mp4"}'
curl -X POST "http://127.0.0.1:8619/api/v1/projects/<id>/assets/upload?filename=clip.mp4" --data-binary @clip.mp4  # 内容上传(拖放导入的落点;8 GiB/文件)
curl -X POST http://127.0.0.1:8619/api/v1/projects/<id>/render -d '{}'
curl -X POST http://127.0.0.1:8619/api/v1/jobs/<jobID>/cancel            # 取消排队/运行中的任务(202;终态 409)
curl http://127.0.0.1:8619/api/v1/projects/<id>/assets/<assetID>/file   # 片段预览(支持 range)
curl -X POST http://127.0.0.1:8619/api/v1/projects/<id>/subtitles -d '{}'  # 经 AI sidecar 语音转写(202 + 任务)
curl http://127.0.0.1:8619/api/v1/projects/<id>/subtitles               # 查询已有字幕产物
curl -X POST http://127.0.0.1:8619/api/v1/projects/<id>/render -d '{"subs": true}'  # 把字幕烧录进成片
curl -X POST http://127.0.0.1:8619/api/v1/projects/<id>/export -d '{"style":"beat_shortform","music":"D:/music/bed.mp3","subs":true}'  # 一键成片:补时间线→补字幕→排队渲染(202 + 步骤清单)
curl -X PUT  http://127.0.0.1:8619/api/v1/projects/<id>/assets/<aid>/roi -d '{"x":0.1,"y":0.1,"w":0.5,"h":0.6}'  # 每源球场 ROI

异步任务端点返回 202 与 job_id;轮询 GET /api/v1/jobs/{id}。 每个工程同时只允许一个 analyze/timeline/render 任务排队或运行——重复 触发返回 409(导入永不去重)。活动任务在 Web UI 里有取消按钮; CLI 运行(在你自己的终端里同步执行)用 Ctrl+C 取消。 仅监听本机回环是设计决定:xcut serve 拒绝任何非回环地址,除非你 同时显式开启 server.listen_remote 并配置 server.auth_token(见 docs/SECURITY.md 与 docs/DECISIONS.md D12)。

远程访问(可选):给非本机对端加一道 bearer token
# 1. 生成一个足够强的 token(≥24 字符,太短会被直接拒绝启动)
$tok = (openssl rand -hex 24)
# 2. 写进 <workspace>/config.json(或设环境变量 XCUT_AUTH_TOKEN)
#    {"server":{"listen":"0.0.0.0:8619","listen_remote":true,"auth_token":"..."}}
./xcut serve   # 启动行会写明当前姿态:loopback only / remote bind, authentication required
curl -H "Authorization: Bearer $tok" http://<主机IP>:8619/api/v1/health
  • 本机回环对端始终可信:桌面客户端、双击启动的 exe、xcut client 都不需要 token。
  • token 只能来自配置文件或环境变量,不是命令行参数(否则进入进程列表与 shell 历史)。
  • xcut config show 里 token 显示为 <set>,xcut init 写出的默认配置也不落盘它。
  • 密码学上是常量时间比较;失败按对端计数(5 分钟 20 次后转 429)。
  • 判定只看 socket 地址,Host/X-Forwarded-For 一律不参与。
  • 传输是明文 HTTP:请放在可信内网或 Tailscale/SSH 隧道里,不要用同机反向代理 套一层 TLS——那会让所有远端都变成"本机回环"从而绕过鉴权(SECURITY.md 有详细说明)。
  • Web UI 可远程使用:浏览器给 <video src>、缩略图和下载链接挂不上请求头, 所以首次登录(用 bearer 令牌证明)后换发一个 HttpOnly; SameSite=Strict 会话 cookie 供读取使用;写入仍必须把会话 id 回显在 X-Cut-Session 头里——跨站页面读不到 HttpOnly cookie,也就无法伪造这个回显,CSRF 因此在 结构上不成立(D14)。令牌本身不落盘,刷新页面不会重复索要。
  • 会话是内存态:TTL 12 小时、上限 256 个、重启即全部失效,DELETE /api/v1/session 或界面右上角的"退出登录"可立即撤销。
  • 运行手册(实测过的 SSH 隧道配方与它把鉴权交给了谁、401/403/429 各代表什么、 备份范围、轮换与撤销步骤):docs/OPERATIONS.md。

🎨 风格(Styles)

风格是数据而非代码——internal/style/presets/ 里的受校验 JSON 预设 (内嵌),可被 <workspace>/styles/ 覆盖:

  • generic_highlight —— 运动/音频均衡打分
  • generic_xfade —— 类似 generic_highlight,但接缝用真正的交叉淡化(xfade)
  • ktv_mv —— 音频主导(歌声/能量),按 onset 密度加权,音乐场景用更长片段
  • badminton_highlight —— 重运动的 rally 模式:onset 密度聚类带迟滞 (真实球场音频从不安静——环境声会让检测器在每个间隙持续触发)、 击球驱动打分、球场 ROI 运动分析

风格里的 target_duration 只是默认:单次生成可以用 xcut timeline/auto --duration <秒>(或界面风格旁的"成片时长(秒)")临时 覆盖,绝不回写预设文件。之所以值得调这个而不是继续调参数——在真实比赛的 标注上量过:60s 成片最多只能覆盖 473s 回合时间里的 12.7%,把目标放到 240s 能覆盖 18/43 个回合(召回 0.112→0.289),精度只降约 7 个点(详见 docs/EVAL.md)。

针对球场区域运动分析,Web UI 可以直接在工程素材的某一帧上框选感兴趣 区域(侧栏"框选球场 ROI…");保存为该素材自己的区域 (GET/PUT/DELETE /api/v1/projects/{id}/assets/{aid}/roi),时间线生成 时覆盖所选风格的 per-preset 区域——每个固定机位的球场位置都可以不同, 没有自己区域的素材回退到风格设置。风格级区域走 GET/PUT/DELETE /api/v1/styles/{name}/roi。

同一处下拉还能选"记分牌区域":它只写下意图 (GET/PUT/DELETE /api/v1/projects/{id}/assets/{aid}/score),下一次 analyze 才会通过 AI sidecar 把它测成得分边界并存回素材;时间线让片段在 最近的可达边界处结束。区域一改,旧测量就被丢弃(不会静默复用)。实测: 在有烧录记分牌的那场比赛上,精度 0.886 → 0.998,同样的 21 条片多覆盖 2 个回合(docs/EVAL.md)。

每个入选片段都在元数据里携带得分、分项与入选原因——Web UI 会展示每段 的"为什么"。

Web UI 支持中英文:顶栏选择器即时切换,偏好持久化,首次访问自动跟随 浏览器语言(零依赖——以英文字符串为键的纯 JSON 词典,Go 测试防漂移)。

✂️ 时间线与渲染

渲染器严格按校验后的时间线执行:cut、fade(经黑场)与 xfade (真正交叉淡化)可在同一条时间线内自由混用;逐片段 speed 对视频与 音频同时生效。不支持的结构(音轨、多轨时间线、片段特效)会被响亮拒绝 而非悄悄丢弃。输出经 ffprobe 校验后原子发布;若 --out 会覆盖任何源 素材,渲染直接拒绝。

渲染是片段级并行的:片段之间相互独立,渲染器按 resource.max_ffmpeg_processes 同时归一化多个片段(fps 重采样放在 缩放之前,59.94→30 fps 时省掉一半像素重采样),再流拷贝拼接。实测 一条 120 s / 15 片段的成片:串行 105 s → 4 槽位 43 s(2.4×), 画面逐帧等价(docs/PERFORMANCE.md)。CPU 编码与 NVENC 在并行下持平 ——瓶颈在源解码;调高 max_ffmpeg_processes 即可继续吃多核。

🎤 字幕(KTV/吉他弹唱)

语音转文字是 AI 能力,因此遵循 sidecar 规则:核心绝不运行或下载模型。 参考 sidecar(scripts/xcut-ai-sidecar.py)探测本机安装的 Whisper 后端 ——openai-whisper、faster-whisper(pip install faster-whisper)或 whisper.cpp 的 whisper-cli——没有安装时如实报告不可用;装好任意一个, 能力即刻点亮,XCut 零改动。然后:

./xcut subtitles song.mp4 --ass        # 转写 → 样式化 ASS(有词级时间戳则卡拉 OK,否则字幕;默认 SRT)
./xcut render proj --subs lyrics.ass   # 把字幕烧录进成片(音频流直拷)

在 Web UI 里同样的链路就是一个按钮:转写(选素材)→ 状态 + 下载链接 → 勾选"烧录字幕"→ 渲染。时间线面板还多一个 ★ 一键成片:它沿用页面上已选好的参数(风格、时长、底乐、卡点),把补时间线 → 补字幕 → 排队渲染并成一个任务,并逐步告诉你每一步是沿用、新建,还是跳过了(以及为什么)。词级时间戳驱动卡拉 OK 填充(每个字随演唱扫过; sidecar 文本会被转义,杂散花括号或换行无法破坏 ASS 事件);没有词级 时间戳时产出同一套版式、同一套换行与停留时间的普通字幕 ASS——两者共用 一个排版器,差别只是没有填充。SRT 生成后,"预览文本"开关可以内联显示字幕内容。

语义 / 视觉 AI(预留接口)

参考 sidecar 另外支持两个 env 配置的 OpenAI 兼容 HTTP 后端——不捆绑 模型、不静默下载,配置即点亮:

# 语音转写走远程 Whisper 服务器(POST /v1/audio/transcriptions)
export XCUT_SIDECAR_STT_URL="http://127.0.0.1:9000"

# 单帧语义描述(POST /v1/chat/completions,多模态模型)——
# 比赛阶段感知、内容打标等语义信号的接入面
export XCUT_SIDECAR_VISION_URL="https://your-gateway.example:8443"
export XCUT_SIDECAR_VISION_MODEL="vision"
export XCUT_SIDECAR_INSECURE_TLS=1   # 自签证书时

配置后 frame_describe 能力在 sidecar capabilities 里点亮(核心消费 它的流水线属后续工作);XCUT_SIDECAR_TIMEOUT(秒)限制单次 HTTP 调用。

👤 人像过滤(Person Filter)

无 AI 依赖的人物标记:在源视频某一帧上框住自己,分析阶段从这块区域量出 一个 HSV 色签(18×3×3 直方图),presence 扫描按滑动窗口回答"这一帧里 '我'在场的强度"——min_player_presence 风格项据此筛掉你不在场的片段。 播种入口走同一条存储规则,重框即弃旧签名、下次分析按新框重测:

xcut player <project>                                                # 列出各资产的标记状态
xcut player <project> --asset <id> --set x,y,w,h [--at seconds]      # 在视频帧上框选
xcut player <project> --asset <id> --set x,y,w,h --photo me.png      # 在照片上框选,立即量签
xcut analyze <project>                                               # 量取色签(视频框选时)

照片播种的坐标归一化在照片上(与分辨率无关),签名当场量好落库—— 下一次分析直接使用,绝不从视频重测;Web UI 的 Regions 面板同样支持 (画框保存,或"从照片种入"选图拖框,立即出签);评测台 manifest 也能 按 case 播种 player_spot:{x,y,w,h,at},让 min_player_presence 在标注素材上可 A/B。

诚实边界:门槛当前标定在单直方图的 patch-max 标度上;三带(头/躯干/腿) 多区域模型已接入扫描(双轨并行,band 轨等真实素材再标定后才进门), 但本质仍是颜色模型——同色系场景(白衣球员+白墙)会饱和,多人区分属 检测器/re-ID 路线(docs/PERSON_FILTER_ROADMAP.md)。

⚙️ 配置

./xcut config show 打印生效配置;优先级为 默认值 < 配置文件(<workspace>/config.json)< 环境变量(XCUT_*)< CLI 参数。

全部资源/配置旋钮(展示默认值)
键 默认值 含义
workspace ~/.xcut 数据目录(数据库、缓存、临时、工程)
resource.max_concurrent_jobs 2 并行任务硬上限
resource.profile auto 机器自动画像:按逻辑核数/内存自动设定并发与线程(上限 ≈ 半个机器的 CPU 与内存),实测把 2 分钟成片的渲染从 105 s 压到 31 s(docs/PERFORMANCE.md);设为 manual 则下面四个旋钮完全由你说了算
resource.max_ffmpeg_processes auto 探测 并行 ffmpeg/ffprobe 硬上限(同时决定渲染时多少片段并行归一化;profile: manual 时的显式值才会生效)
resource.max_render_workers 1 并发渲染任务的独立上限
resource.max_analysis_workers 2 一次分析同时推进多少个素材(子进程数仍受 max_ffmpeg_processes 限制)
resource.ffmpeg_threads 2 每进程 -threads
resource.ffmpeg_max_memory_mb 1536 单 ffmpeg 进程内存上限(Windows 由 job object 强制;Linux 由 systemd scope 的 MemoryMax 强制,混合 cgroup 的机器上可能不生效,见 docs/OPERATIONS.md;超限 = 编码器因分配失败退出,渲染响亮报错)。实测最贵的正常子进程是 xfade 渲染 566 MB,默认值据此定;0 = 不限,高分辨率渲染可再调高
resource.frame_sample_fps 2 分析采样率
resource.analysis_width 640 分析降采样宽度
resource.proxy_enabled true 生成低分辨率分析代理(重复分析实测快 10–20×;磁盘由 max_proxy_gb 兜住,false 可显式关掉)
resource.max_proxy_gb 2 代理磁盘预算(LRU 逐出)
resource.proxy_threads 继承 一次性代理编码线程(解码受限;调高可缩短冷启动)
resource.analyzer_call_timeout 30m 单分析器 ffmpeg 预算(防挂死)
resource.max_temp_gb / max_cache_gb 20 / 10 磁盘预算
jobs.max_history 500 保留的终态任务行数(随任务完成修剪)
job.stale_running_after 2h CLI 启动孤儿任务对账的年龄门槛
log.level / log.max_size_mb / log.max_files info / 50 / 3 serve 日志轮转
server.listen 127.0.0.1:8619 除 listen_remote 外强制本机回环
server.listen_remote false 允许非回环绑定;必须同时配 auth_token(D12)
server.auth_token (空) 非本机对端的 bearer token,≥24 字符(或 XCUT_AUTH_TOKEN)
workers.audio auto auto/ffmpeg/rust 音频分析器
workers.ai_bin xcut-ai-sidecar AI sidecar 二进制(能力自动探测)
render.encoder auto 成片视频编码器:auto 以真实小编码探测硬件(NVENC/AMF/QSV/VAAPI,按平台排序),全部不可用回退 libx264;也可具名指定。CRF 自动映射 NVENC -cq(实测 +8 齐平);hevc 输出自带 hvc1 标签
ffmpeg.bin / ffmpeg.ffprobe_bin ffmpeg / ffprobe 工具链覆盖(或 XCUT_FFMPEG/XCUT_FFPROBE)

没有任何东西无界运行:任务、进程、缓存、代理、临时文件与日志都有配置 上限。xcut cleanup [--dry-run] 回收临时空间;xcut cache stats|clear 检查并清理分析/代理缓存。

🦀 可选的 Rust worker

Rust worker 加速音频分析,并为所有未来 worker(包括 AI sidecar)验证 进程边界协议。它永远不是必需品:

cargo build --release -p xcut-worker-media
# 然后把 target/release/xcut-worker-media 放上 PATH,或设置:
#   {"workers": {"media_bin": "/path/to/xcut-worker-media", "audio": "auto"}}

auto 模式在 worker 缺失或遇到编解码缺口时自动回退到内置 FFmpeg 分析器。

🛠️ 开发

go build ./... && go vet ./... && go test ./...   # Go 侧
cargo test                                          # Rust 侧(crates/)

测试用 FFmpeg lavfi 现场生成全部媒体 fixture——仓库里没有二进制 fixture。缺少 FFmpeg 时集成测试自动跳过。

架构、决策、安全模型、性能策略都在 docs/:

文档 内容
docs/ARCHITECTURE.md 流水线、边界、worker 协议
docs/DECISIONS.md ADR 日志(为什么是 Go/Rust/SQLite/JSON…)
docs/SECURITY.md 威胁模型与控制措施
docs/PERFORMANCE.md 实测基线
docs/PROJECT_STATE.md 当前真实可用状态
docs/ROADMAP.md 演进方向
docs/USAGE.md 逐命令参考
docs/EVAL.md 选择质量评估(xcut eval)

📦 打包

scripts/build-release.ps1   # Windows(PowerShell 5.1+)
scripts/build-release.sh    # Linux/macOS(bash)

在 dist/ 下产出带版本号的二进制:

产物 平台
xcut(核心 + 内嵌 Web UI) windows/amd64, linux/amd64, linux/arm64
xcut-worker-media(可选) windows/amd64, linux/amd64(静态 musl)

Go 二进制完全静态(无 CGO)——即拷即用。Linux 的 Rust worker 用内置 rust-lld 针对 musl 目标构建,无需平台工具链。

📄 许可证

MIT

About

本地自动化剪辑工具

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages