318 Commits
Author SHA1 Message Date
HommyandClaude Code 8fb0a2f438 feat: add_captions 支持自定义描边不透明度与宽度
- 新增接口参数 border_alpha / border_width
- 普通描边与关键词描边共用同一组参数
- 默认值保持原输出,向后兼容
- 新增回归测试并同步中英文文档

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-30 11:54:10 +08:00
HommyandClaude Code b3d01595e2 文字模板支持自带入场动画
- 配置可补录模板资源清单(resources)与入场动画(animation),path 留空由剪映按 resource_id 拉取
- 动画写入片段的 sticker_animation 素材,显式 in_animation 优先于模板动画
- 为“嘎嘎香”模板补录资源与动画数据,并补充测试

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-19 21:58:54 +08:00
HommyandClaude Code 16c442e36f 配置路径内置到使用处,精简 config.py
- 贴纸/花字/文字模板/气泡/发光清单及草稿模板路径改由各模块固定路径加载
- LOG_DIR 与视频任务数据库路径改为模块内计算
- 同步更新相关测试

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-18 21:36:40 +08:00
Hommy 76fbac67bd 优化代码。 2026-10-18 10:15:01 +08:00
Hommy c3c0292708 优化接口提示。 2026-10-18 10:01:27 +08:00
Hommy 885366ce7f 更新数据。 2026-10-18 09:38:57 +08:00
HommyandClaude Code ae3cb76899 余额口径统一:错误消息与交易描述改用余额/元
- 2035 错误消息由「当前积分需大于 1」改为「充值余额需大于 1」,英文同步。
- gen_video 交易描述的费用单位由「积分」改为「元」,注释里的单价与扣费说法同步。
- upload_file 注释删掉「1 积分 = 1 元」的换算说明。
- gen_video / upload_file 文档的错误码表统一为「充值余额不足 / 当前余额」,
  避免文档同步回本站时把旧口径带回。

验证:python3 -m py_compile 通过。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-17 11:47:03 +08:00
HommyandClaude Code b772987d29 add_captions 新增文字背景与文字发光支持,均照剪映草稿实证实现。
两个功能都是剪映字幕面板里的文字装饰效果,用同一份 add_captions 接口暴露,
且都只做接口级(不做逐条覆盖)。

has_background / background_info:文字底下的一层纯色底板。草稿中表现为文本素材
自己的 background_* 字段,同时 check_flag 置第 16 位(7 → 23)。字段名与取值与草稿
一一对应,无需单位换算;唯一例外是偏移量用草稿坐标 [-1, 1](0 居中),而库的构造
函数收 UI 坐标 [0.5 居中],故构造后直接赋值,避免 *2-1 往返引入浮点噪声。背景色
不经 hex_to_rgb——草稿里存的就是 "#RRGGBB" 字符串,非法值会原样落进草稿,故新增
_normalize_hex_color 做宽松校验,非法时回退黑色并告警(而非像 text_color 回退白色)。

text_glow:剪映发光面板的预设(外发光 / 轮廓光)。草稿中表现为 materials.effects 里
一条 type="bloom" 的素材,由片段 extra_material_refs 引用(追加在 sticker_animation
之后),check_flag 置第 64 位(7 → 71)。除 check_flag 外,带发光的文本素材与普通
字幕逐字段完全相同。发光不做优先级:它既不掌管片段的素材身份(那是文字模板的事),
也不改动文字样式(那是花字的事),只是再挂一条素材,故与花字 / 文字模板 / 气泡都
可以叠加,花字叠加时记告警。

pyJianYingDraft 侧改动(文字背景那次库已支持,是纯穿参;发光这次必须动库):
- 新增 TextGlow 素材类与 TextSegment.add_glow(),check_flag 增加第 64 位。
  export_json 写出草稿实证的整套字段,只去掉依赖创建者本机剪映缓存的 path
  (与气泡一致,由剪映按 resource_id 自行拉取)。
