【开源剪映小助手】架构设计

架构设计

目录

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

引言

本项目"capcut-mate"是一个面向剪映(CapCut)的自动化辅助系统,提供草稿管理、媒体素材处理、特效与字幕集成、以及视频导出能力。系统采用前后端分离策略:后端为基于 FastAPI 的 Web API,前端为 Electron 桌面应用,二者通过 IPC 和 HTTP 协议进行交互;同时系统支持容器化部署,便于在云渲染场景中运行。

项目结构

项目采用模块化分层组织:

  • 后端服务层:FastAPI 应用、路由层、中间件、服务层、工具与配置
  • 剪映自动化层:基于 UI 自动化库的剪映控制模块
  • 前端桌面应用:Electron 主进程、预加载脚本、IPC 处理器、React 前端
  • 配置与资源:OpenAPI 描述、Docker 配置、模板与贴纸配置
  • 测试与工具:测试用例、ffprobe 工具

#mermaid-svg-UToowtGF7zjTmz4I{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UToowtGF7zjTmz4I .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UToowtGF7zjTmz4I .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UToowtGF7zjTmz4I .error-icon{fill:#552222;}#mermaid-svg-UToowtGF7zjTmz4I .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UToowtGF7zjTmz4I .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UToowtGF7zjTmz4I .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UToowtGF7zjTmz4I .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UToowtGF7zjTmz4I .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UToowtGF7zjTmz4I .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UToowtGF7zjTmz4I .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UToowtGF7zjTmz4I .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UToowtGF7zjTmz4I .marker.cross{stroke:#333333;}#mermaid-svg-UToowtGF7zjTmz4I svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UToowtGF7zjTmz4I p{margin:0;}#mermaid-svg-UToowtGF7zjTmz4I .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UToowtGF7zjTmz4I .cluster-label text{fill:#333;}#mermaid-svg-UToowtGF7zjTmz4I .cluster-label span{color:#333;}#mermaid-svg-UToowtGF7zjTmz4I .cluster-label span p{background-color:transparent;}#mermaid-svg-UToowtGF7zjTmz4I .label text,#mermaid-svg-UToowtGF7zjTmz4I span{fill:#333;color:#333;}#mermaid-svg-UToowtGF7zjTmz4I .node rect,#mermaid-svg-UToowtGF7zjTmz4I .node circle,#mermaid-svg-UToowtGF7zjTmz4I .node ellipse,#mermaid-svg-UToowtGF7zjTmz4I .node polygon,#mermaid-svg-UToowtGF7zjTmz4I .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UToowtGF7zjTmz4I .rough-node .label text,#mermaid-svg-UToowtGF7zjTmz4I .node .label text,#mermaid-svg-UToowtGF7zjTmz4I .image-shape .label,#mermaid-svg-UToowtGF7zjTmz4I .icon-shape .label{text-anchor:middle;}#mermaid-svg-UToowtGF7zjTmz4I .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UToowtGF7zjTmz4I .rough-node .label,#mermaid-svg-UToowtGF7zjTmz4I .node .label,#mermaid-svg-UToowtGF7zjTmz4I .image-shape .label,#mermaid-svg-UToowtGF7zjTmz4I .icon-shape .label{text-align:center;}#mermaid-svg-UToowtGF7zjTmz4I .node.clickable{cursor:pointer;}#mermaid-svg-UToowtGF7zjTmz4I .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UToowtGF7zjTmz4I .arrowheadPath{fill:#333333;}#mermaid-svg-UToowtGF7zjTmz4I .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UToowtGF7zjTmz4I .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UToowtGF7zjTmz4I .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UToowtGF7zjTmz4I .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UToowtGF7zjTmz4I .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UToowtGF7zjTmz4I .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UToowtGF7zjTmz4I .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UToowtGF7zjTmz4I .cluster text{fill:#333;}#mermaid-svg-UToowtGF7zjTmz4I .cluster span{color:#333;}#mermaid-svg-UToowtGF7zjTmz4I div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UToowtGF7zjTmz4I .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UToowtGF7zjTmz4I rect.text{fill:none;stroke-width:0;}#mermaid-svg-UToowtGF7zjTmz4I .icon-shape,#mermaid-svg-UToowtGF7zjTmz4I .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UToowtGF7zjTmz4I .icon-shape p,#mermaid-svg-UToowtGF7zjTmz4I .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UToowtGF7zjTmz4I .icon-shape .label rect,#mermaid-svg-UToowtGF7zjTmz4I .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UToowtGF7zjTmz4I .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UToowtGF7zjTmz4I .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UToowtGF7zjTmz4I :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 部署与配置
后端服务
前端桌面应用
desktop-client/main.js

