CapCutAPI 简介
CapCutAPI 是一个基于 Python 的开放式视频编辑 API,它把 剪映/CapCut 桌面版的核心编辑功能 抽象成接口,让开发者可以通过代码来创建、修改和保存视频草稿。
借助 CapCutAPI,你可以:
- 自动化视频编辑:用脚本批量处理视频、图片、音频、字幕,而不必在软件里手工操作。
- 精确控制效果:支持多轨道、关键帧、转场、滤镜、贴纸等编辑功能,像调用函数一样灵活组合。
- 云端/本地无缝衔接:在本地生成草稿文件(
dfd_...
文件夹),直接放入剪映/CapCut 草稿目录后即可继续编辑、导出。 - 扩展 AI 工作流:结合 AI 生成的图像、视频、字幕等,快速构建智能化视频生产流水线。
典型应用场景:
- 批量生成营销/电商短视频
- 将 AI 生成的素材二次编辑为可用成片
- 自动加字幕、标题、贴纸和转场
- 教育、广告、游戏等行业的视频模板化制作
通过 CapCutAPI,视频编辑从“人工点点点”变成了“写代码 + 自动生成”,极大提升了生产效率,非常适合需要 批量化、自动化、可控化 视频生产的团队和个人。
项目教程地址:https://github.com/sun-guannan/CapCutAPI
下面是一份面向 Windows 的完整使用教程,帮你从零到能在剪映直接看到由 CapCutAPI 生成的草稿。步骤短而全,照着做就能跑起来。
一、准备环境(只做一次)
- 安装必需软件
- Python 3.10+(装好后在 PowerShell 里能
python --version
) - FFmpeg(可后装,做转码时更稳)
- Git(可选;你也可以直接下 ZIP)
- 获取项目代码
- 若 ZIP:下载并解压到:
E:\xiangmulist\AI视频\CapCutAPI-main
- 创建 & 激活虚拟环境
cd "E:\xiangmulist\AI视频\CapCutAPI-main"
python -m venv venv-capcut
.\venv-capcut\Scripts\activate
看到命令前缀变成 (venv-capcut)
表示已激活。
- 安装依赖
pip install -r requirements.txt
# 如需 MCP 功能(可选)
pip install -r requirements-mcp.txt
- 复制默认配置
copy config.json.example config.json
保持默认即可(后续需要再改)。
二、启动后端服务(每次使用都要开)
在一个 PowerShell 窗口里(保持不关):
cd "E:\xiangmulist\AI视频\CapCutAPI-main"
.\venv-capcut\Scripts\activate
python capcut_server.py
看到类似:
* Running on http://127.0.0.1:9001
说明服务已 OK。
三、生成一个“示例视频草稿”
我们用直接调用 API的方式(不依赖 example.py
里没有的函数),一键创建草稿 → 加视频 → 加文字 → 保存。
- 新建脚本
ceshi.py
(放在项目根目录):
# ceshi.py
import requests, json
BASE = "http://127.0.0.1:9001"
VIDEO_URL = "https://file-examples.com/storage/fe1e85c1e9a849f7b45f3c4/2017/04/file_example_MP4_480_1_5MG.mp4"
# 1) 创建草稿(竖屏 1080x1920)
r = requests.post(f"{BASE}/create_draft", json={"width":1080, "height":1920}, timeout=60)
r.raise_for_status()
draft_id = r.json()["draft_id"]
print("✅ 创建草稿:", draft_id)
# 2) 添加视频(0~3秒)
r = requests.post(f"{BASE}/add_video", json={
"draft_id": draft_id,
"video_url": VIDEO_URL,
"start": 0,
"end": 3,
"volume": 0.8
}, timeout=120)
r.raise_for_status()
print("✅ 视频添加成功")
# 3) 添加文字(同样 0~3秒)
r = requests.post(f"{BASE}/add_text", json={
"draft_id": draft_id,
"text": "Hello CapCut",
"start": 0,
"end": 3,
"font_size": 64,
"shadow_enabled": True
}, timeout=60)
r.raise_for_status()
print("✅ 文字添加成功")
# 4) 保存草稿(会在 capcut_server 的工作目录生成 dfd_* 文件夹)
r = requests.post(f"{BASE}/save_draft", json={"draft_id": draft_id}, timeout=180)
r.raise_for_status()
print("✅ 草稿已保存:\n", json.dumps(r.json(), ensure_ascii=False, indent=2))
print("\n草稿ID:", draft_id)
- 运行:
cd "E:\xiangmulist\AI视频\CapCutAPI-main"
.\venv-capcut\Scripts\activate
python .\ceshi.py
控制台会打印一个 draft_id(例如 dfd_cat_...
),并在项目根目录生成同名草稿文件夹。
四、让草稿“自动进入剪映草稿目录”
CapCutAPI 默认把草稿生成在服务器当前工作目录(即项目根目录)。为了让剪映能直接看到,我们做一个小网页工具:输入草稿 ID → 自动把 dfd_* 文件夹移动到剪映的草稿目录。
先确认剪映的真实草稿目录:在剪映【草稿】页,任意草稿右上角“···”→ 在文件夹中显示 → 复制这个路径。
假设你的目录是:E:\jianyingcaogao\JianyingPro Drafts
- 在项目根目录新建
web_save_draft.py
:
# web_save_draft.py
# 运行: python web_save_draft.py
# 打开: http://127.0.0.1:5050
from flask import Flask, request, render_template_string
import requests, time, shutil, traceback
from pathlib import Path
# ============ 配置区(按需修改) ============
CAPCUT_API_BASE = "http://127.0.0.1:9001" # capcut_server.py 地址
SERVER_GENERATE_ROOT = Path(r"E:\xiangmulist\AI视频\CapCutAPI-main") # dfd_* 实际生成目录(capcut_server 的工作目录)
SAVE_ROOT = Path(r"E:\jianyingcaogao\JianyingPro Drafts") # 剪映草稿目录(“在文件夹中显示”的结果)
PORT = 5050 # 网页端口
# ==========================================
app = Flask(__name__)
PAGE = """
<!doctype html>
<html lang="zh">
<head><meta charset="utf-8"><title>CapCut 草稿保存器</title>
<style>
body{font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif;max-width:900px;margin:32px auto;padding:0 16px}
input{width:420px;padding:8px} button{padding:8px 12px;margin-left:8px}
pre{background:#f6f8fa;border:1px solid #ddd;padding:12px;white-space:pre-wrap}
</style>
</head>
<body>
<h1>CapCut 草稿保存器</h1>
<form method="POST" action="/save">
<input name="draft_id" placeholder="dfd_ 开头的草稿 ID" required>
<button type="submit">保存到剪映目录</button>
</form>
<pre>{{ log }}</pre>
</body>
</html>
"""
def wait_for_folder(path: Path, timeout=45):
t0 = time.time()
while time.time() - t0 < timeout:
if path.exists() and path.is_dir():
return True
time.sleep(0.5)
return False
def log_lines(lines):
return render_template_string(PAGE, log="\n".join(lines))
@app.route("/", methods=["GET"])
def index():
return log_lines([
"就绪:请输入草稿 ID。",
f"CAPCUT_API_BASE = {CAPCUT_API_BASE}",
f"SERVER_GENERATE_ROOT = {SERVER_GENERATE_ROOT}",
f"SAVE_ROOT = {SAVE_ROOT}",
])
@app.route("/save", methods=["POST"])
def save():
lines = []
def L(s): lines.append(s)
draft_id = (request.form.get("draft_id") or "").strip()
L(f"输入的 draft_id: {draft_id}")
L(f"CAPCUT_API_BASE: {CAPCUT_API_BASE}")
L(f"SERVER_GENERATE_ROOT: {SERVER_GENERATE_ROOT}")
L(f"SAVE_ROOT (剪映目录): {SAVE_ROOT}")
if not draft_id.startswith("dfd_"):
L("❌ 草稿 ID 必须以 dfd_ 开头。")
return log_lines(lines)
# 1) 触发保存(让服务器生成/更新 dfd_*)
try:
L("调用 /save_draft ...")
r = requests.post(f"{CAPCUT_API_BASE}/save_draft", json={"draft_id": draft_id}, timeout=300)
L(f"/save_draft 状态码: {r.status_code}")
try:
L(f"/save_draft 返回: {r.json()}")
except Exception:
L(f"/save_draft 文本: {r.text[:500]}")
r.raise_for_status()
except Exception as e:
L(f"❌ 请求 capcut_server 失败: {e}")
return log_lines(lines)
# 2) 在生成目录定位草稿
src = SERVER_GENERATE_ROOT / draft_id
L(f"预期生成路径: {src}")
if not wait_for_folder(src, timeout=45):
L("未在预期路径看到草稿,兜底扫描 SERVER_GENERATE_ROOT 下最新 dfd_* ...")
candidates = sorted(SERVER_GENERATE_ROOT.glob("dfd_*"), key=lambda p: p.stat().st_mtime, reverse=True)
L(f"候选数量: {len(candidates)}")
if not candidates:
L("❌ 没有找到任何 dfd_* 文件夹。请核对 SERVER_GENERATE_ROOT,或让 capcut_server 在该目录运行。")
return log_lines(lines)
src = next((p for p in candidates if p.name.startswith(draft_id)), candidates[0])
L(f"采用候选: {src}")
if not src.exists():
L(f"❌ 仍未找到草稿: {src}")
return log_lines(lines)
# 3) 准备目标(剪映目录)
dst = SAVE_ROOT / src.name
try:
SAVE_ROOT.mkdir(parents=True, exist_ok=True)
probe = SAVE_ROOT / "_write_probe.tmp"
probe.write_text("ok", encoding="utf-8")
probe.unlink(missing_ok=True)
L("剪映目录写入测试:OK")
except Exception as e:
L(f"❌ 剪映目录不可写:{e}")
return log_lines(lines)
if dst.exists():
L("目标已存在,删除旧目录 ...")
shutil.rmtree(dst, ignore_errors=True)
# 4) 先尝试移动,失败则复制
try:
L("执行移动 shutil.move(src, dst) ...")
shutil.move(str(src), str(dst))
moved = True
except Exception as e:
L(f"移动失败:{e}")
L("尝试复制 shutil.copytree(src, dst) ...")
traceback.print_exc()
shutil.copytree(src, dst)
moved = False
L(f"✅ 已写入剪映目录(操作:{'move' if moved else 'copy'})")
L(f"在剪映草稿页查看:{dst.name}")
return log_lines(lines)
if __name__ == "__main__":
app.run(host="127.0.0.1", port=PORT, debug=False)
- 启动网页保存器(在另一个窗口,保持后端服务不关):
cd "E:\xiangmulist\AI视频\CapCutAPI-main"
.\venv-capcut\Scripts\activate
python .\web_save_draft.py
打开浏览器访问:http://127.0.0.1:5050
把刚才 ceshi.py
打印的 draft_id 粘进去,点【保存到剪映目录】。页面会显示详细日志。成功后,打开剪映 → 草稿,就能看到新项目。
五、(可选)一键启动脚本
start_server.bat
(双击启动后端服务)
@echo off
cd /d E:\xiangmulist\AI视频\CapCutAPI-main
call .\venv-capcut\Scripts\activate.bat
python capcut_server.py
start_web.bat
(双击启动网页保存器)
@echo off
cd /d E:\xiangmulist\AI视频\CapCutAPI-main
call .\venv-capcut\Scripts\activate.bat
python web_save_draft.py
六、常见问题排查
- 浏览器打开根路径 404? 正常,因为根路由没定义;用 POST 接口或网页保存器就行。
- 保存成功但剪映看不到:
- 用“在文件夹中显示”确认剪映真实草稿目录,
SAVE_ROOT
要与之匹配; - 检查目录层级:
...\JianyingPro Drafts\dfd_xxx\
里直接是draft_info.json / draft_settings / assets
等; - 刷新剪映,必要时重启;
- 草稿名必须
dfd_
开头且文件夹名别改。
- 用“在文件夹中显示”确认剪映真实草稿目录,
- 素材没下载成功: 换成公开可直连的 mp4 链接(教程里已提供)。
- 移动失败: 脚本会自动回退“复制”;若还不行,检查杀毒/权限,用管理员 PowerShell 重试。
- 端口被占用: 改后端或网页的端口(例如 9002/5051),并同步脚本里的地址。
七、你之后的“日常流程”(最短路径)
- 双击
start_server.bat
(开后端); - 双击
start_web.bat
(开网页保存器); - 运行你的业务脚本生成草稿(或直接在网页里输入已有
draft_id
); - 打开网页
http://127.0.0.1:5050
→ 输入草稿 ID → 一键保存到剪映; - 打开剪映 → 草稿,继续编辑/导出。