- create_from_template 同步携带 glow,否则模板派生的片段会静默丢发光。
- script_file 的 filters 类型提示、add_segment 收集、inspect_material 新增 bloom
  分支(用 .get 兜底,避免第三条 effect["type"] KeyError)。
- __init__ 导出 TextGlow,顺带补上一直漏在 __all__ 外的 TextBubble。

新增 config/glow.json 与 get_text_glows 解析器,结构照抄气泡那套:effect_id 与
resource_id 不是同一个值,故四种写法(名称 / resource_id / effect_id /
"effect_id:resource_id" 显式 ID 对),且不做纯数字透传。清单外发光的 bloom_params
无实证取值,落到默认值并告警——剪映不会按 resource_id 重新推导这些数值。

逐字段对拍参照草稿:背景的 8 个 background_* 字段与 check_flag 与草稿全等;发光的
bloom 素材只有 id(重新生成)与 path(刻意不导出)两个键不同,bloom_params 精确
相等,check_flag 同为 71。文本素材与草稿的 font_path / force_apply_line_max_width /
shadow_point 差异普通字幕也有,与本次改动无关。请求 → schema → router → service →
落盘草稿的全链路实跑通过;字幕相关测试 121 项通过,全量回归与改动前的失败基线
逐行相同(仓库本就有 51 项环境性失败)。

已知事项:两者的渲染效果均未在剪映里实测,文档已按仓库习惯标注;发光草稿里两条
字幕用了不同预设,接口级参数下复刻需调用两次 add_captions。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 19:49:18 +08:00
HommyandClaude Code fe91868049 贴纸配置瘦身:只保留 title/sticker_id/image_url 三个字段。
config/sticker.json 从 58MB / 135 万行降到 22MB / 7.9 万行,79,368 条条目数
与顺序均不变。删掉的字段及依据:

- preview_cover:全部 79,368 条均为空串,零信息。
- sticker_package(含 height_per_frame/size/width_per_frame)与 sticker_type:
  无任何代码读取。add_sticker 完全不读本配置,它只用调用方传入的 sticker_id,
  草稿素材是极简的(id/resource_id/sticker_id/source_platform/type)。
- track_thumbnail:与 large_image 是同一素材的 120×120 与 1920×1920 两种尺寸,
  但签名不同、无法互相推导,本次一并去掉。

保留的三个字段构成检索到使用的完整链路:title 是唯一的搜索键,sticker_id 是
add_sticker 唯一需要的入参,image_url 供调用方展示预览。

顺带把序列化格式改为一条一行(原为 indent=2,每条 4 行),与
config/text_template.json 的大清单一风格一致,便于 diff。

这是对外契约变更:响应由嵌套(sticker.large_image.image_url)改为扁平
(image_url),故同步更新 schemas/search_sticker.py(StickerItem 拉平,
StickerInfo/StickerPackage/LargeImage 三个类删除)、双语文档(含旧版本字段
说明与调用方调整提示)与 openapi.yaml(8 个响应示例 + 响应结构定义)。
service/search_sticker.py 删掉一行死 import:它导入了上述四个类,实际一个都
没用到,删类后会直接 ImportError。

tools/query_sticker.py 新增 flatten_sticker():上游返回的仍是嵌套结构,不转换
的话工具产出的文件与新配置格式对不上;对已是扁平的输入幂等,缺 title/sticker_id
的条目跳过并计数。

无损验证:79,368 条逐条比对 title/sticker_id/image_url 全部一致,条目顺序一致;
openapi.yaml 的 8 个示例同样逐条比对一致。测试 56 项通过(3 个贴纸 + 53 个字幕/
模板/气泡),端到端 SearchStickerResponse 校验通过。