Electron主进程
desktop-client/preload.js

预加载桥接
desktop-client/nodeapi/ipcHandlers.js

IPC处理器
desktop-client/web/*

React前端
desktop-client/web/src/services/electronService.js

Electron服务封装
main.py

应用入口
src/router/v1.py

路由与API
src/middlewares/prepare.py

准备中间件
src/middlewares/response.py

响应中间件
src/service/*

业务服务
config.py

配置常量
src/pyJianYingDraft/jianying_controller.py

剪映自动化
Dockerfile

镜像构建
docker-compose.yaml

容器编排
openapi.yaml

API规范

核心组件

  • 应用入口与中间件
    • 应用入口负责创建 FastAPI 实例、注册路由与中间件,并启动服务。
    • 准备中间件在请求到达时创建草稿与临时目录,保证运行时文件系统就绪。
    • 统一响应中间件负责将业务响应标准化为统一格式,并集中处理异常与 422 参数校验。
  • 路由与 API
    • 路由层提供 v1 版本的完整 API,覆盖草稿创建/保存、媒体添加、特效/字幕/贴纸、时间线计算、草稿查询、视频生成与状态查询等。
    • OpenAPI 规范定义了各接口的请求/响应模型与示例。
  • 服务层
    • 服务层封装具体业务逻辑,调用底层工具与剪映自动化模块,返回标准化结果。
  • 剪映自动化
    • 剪映控制器通过 UI 自动化库与剪映窗口交互,支持草稿查找、导出流程控制、分辨率/帧率设置、导出完成检测与文件移动等。
  • 配置与部署
    • 配置文件集中管理路径、下载 URL、提示 URL、模板与 COS 存储等。
    • Dockerfile 与 docker-compose.yaml 提供容器化部署方案,支持挂载输出目录、时区与资源限制。

架构总览

系统采用前后端分离与容器化部署相结合的架构:

  • 前端(Electron + React):提供桌面应用界面,通过 IPC 与主进程通信,实现文件保存、日志、历史记录、URL 检测等功能。
  • 后端(FastAPI):提供 RESTful API,统一处理请求、中间件标准化响应、服务层编排业务逻辑。
  • 自动化层:通过剪映控制器与剪映窗口交互,实现草稿导出自动化。
  • 部署层:Docker 镜像与 Compose 编排,支持挂载输出目录、环境变量配置与资源限制。

#mermaid-svg-0XNUZcqC4DbcLIUU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0XNUZcqC4DbcLIUU .error-icon{fill:#552222;}#mermaid-svg-0XNUZcqC4DbcLIUU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0XNUZcqC4DbcLIUU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0XNUZcqC4DbcLIUU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0XNUZcqC4DbcLIUU .marker.cross{stroke:#333333;}#mermaid-svg-0XNUZcqC4DbcLIUU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0XNUZcqC4DbcLIUU p{margin:0;}#mermaid-svg-0XNUZcqC4DbcLIUU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0XNUZcqC4DbcLIUU .cluster-label text{fill:#333;}#mermaid-svg-0XNUZcqC4DbcLIUU .cluster-label span{color:#333;}#mermaid-svg-0XNUZcqC4DbcLIUU .cluster-label span p{background-color:transparent;}#mermaid-svg-0XNUZcqC4DbcLIUU .label text,#mermaid-svg-0XNUZcqC4DbcLIUU span{fill:#333;color:#333;}#mermaid-svg-0XNUZcqC4DbcLIUU .node rect,#mermaid-svg-0XNUZcqC4DbcLIUU .node circle,#mermaid-svg-0XNUZcqC4DbcLIUU .node ellipse,#mermaid-svg-0XNUZcqC4DbcLIUU .node polygon,#mermaid-svg-0XNUZcqC4DbcLIUU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0XNUZcqC4DbcLIUU .rough-node .label text,#mermaid-svg-0XNUZcqC4DbcLIUU .node .label text,#mermaid-svg-0XNUZcqC4DbcLIUU .image-shape .label,#mermaid-svg-0XNUZcqC4DbcLIUU .icon-shape .label{text-anchor:middle;}#mermaid-svg-0XNUZcqC4DbcLIUU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0XNUZcqC4DbcLIUU .rough-node .label,#mermaid-svg-0XNUZcqC4DbcLIUU .node .label,#mermaid-svg-0XNUZcqC4DbcLIUU .image-shape .label,#mermaid-svg-0XNUZcqC4DbcLIUU .icon-shape .label{text-align:center;}#mermaid-svg-0XNUZcqC4DbcLIUU .node.clickable{cursor:pointer;}#mermaid-svg-0XNUZcqC4DbcLIUU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0XNUZcqC4DbcLIUU .arrowheadPath{fill:#333333;}#mermaid-svg-0XNUZcqC4DbcLIUU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0XNUZcqC4DbcLIUU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0XNUZcqC4DbcLIUU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0XNUZcqC4DbcLIUU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0XNUZcqC4DbcLIUU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0XNUZcqC4DbcLIUU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0XNUZcqC4DbcLIUU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0XNUZcqC4DbcLIUU .cluster text{fill:#333;}#mermaid-svg-0XNUZcqC4DbcLIUU .cluster span{color:#333;}#mermaid-svg-0XNUZcqC4DbcLIUU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0XNUZcqC4DbcLIUU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0XNUZcqC4DbcLIUU rect.text{fill:none;stroke-width:0;}#mermaid-svg-0XNUZcqC4DbcLIUU .icon-shape,#mermaid-svg-0XNUZcqC4DbcLIUU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0XNUZcqC4DbcLIUU .icon-shape p,#mermaid-svg-0XNUZcqC4DbcLIUU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0XNUZcqC4DbcLIUU .icon-shape .label rect,#mermaid-svg-0XNUZcqC4DbcLIUU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0XNUZcqC4DbcLIUU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0XNUZcqC4DbcLIUU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0XNUZcqC4DbcLIUU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 前端桌面应用

Electron + React
IPC桥接

preload.js
主进程

desktop-client/main.js
IPC处理器

nodeapi/ipcHandlers.js
后端API

FastAPI
路由层

src/router/v1.py
服务层

src/service/*
剪映自动化

jianying_controller.py
准备中间件
响应中间件
配置

config.py
容器化部署

Dockerfile/docker-compose.yaml

详细组件分析

后端应用与中间件

  • 应用入口负责:
    • 创建 FastAPI 应用并设置标题与版本
    • 注册 v1 路由与统一前缀
    • 注册准备中间件与统一响应中间件
    • 打印路由信息并启动服务
  • 准备中间件:
    • 在请求到达前创建草稿目录与临时目录,确保文件系统可用
  • 统一响应中间件:
    • 统一成功响应格式(code/message/data)
    • 统一异常处理(自定义异常与通用异常)
    • 特殊处理 422 参数校验错误,提取字段与消息并格式化

"服务层" "路由层" "响应中间件" "准备中间件" "FastAPI应用" "客户端" "服务层" "路由层" "响应中间件" "准备中间件" "FastAPI应用" "客户端" #mermaid-svg-GvCXC5YRvvEQzxRN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GvCXC5YRvvEQzxRN .error-icon{fill:#552222;}#mermaid-svg-GvCXC5YRvvEQzxRN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GvCXC5YRvvEQzxRN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GvCXC5YRvvEQzxRN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GvCXC5YRvvEQzxRN .marker.cross{stroke:#333333;}#mermaid-svg-GvCXC5YRvvEQzxRN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GvCXC5YRvvEQzxRN p{margin:0;}#mermaid-svg-GvCXC5YRvvEQzxRN .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GvCXC5YRvvEQzxRN text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-GvCXC5YRvvEQzxRN .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GvCXC5YRvvEQzxRN .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-GvCXC5YRvvEQzxRN .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-GvCXC5YRvvEQzxRN .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-GvCXC5YRvvEQzxRN #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-GvCXC5YRvvEQzxRN .sequenceNumber{fill:white;}#mermaid-svg-GvCXC5YRvvEQzxRN #sequencenumber{fill:#333;}#mermaid-svg-GvCXC5YRvvEQzxRN #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-GvCXC5YRvvEQzxRN .messageText{fill:#333;stroke:none;}#mermaid-svg-GvCXC5YRvvEQzxRN .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GvCXC5YRvvEQzxRN .labelText,#mermaid-svg-GvCXC5YRvvEQzxRN .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-GvCXC5YRvvEQzxRN .loopText,#mermaid-svg-GvCXC5YRvvEQzxRN .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-GvCXC5YRvvEQzxRN .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GvCXC5YRvvEQzxRN .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-GvCXC5YRvvEQzxRN .noteText,#mermaid-svg-GvCXC5YRvvEQzxRN .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-GvCXC5YRvvEQzxRN .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GvCXC5YRvvEQzxRN .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GvCXC5YRvvEQzxRN .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GvCXC5YRvvEQzxRN .actorPopupMenu{position:absolute;}#mermaid-svg-GvCXC5YRvvEQzxRN .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-GvCXC5YRvvEQzxRN .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GvCXC5YRvvEQzxRN .actor-man circle,#mermaid-svg-GvCXC5YRvvEQzxRN line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-GvCXC5YRvvEQzxRN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "HTTP请求" "进入准备阶段" "创建目录完成" "进入响应处理" "转发请求" "调用业务逻辑" "返回业务结果" "返回响应" "统一格式响应"

路由与服务层

  • 路由层:
    • 提供 v1 版本的完整 API,包括草稿管理、媒体添加、特效/字幕/贴纸、时间线计算、草稿查询、视频生成与状态查询等
    • 每个路由调用服务层执行业务逻辑,并返回 Pydantic 模型定义的响应
  • 服务层:
    • 通过统一的 init.py 暴露所有服务函数,便于路由层按需调用
    • 服务层内部可进一步调用工具模块与剪映自动化模块

#mermaid-svg-OiOYl5ibu9l0In6S{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OiOYl5ibu9l0In6S .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OiOYl5ibu9l0In6S .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OiOYl5ibu9l0In6S .error-icon{fill:#552222;}#mermaid-svg-OiOYl5ibu9l0In6S .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OiOYl5ibu9l0In6S .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OiOYl5ibu9l0In6S .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OiOYl5ibu9l0In6S .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OiOYl5ibu9l0In6S .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OiOYl5ibu9l0In6S .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OiOYl5ibu9l0In6S .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OiOYl5ibu9l0In6S .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OiOYl5ibu9l0In6S .marker.cross{stroke:#333333;}#mermaid-svg-OiOYl5ibu9l0In6S svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OiOYl5ibu9l0In6S p{margin:0;}#mermaid-svg-OiOYl5ibu9l0In6S g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-OiOYl5ibu9l0In6S g.classGroup text .title{font-weight:bolder;}#mermaid-svg-OiOYl5ibu9l0In6S .cluster-label text{fill:#333;}#mermaid-svg-OiOYl5ibu9l0In6S .cluster-label span{color:#333;}#mermaid-svg-OiOYl5ibu9l0In6S .cluster-label span p{background-color:transparent;}#mermaid-svg-OiOYl5ibu9l0In6S .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OiOYl5ibu9l0In6S .cluster text{fill:#333;}#mermaid-svg-OiOYl5ibu9l0In6S .cluster span{color:#333;}#mermaid-svg-OiOYl5ibu9l0In6S .nodeLabel,#mermaid-svg-OiOYl5ibu9l0In6S .edgeLabel{color:#131300;}#mermaid-svg-OiOYl5ibu9l0In6S .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-OiOYl5ibu9l0In6S .label text{fill:#131300;}#mermaid-svg-OiOYl5ibu9l0In6S .labelBkg{background:#ECECFF;}#mermaid-svg-OiOYl5ibu9l0In6S .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-OiOYl5ibu9l0In6S .classTitle{font-weight:bolder;}#mermaid-svg-OiOYl5ibu9l0In6S .node rect,#mermaid-svg-OiOYl5ibu9l0In6S .node circle,#mermaid-svg-OiOYl5ibu9l0In6S .node ellipse,#mermaid-svg-OiOYl5ibu9l0In6S .node polygon,#mermaid-svg-OiOYl5ibu9l0In6S .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OiOYl5ibu9l0In6S .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S g.clickable{cursor:pointer;}#mermaid-svg-OiOYl5ibu9l0In6S g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-OiOYl5ibu9l0In6S g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-OiOYl5ibu9l0In6S .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-OiOYl5ibu9l0In6S .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-OiOYl5ibu9l0In6S .dashed-line{stroke-dasharray:3;}#mermaid-svg-OiOYl5ibu9l0In6S .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-OiOYl5ibu9l0In6S #compositionStart,#mermaid-svg-OiOYl5ibu9l0In6S .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #compositionEnd,#mermaid-svg-OiOYl5ibu9l0In6S .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #dependencyStart,#mermaid-svg-OiOYl5ibu9l0In6S .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #dependencyStart,#mermaid-svg-OiOYl5ibu9l0In6S .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #extensionStart,#mermaid-svg-OiOYl5ibu9l0In6S .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #extensionEnd,#mermaid-svg-OiOYl5ibu9l0In6S .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #aggregationStart,#mermaid-svg-OiOYl5ibu9l0In6S .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #aggregationEnd,#mermaid-svg-OiOYl5ibu9l0In6S .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #lollipopStart,#mermaid-svg-OiOYl5ibu9l0In6S .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S #lollipopEnd,#mermaid-svg-OiOYl5ibu9l0In6S .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-OiOYl5ibu9l0In6S .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-OiOYl5ibu9l0In6S .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OiOYl5ibu9l0In6S .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OiOYl5ibu9l0In6S .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OiOYl5ibu9l0In6S :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "调用"
Router_v1
+create_draft()
+save_draft()
+add_videos()
+add_audios()
+add_images()
+add_sticker()
+add_keyframes()
+add_captions()
+add_effects()
+add_masks()
+add_text_style()
+get_text_animations()
+get_image_animations()
+easy_create_material()
+get_draft()
+gen_video()
+gen_video_status()
+get_audio_duration()
+timelines()
+audio_timelines()
+audio_infos()
+imgs_infos()
+caption_infos()
+effect_infos()
+keyframes_infos()
+video_infos()
+search_sticker()
+get_url()
+str_list_to_objs()
+str_to_list()
+objs_to_str_list()
Service
+create_draft()
+save_draft()
+add_videos()
+add_audios()
+add_images()
+add_sticker()
+add_keyframes()
+add_captions()
+add_effects()
+add_masks()
+add_text_style()
+get_text_animations()
+get_image_animations()
+easy_create_material()
+get_draft()
+gen_video()
+gen_video_status()
+get_audio_duration()
+timelines()
+audio_timelines()
+audio_infos()
+imgs_infos()
+caption_infos()
+effect_infos()
+keyframes_infos()
+video_infos()
+search_sticker()
+get_url()
+str_list_to_objs()
+str_to_list()
+objs_to_str_list()

剪映自动化组件

  • 剪映控制器:
    • 通过 UI 自动化库定位剪映窗口,识别主页、编辑页与导出页状态
    • 支持草稿查找、导出按钮点击、导出设置(分辨率/帧率)、导出完成检测与文件移动
    • 提供状态机与超时控制,确保自动化流程稳定
  • 设计要点:
    • 状态枚举与状态机:导出分辨率、帧率枚举;应用状态与子状态
    • 控件查找器:基于描述与类名的匹配器,提升控件定位稳定性
    • 错误处理:针对未找到控件、超时等异常进行统一处理

#mermaid-svg-YPRCJLh5NXaypNYB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YPRCJLh5NXaypNYB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YPRCJLh5NXaypNYB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YPRCJLh5NXaypNYB .error-icon{fill:#552222;}#mermaid-svg-YPRCJLh5NXaypNYB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YPRCJLh5NXaypNYB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YPRCJLh5NXaypNYB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YPRCJLh5NXaypNYB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YPRCJLh5NXaypNYB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YPRCJLh5NXaypNYB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YPRCJLh5NXaypNYB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YPRCJLh5NXaypNYB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YPRCJLh5NXaypNYB .marker.cross{stroke:#333333;}#mermaid-svg-YPRCJLh5NXaypNYB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YPRCJLh5NXaypNYB p{margin:0;}#mermaid-svg-YPRCJLh5NXaypNYB defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-YPRCJLh5NXaypNYB g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-YPRCJLh5NXaypNYB g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-YPRCJLh5NXaypNYB g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-YPRCJLh5NXaypNYB g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-YPRCJLh5NXaypNYB g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-YPRCJLh5NXaypNYB .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-YPRCJLh5NXaypNYB .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-YPRCJLh5NXaypNYB .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-YPRCJLh5NXaypNYB .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-YPRCJLh5NXaypNYB .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-YPRCJLh5NXaypNYB .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-YPRCJLh5NXaypNYB .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-YPRCJLh5NXaypNYB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YPRCJLh5NXaypNYB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YPRCJLh5NXaypNYB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YPRCJLh5NXaypNYB .edgeLabel .label text{fill:#333;}#mermaid-svg-YPRCJLh5NXaypNYB .label div .edgeLabel{color:#333;}#mermaid-svg-YPRCJLh5NXaypNYB .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-YPRCJLh5NXaypNYB .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-YPRCJLh5NXaypNYB .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-YPRCJLh5NXaypNYB .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-YPRCJLh5NXaypNYB .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-YPRCJLh5NXaypNYB .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YPRCJLh5NXaypNYB .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YPRCJLh5NXaypNYB #statediagram-barbEnd{fill:#333333;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YPRCJLh5NXaypNYB .cluster-label,#mermaid-svg-YPRCJLh5NXaypNYB .nodeLabel{color:#131300;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-YPRCJLh5NXaypNYB .note-edge{stroke-dasharray:5;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-note text{fill:black;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram-note .nodeLabel{color:black;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagram .edgeLabel{color:red;}#mermaid-svg-YPRCJLh5NXaypNYB #dependencyStart,#mermaid-svg-YPRCJLh5NXaypNYB #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-YPRCJLh5NXaypNYB .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YPRCJLh5NXaypNYB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "点击草稿"
"点击导出"
"检测到导出按钮"
"点击最终导出"
"检测到完成按钮"
"关闭完成窗口"
主页
编辑页
导出前置页
导出开始
导出中
导出完成

前端桌面应用与 IPC

  • 主进程:
    • 创建 BrowserWindow,加载开发/生产模式下的 React 应用
    • 初始化 IPC 处理器,暴露文件保存、日志、历史记录、URL 检测等接口
  • 预加载脚本:
    • 通过 contextBridge 暴露安全 API 至渲染进程,封装 IPC 调用
  • IPC 处理器:
    • 实现 save-file、get-download-log、clear-download-log、on-file-operation-log、show-message-box、get-config-data、update-draft-path、open-external-url、check-url-access、get-history-record 等
  • Electron 服务封装:
    • 根据是否在 Electron 环境选择真实 API 或模拟实现,保证浏览器环境下的兼容性

"后端API" "IPC处理器" "Electron主进程" "预加载脚本" "React界面" "后端API" "IPC处理器" "Electron主进程" "预加载脚本" "React界面" #mermaid-svg-oF03NhGB0H9cV4Qt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oF03NhGB0H9cV4Qt .error-icon{fill:#552222;}#mermaid-svg-oF03NhGB0H9cV4Qt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oF03NhGB0H9cV4Qt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oF03NhGB0H9cV4Qt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oF03NhGB0H9cV4Qt .marker.cross{stroke:#333333;}#mermaid-svg-oF03NhGB0H9cV4Qt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oF03NhGB0H9cV4Qt p{margin:0;}#mermaid-svg-oF03NhGB0H9cV4Qt .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-oF03NhGB0H9cV4Qt text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-oF03NhGB0H9cV4Qt .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-oF03NhGB0H9cV4Qt .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-oF03NhGB0H9cV4Qt .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-oF03NhGB0H9cV4Qt .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-oF03NhGB0H9cV4Qt #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-oF03NhGB0H9cV4Qt .sequenceNumber{fill:white;}#mermaid-svg-oF03NhGB0H9cV4Qt #sequencenumber{fill:#333;}#mermaid-svg-oF03NhGB0H9cV4Qt #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-oF03NhGB0H9cV4Qt .messageText{fill:#333;stroke:none;}#mermaid-svg-oF03NhGB0H9cV4Qt .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-oF03NhGB0H9cV4Qt .labelText,#mermaid-svg-oF03NhGB0H9cV4Qt .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-oF03NhGB0H9cV4Qt .loopText,#mermaid-svg-oF03NhGB0H9cV4Qt .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-oF03NhGB0H9cV4Qt .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-oF03NhGB0H9cV4Qt .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-oF03NhGB0H9cV4Qt .noteText,#mermaid-svg-oF03NhGB0H9cV4Qt .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-oF03NhGB0H9cV4Qt .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-oF03NhGB0H9cV4Qt .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-oF03NhGB0H9cV4Qt .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-oF03NhGB0H9cV4Qt .actorPopupMenu{position:absolute;}#mermaid-svg-oF03NhGB0H9cV4Qt .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-oF03NhGB0H9cV4Qt .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-oF03NhGB0H9cV4Qt .actor-man circle,#mermaid-svg-oF03NhGB0H9cV4Qt line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-oF03NhGB0H9cV4Qt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "调用electronService方法" "ipcRenderer.invoke(...)" "ipcMain.handle(...)" "HTTP请求后端API" "返回响应" "返回结果" "返回结果" "更新界面状态"

配置与部署

  • 配置文件:
    • 定义项目根目录、草稿目录、临时目录、下载 URL、提示 URL、贴纸配置路径、模板目录、剪映草稿保存路径、COS 存储配置、API Key 启用开关等
  • Docker 镜像:
    • 基于 Python slim 镜像,使用 uv 安装依赖,暴露 30000 端口,设置环境变量与缓存目录
  • Compose 编排:
    • 暴露 30000 端口,挂载输出目录与时区,设置内存/CPU 限制与 OOM 优先级,支持自动重启

依赖关系分析

  • 组件耦合与内聚
    • 路由层与服务层高内聚,通过 Pydantic 模型解耦请求/响应结构
    • 中间件与路由层低耦合,通过 FastAPI 生命周期管理
    • 剪映自动化模块与服务层松耦合,通过函数调用与异常传播
  • 外部依赖与集成点
    • 剪映自动化依赖 UI 自动化库与操作系统窗口句柄
    • 前端通过 IPC 与主进程通信,主进程与后端 API 交互
    • 容器化部署依赖 Docker 与 Compose,支持挂载与环境变量注入

#mermaid-svg-pJBghvHp4iVX4uXw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pJBghvHp4iVX4uXw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pJBghvHp4iVX4uXw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pJBghvHp4iVX4uXw .error-icon{fill:#552222;}#mermaid-svg-pJBghvHp4iVX4uXw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pJBghvHp4iVX4uXw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pJBghvHp4iVX4uXw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pJBghvHp4iVX4uXw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pJBghvHp4iVX4uXw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pJBghvHp4iVX4uXw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pJBghvHp4iVX4uXw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pJBghvHp4iVX4uXw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pJBghvHp4iVX4uXw .marker.cross{stroke:#333333;}#mermaid-svg-pJBghvHp4iVX4uXw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pJBghvHp4iVX4uXw p{margin:0;}#mermaid-svg-pJBghvHp4iVX4uXw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pJBghvHp4iVX4uXw .cluster-label text{fill:#333;}#mermaid-svg-pJBghvHp4iVX4uXw .cluster-label span{color:#333;}#mermaid-svg-pJBghvHp4iVX4uXw .cluster-label span p{background-color:transparent;}#mermaid-svg-pJBghvHp4iVX4uXw .label text,#mermaid-svg-pJBghvHp4iVX4uXw span{fill:#333;color:#333;}#mermaid-svg-pJBghvHp4iVX4uXw .node rect,#mermaid-svg-pJBghvHp4iVX4uXw .node circle,#mermaid-svg-pJBghvHp4iVX4uXw .node ellipse,#mermaid-svg-pJBghvHp4iVX4uXw .node polygon,#mermaid-svg-pJBghvHp4iVX4uXw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pJBghvHp4iVX4uXw .rough-node .label text,#mermaid-svg-pJBghvHp4iVX4uXw .node .label text,#mermaid-svg-pJBghvHp4iVX4uXw .image-shape .label,#mermaid-svg-pJBghvHp4iVX4uXw .icon-shape .label{text-anchor:middle;}#mermaid-svg-pJBghvHp4iVX4uXw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pJBghvHp4iVX4uXw .rough-node .label,#mermaid-svg-pJBghvHp4iVX4uXw .node .label,#mermaid-svg-pJBghvHp4iVX4uXw .image-shape .label,#mermaid-svg-pJBghvHp4iVX4uXw .icon-shape .label{text-align:center;}#mermaid-svg-pJBghvHp4iVX4uXw .node.clickable{cursor:pointer;}#mermaid-svg-pJBghvHp4iVX4uXw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pJBghvHp4iVX4uXw .arrowheadPath{fill:#333333;}#mermaid-svg-pJBghvHp4iVX4uXw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pJBghvHp4iVX4uXw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pJBghvHp4iVX4uXw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pJBghvHp4iVX4uXw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pJBghvHp4iVX4uXw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pJBghvHp4iVX4uXw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pJBghvHp4iVX4uXw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pJBghvHp4iVX4uXw .cluster text{fill:#333;}#mermaid-svg-pJBghvHp4iVX4uXw .cluster span{color:#333;}#mermaid-svg-pJBghvHp4iVX4uXw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pJBghvHp4iVX4uXw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pJBghvHp4iVX4uXw rect.text{fill:none;stroke-width:0;}#mermaid-svg-pJBghvHp4iVX4uXw .icon-shape,#mermaid-svg-pJBghvHp4iVX4uXw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pJBghvHp4iVX4uXw .icon-shape p,#mermaid-svg-pJBghvHp4iVX4uXw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pJBghvHp4iVX4uXw .icon-shape .label rect,#mermaid-svg-pJBghvHp4iVX4uXw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pJBghvHp4iVX4uXw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pJBghvHp4iVX4uXw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pJBghvHp4iVX4uXw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 路由层
服务层
剪映自动化
中间件
前端桌面应用
IPC桥接
主进程
后端API

性能考量

  • 中间件顺序与开销
    • 准备中间件在请求早期创建目录,避免后续 IO 报错,减少重试成本
    • 统一响应中间件对 JSON 响应进行格式化,建议在高并发场景下关注序列化开销
  • 容器资源限制
    • Compose 中设置内存上限与 CPU 份额,结合 OOM 优先级调整,有助于在多任务场景下稳定运行
  • 剪映自动化
    • 自动化流程包含多次窗口查找与点击,建议在批量导出时增加重试与超时控制,避免长时间阻塞

故障排查指南

  • 常见问题与定位
    • 422 参数校验失败:统一响应中间件会解析 FastAPI 的验证错误并格式化为统一错误响应,检查请求体字段与类型
    • 服务器内部错误:统一响应中间件捕获通用异常并返回标准错误格式,查看日志定位具体异常
    • 剪映窗口未找到:检查剪映是否已安装、版本是否受支持、窗口标题是否匹配
    • IPC 通信异常:确认预加载脚本正确暴露 API,主进程已注册相应 handle,渲染进程通过 electronService 调用
  • 日志与监控
    • 后端日志:中间件与服务层均记录关键事件与错误
    • 前端日志:主进程与渲染进程均可输出日志,便于定位 IPC 与网络问题

结论

capcut-mate 项目通过清晰的分层架构与前后端分离策略,实现了对剪映的自动化控制与 API 服务。后端以 FastAPI 为核心,配合中间件与服务层,提供稳定可靠的接口;前端通过 Electron 与 IPC 实现桌面应用体验;容器化部署简化了运维与扩展。该架构具备良好的可维护性与扩展性,适合在云渲染与本地场景中灵活部署。

附录

  • API 规范参考:OpenAPI 描述文件定义了完整的接口契约与示例,便于客户端对接与测试
  • 前端工程配置:Electron 与 Vite 的组合提供了高效的开发与打包体验

文档信息

相关推荐
用户5191495848451 小时前
Wux Blog Editor 漏洞利用工具 (CVE-2024-9932)
人工智能·aigc
yyuuuzz1 小时前
谷歌云基础服务的入门认知
linux·运维·服务器·数据库·人工智能·github
_code_bear_2 小时前
如何设计 Agent 场景下的 Prompt
程序员·开源·设计
GitCode官方2 小时前
开源鸿蒙跨平台直播|Flutter 鸿蒙化进阶:三方库适配与性能调优实战
flutter·华为·开源·harmonyos·atomgit
码途漫谈2 小时前
Harness:让 Claude Code 先组队,再开工
开源·ai编程
冬奇Lab2 小时前
每日一个开源项目 第124篇:last30days —— 洞察最近30天:跨越信息茧房的 AI Agent 搜索引擎
人工智能·搜索引擎·开源
天丁o2 小时前
开源教程:用飞书长连接把本地 Codex CLI 接入机器人,支持进度心跳和可见过程
机器人·开源·飞书
RuoyiOffice2 小时前
2026 企业定制开发选型:从零开发、低代码、SaaS 与 RuoYi Office 怎么选?
spring boot·uni-app·开源·saas·oa·定制化·ruoyioffice
指针不迷路2 小时前
【Windows安装openclaw,配置qwen模型和ollama本地模型,飞书群组添加机器人】
aigc