已知事项:image_url 是带签名的临时 URL,有效期至 2026-12-15,到期后预览图失效
(title/sticker_id 不受影响,add_sticker 不依赖该字段),届时需重新抓取。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 18:33:34 +08:00
HommyandClaude Code 3cb4d10213 add_captions 新增 text_bubble 参数,支持剪映气泡字幕。
气泡在剪映数据模型里是第三种文字效果:素材是 materials.effects 中一条
type="text_shape" 的条目,由文本片段的 extra_material_refs 引用(追加在
sticker_animation 之后)。与花字同在 extra_material_refs 且互斥;与文字模板
不同,它不改片段的 material_id,也不重置文字样式。

气泡1 对照样本揭示的关键结构:气泡的 effect_id 与 resource_id 不是同一个值
(草稿中 effect_id="716434"、resource_id="6821385652727190024"),两者缺一剪映
就定位不到资源。因此参数取值支持名称、resource_id、effect_id,以及清单外的
"effect_id:resource_id" 显式 ID 对;纯数字不做透传(无法补全另一半),按未找到
处理并回退普通字幕。清单见 config/bubble.json,id 为 resource_id、effect_id
单独给出(与 text_template.json 里 id 兼作 effect_id 的约定不同)。

优先级 文字模板 > 气泡 > 花字:气泡与花字同属文字效果且互斥,气泡优先并告警;
模板掌管片段素材身份,优先级更高,模板生效时不处理气泡。气泡只提供文字底下的
装饰底板,不像花字那样重置 text_color/border_color/has_shadow——这点由草稿实证:
两条字幕(普通/带气泡)的样式字段完全一致。

气泡素材的名称/分类字段改为已知时写入、未知时保持最小结构,故 TextBubble 原
有的最小导出不变;add_bubble 新增 name/category_id/category_name/extra_material
四个可选关键字参数,extra_material 用于原样覆写本机缓存 path 等本服务无从得知
的字段(与 TextTemplateRef 的设计一致)。

清单目前只收录气泡1 草稿实证过的 1 个气泡,其余气泡靠显式 ID 对传入。速创小助手
的气泡页虽有 326 个气泡的名称与预览图(其名称即剪映气泡名,草稿里的「背景装饰54」
正在其中),但不提供 effect_id/resource_id(该站「特效」页才提供 id 对),故无法
直接批量导入,补齐 id 需在剪映「气泡」面板逐个确认。

未使用气泡时行为零变化:已用 HEAD 代码与改动后代码生成同一批普通字幕草稿(含
关键词高亮/描边/阴影/动画/样式/字体/花字/文字模板)做 UUID 归一化比对,12 个
用例逐字节一致。新增 tests/test_add_captions_text_bubble.py 14 项;字幕回归
套件 53 项通过。

已知限制:气泡素材的 path/request_id 等取决于创建者本机剪映缓存,本服务不导出,
由剪映按 effect_id/resource_id 自行拉取(花字即如此工作,但两者是不同素材类型与
渲染路径,属推断而非实测)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 18:11:51 +08:00
HommyandClaude Code ee7968413a 文字模板清单扩充到 5166 个,重名查找改为确定性命中。
清单取自 font.ai-tools.cn 的文字模板页:该页是 Next.js 应用,数据不打在
HTML 里而是内联在 3.8MB 的 chunk 中(数组 y=[{id,key,name}] 为分类表,
紧随其后的数组为模板表)。用括号计数+正则从压缩后的 JS 里抽出 5166 条模板
与 43 个分类,未匹配残片为 0,无空名、无缺失分类、无未知分类 id。

分类取「第一个非 feed 分类」:11739(最新)/10577(热门) 是列表页的 feed 分类
而非内容分类,3651/3580 条模板同时挂着它们,直接取首个分类会有一大半模板被
归到「最新」。例外是草稿1 实证过的 7383613902744980770——第三方数据把它归到
美食(10692),但剪映写进草稿的是 热门(10577)(key_value.json 的
materialThirdcategoryId 亦为 10577),以草稿为准,用 VERIFIED 常量覆盖。

重名处理由「后写覆盖」改为「先写生效」并计数:清单里 498 条重名,其中「我的
水印」重名 41 条,原来的后写覆盖会让命中哪一条取决于配置顺序且不易察觉。
名称查找现固定命中配置中靠前的一条,日志打印实际可用名称数与忽略数,需要精确
定位时传 effect_id。

id 即 effect_id/resource_id,全部 19 位、前缀 70-76,与草稿1 那个可用 id
(7383613902744980770) 同形同域。

测试新增 4 项:清单完整性与字段非空、抽样按名/按 id 反查一致、重名确定性、
实证模板保留草稿分类。原 8 项与字幕回归套件共 52 项通过。

未能验证的部分:5166 个 id 中只有草稿1 那个有实证,其余无法在剪映侧逐一确认;
且 4735 个为 VIP 模板,未购买时可能不渲染,is_vip 已存入清单供筛选。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 16:11:03 +08:00
HommyandClaude Code 13e4649058 add_captions 新增 text_template 参数,支持剪映文字模板。
文字模板在剪映数据模型里是一种文本片段样式而非新片段类型,故加可选参数
text_template,不新开接口。参数可取模板名称或 effect_id,映射表见
config/text_template.json,不在表中的纯数字直接透传。

草稿1 对照样本揭示的关键结构:套用模板时片段的 material_id 指向
materials.text_templates 中的模板素材,而不是它的文本素材——文本素材只能由
模板的 text_info_resources[].text_material_id 反向找到。因此只在 export_json
里改写 material_id,self.material_id 保持不变,接口返回的 text_ids 仍是文本
素材 id,text_ids ⊂ materials.texts[].id 这一既有不变式对两类字幕都成立。

模板素材不持有 segment 反向引用:create_from_template 与 import_track 的
deepcopy 会让两个片段共享同一个 material id、且 text_material_id 指向旧素材,
改为在 add_segment 时快照 extra_material_refs 与时长。attach_info.clip 发单位
矩阵而非抄 segment 的 clip——样本里那个 5.35°/0.97 是模板自带布局,抄过去会
让用户位移叠加两次。

text_effect 与 text_template 互斥且模板优先:模板掌管片段素材身份、花字掌管
styles[0].effectStyle,同时生效的渲染结果未定义。文字模板不套用花字那套
text_color/border_color/has_shadow 重置,模板配色由模板自身决定。

未使用模板时行为零变化:text_templates 未使用时导出仍是 [],export_material
的改动全部包在 if self.text_template is not None 内。已用 HEAD 代码与改动后
代码生成同一批普通字幕草稿(含关键词高亮/描边/阴影/动画)做 UUID 归一化比对,
逐字节一致。

新增 tests/test_add_captions_text_template.py 8 项;字幕回归套件 48 项通过。

已知限制:模板的 path/resources/装饰贴纸取决于创建者本机剪映缓存,无法在本
服务侧得知,发空值由剪映按 effect_id 自行拉取(花字即如此工作,但两者是不同
素材类型与渲染路径,属推断而非实测);多文本槽模板目前只发一个槽。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-14 16:00:38 +08:00
HommyandClaude Code b4e39e9451 修复 get_draft 错误码不重试,并给下载阶段加总超时。
ResponseMiddleware 把所有非 200 改写成 HTTP 200,真实状态码在 body 的 code 里。
因此 draft_downloader 里按 HTTP 状态判断重试的分支对文件列表请求是死代码,
真实错误全部走 code != 0 分支——而该分支此前立即判死、零重试,服务端 5xx
事实上从未被重试过;desktop-client 则只检查 response.status(恒为 200),
从不看 code,服务端瞬时错误直接弹报错、不重试。

服务端 code != 0 现按信封分类:9998/9999(系统内部错误)与 ≥500 可重试,
业务码 1001-2050 保持立即失败。客户端把信封校验移进 requestGetDraftOnce,
使其落在重试循环内;只挂 apiCode 不挂 response,否则 response.status 恒为
200 会把「服务器返回错误 (200)」当成原因报给用户。

下载阶段新增 5 分钟总预算:读写超时只管单次 socket 读写,慢速滴流能无限续期,
重试预算又逐层相乘,故另设按阶段计时的预算,检查点只在发起新请求之前与 chunk
之间(后者是慢速滴流唯一能拦住的地方)。另修 _download_remote_file_raising
不归还连接的泄漏,并给 robocopy 加 120s 超时。

客户端 ENOTFOUND(NXDOMAIN,对应服务端 Errno 11001)改为 3 次小预算重试,
与服务端 _DNS_RETRY_BUDGET 对齐;ECONNREFUSED 仍不重试。

下载器测试 128 → 144 项。改动了一条既有断言:test_non200_404_does_not_retry
原先写 assert_not_called(),即把「404 分支不归还连接」这个泄漏当成了预期行为。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 21:18:59 +08:00
HommyandClaude Code 0346b20c6a 补齐草稿下载的网络重试覆盖,瞬时故障不再被判死。
线上素材域名解析瞬时失败(Errno 11001)会把整个导出任务判死,而该素材实测
HTTP 200 可正常访问:getaddrinfo failed 被列为永久错误,一次抖动即失败,
且报成「草稿或素材不存在/URL无效」,把排查引向错误方向。现改为小预算快速
重试(3 次),耗尽后归类为网络重试耗尽。

同类缺口一并补齐:HTTP 500(多为 OSS/Nginx 的瞬时内部错误)、
ContentDecodingError(响应体解码失败,不继承 ConnectionError 故被漏掉)、
以及文件列表返回 200 但正文非 JSON(网关截断响应或 HTML 错误页)。

desktop-client 同步将 500 纳入可重试状态,与服务端保持一致;唯一保留的差异是
416,客户端在 resumableDownload 中单独处理续传边界,已在两侧注释中说明。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 18:46:20 +08:00
Hommy b92e8e25f9 解决剪映草稿下载失败,导致渲染失败的问题。 2026-10-09 18:08:11 +08:00
HommyandClaude Code b90e327887 美妆支持剪映全部 54 个套装预设。
新增 tools/extract_makeup_looks.py,从剪映素材面板缓存(get_panel_info,
category_key=taozhuang)导出套装清单,生成 makeup_looks_generated.py
(名称 + resource_id + is_vip,取最新一份完整快照,已下架的不残留)。

美妆目录改由该清单构建,makeup.look 直接传剪映套装中文名即可,
含裸妆、原生、初恋、淡妆公式等;文档补齐 54 个取值与刷新方式。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-06 21:26:10 +08:00
HommyandClaude Code b1a8778b59 修复美妆 face_id 写死人脸序号导致妆容不渲染。
face_id 是剪映检出人脸的序号(0 起),不是妆容自身的槽位:参考草稿里的 "1"
是该视频第 2 张人脸的序号,写死后换素材就会指向不存在的人脸,草稿里素材在、
画面上却没有妆容。现默认写 "-1"(全部人脸,对齐剪映「全局应用」),并支持在
makeup 里用 face_id 指定具体人脸;复用已有素材时同步刷新 meta,使换人脸生效。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-06 21:03:03 +08:00
Hommy 31a521d235 新增加美颜美体接口。 2026-10-06 16:53:33 +08:00
Hommy e6e6cc99ce 新增加文件上传接口。 2026-10-06 11:31:52 +08:00
Hommy fc333a103d 解决语法问题。 2026-09-19 23:12:35 +08:00
Hommy 08a323f9b3 增强美颜接口。 2026-09-19 23:10:42 +08:00
Hommy 67139e8a9b 添加蒙版大小关键帧。 2026-09-19 22:40:04 +08:00
Hommy 5708cc2c6f 新增加蒙版关键帧的接口。 2026-09-19 14:37:09 +08:00
Hommy ddb1ab66e4 添加人像美颜的接口。 2026-09-19 11:56:45 +08:00
Hommy 074652b361 更新导出超时时间为10分钟。 2026-09-09 14:05:36 +08:00
Hommy 126156d5f5 添加设置最大行宽。 2026-09-07 20:13:43 +08:00
Hommy 7972eea573 增加参数:line_max_width,默认值是0.82 2026-09-07 16:57:26 +08:00
Hommy 7850249fc6 解决偶发的文件下载失败的问题。 2026-09-06 22:57:32 +08:00
Hommy b3fc256a07 优化配置。 2026-09-01 09:54:08 +08:00
Hommy c4e4fd0c66 合入pro分支中的关键特性。 2026-09-01 09:46:16 +08:00
Hommy 14956b8405 优化字体兼容性问题。 2026-08-31 16:52:42 +08:00
Hommy 0e9e57efa0 优化字幕兼容性。 2026-08-31 16:42:49 +08:00
Hommy 7cad08774b 解决本地文件下载完成,断点续传失败的问题。 2026-08-24 09:48:50 +08:00
Hommy 3cfbfb54e1 统一重试次数为10次。 2026-08-22 22:07:57 +08:00
Hommy f626d73a2b 优化资源文件下载,增加断点续传的能力。 2026-08-22 21:54:50 +08:00
Hommy 4010029b56 新增加TOS(火山引擎对象存储)实现,配置如下:
# 火山引擎 TOS AccessKeyId(COS、OSS 均未配置完整时作为兜底)
TOS_ACCESS_KEY_ID=
# 火山引擎 TOS AccessKeySecret
TOS_ACCESS_KEY_SECRET=
# TOS 存储桶名称
TOS_BUCKET_NAME=
# TOS 地域,例如 cn-beijing、cn-shanghai
TOS_REGION=
# TOS 访问域名(可选,未设置时按地域自动生成,例如 tos-cn-beijing.volces.com)
TOS_ENDPOINT=

优先级排最后,当COS,OSS都没有配置时,才使用TOS
2026-08-21 12:15:44 +08:00
Hommy 7c7efe860c 添加文字竖排的功能。 2026-08-19 11:12:36 +08:00
Hommy 01c64aaae3 优化积分计数。 2026-08-17 21:35:00 +08:00
Hommy 4357bfb3bb 增加文件下载快速失败,优化云渲染速度。 2026-08-12 14:42:02 +08:00
Hommy 775a003d0d 优化接口提示。 2026-08-09 11:10:22 +08:00
Hommy dc4b342302 Merge branch 'main' of github.com:Hommy-master/capcut-mate 2026-08-06 20:39:01 +08:00
Hommy 3c9136df5c 优化一下,如果keyword_font、keyword_font_size没有传值时,使用正文字幕的字体和大小 2026-08-06 20:38:34 +08:00
Hommy 5958dd811e 更新注释。 2026-08-06 11:20:12 +08:00
Hommy 4194afb182 新增加关键词字体设置。 2026-08-06 09:59:27 +08:00
Hommy 5763a5d182 添加关键词阴影。 2026-08-05 22:17:22 +08:00
Hommy f0e32ca5dc 添加关键词阴影 2026-08-04 14:18:29 +08:00
Hommy 74c6183fe8 统一转场时长的处理方式。 2026-07-20 13:21:56 +08:00
Hommy 0dc6282ce7 优化报错提示。 2026-07-20 13:12:10 +08:00
Hommy 3ba95827a6 草稿下载失败需要做一个区分:
1. 一类是:文件404,提供的URL网络连接不上导致的404错误;
2. 另一类:文件存在,下载过程中,网络抖动导致重试次数耗尽导致的失败;
2026-07-20 10:36:37 +08:00
Hommy 96f36486a9 解决草稿下载失败的问题。 2026-06-22 20:12:28 +08:00