Files
capcut-mate/config.py
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

93 lines
4.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目常量定义
import os
# 项目根目录
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
# 保存剪映草稿的目录
DRAFT_DIR = os.path.join(PROJECT_ROOT, "output", "draft")
# 日志目录
LOG_DIR = os.path.join(PROJECT_ROOT, "logs")
# 临时文件目录
TEMP_DIR = os.path.join(PROJECT_ROOT, "temp")
# 视频生成任务完成结果(SQLite 持久化)
VIDEO_GEN_TASK_DB_PATH = os.path.join(PROJECT_ROOT, "db", "video_gen_tasks.sqlite3")
# 视频生成任务:生成视频在 COS 上的可访问保留天数(预签名下载 URL 有效期,环境变量覆盖)
VIDEO_GEN_RETENTION_DAYS = max(1, int(os.getenv("VIDEO_GEN_RETENTION_DAYS", "7")))
# 剪映草稿的下载路径
DRAFT_URL = os.getenv("DRAFT_URL", "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft")
# 将容器内的文件路径转成一个下载路径,执行替换操作,即将/app/ -> https://capcut-mate.jcaigc.cn/
DOWNLOAD_URL = os.getenv("DOWNLOAD_URL", "https://capcut-mate.jcaigc.cn/")
# 草稿提示URL
TIP_URL = os.getenv("TIP_URL", "https://docs.jcaigc.cn/")
# 贴纸配置文件路径
STICKER_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config", "sticker.json")
# 花字配置文件路径
HUAZI_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config", "huazi.json")
# 文字模板配置文件路径
TEXT_TEMPLATE_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config", "text_template.json")
# 气泡配置文件路径
BUBBLE_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config", "bubble.json")
# 发光配置文件路径
GLOW_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config", "glow.json")
# 模板目录路径
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "template")
# 剪映草稿保存路径(下载剪映草稿保存位置)-- 云渲染必需配置
#DRAFT_SAVE_PATH = "C:/Users/Administrator/AppData/Local/JianyingPro/User Data/Projects/com.lveditor.draft"
DRAFT_SAVE_PATH = "C:/Users/1/AppData/Local/JianyingPro/User Data/Projects/com.lveditor.draft"
# 腾讯云对象存储配置(优先)
COS_SECRET_ID = os.getenv("COS_SECRET_ID", "")
COS_SECRET_KEY = os.getenv("COS_SECRET_KEY", "")
COS_BUCKET_NAME = os.getenv("COS_BUCKET_NAME", "")
COS_REGION = os.getenv("COS_REGION", "")
# 阿里云对象存储配置(COS 未配置时作为兜底)
OSS_ACCESS_KEY_ID = os.getenv("OSS_ACCESS_KEY_ID", "")
OSS_ACCESS_KEY_SECRET = os.getenv("OSS_ACCESS_KEY_SECRET", "")
OSS_BUCKET_NAME = os.getenv("OSS_BUCKET_NAME", "")
OSS_ENDPOINT = os.getenv("OSS_ENDPOINT", "")
# 火山引擎 TOS AccessKeyId(COS、OSS 均未配置完整时作为兜底)
TOS_ACCESS_KEY_ID = os.getenv("TOS_ACCESS_KEY_ID", "")
# 火山引擎 TOS AccessKeySecret
TOS_ACCESS_KEY_SECRET = os.getenv("TOS_ACCESS_KEY_SECRET", "")
# TOS 存储桶名称
TOS_BUCKET_NAME = os.getenv("TOS_BUCKET_NAME", "")
# TOS 地域,例如 cn-beijing、cn-shanghai
TOS_REGION = os.getenv("TOS_REGION", "")
# TOS 访问域名(可选,未设置时按地域自动生成,例如 tos-cn-beijing.volces.com)
TOS_ENDPOINT = os.getenv("TOS_ENDPOINT", "")
# 对象存储上传目录前缀(根目录),COS / OSS / TOS 共用。
# 最终 object key 格式:[前缀/]yyyy-MM-dd/文件名;前缀为空时文件落在桶根目录下的日期目录中。
# 首尾多余的 / 会自动去除。
#
# 配置示例(环境变量 STORAGE_UPLOAD_PREFIX):
# 未设置或留空 -> 2026-06-15/video.mp4
# capcut-mate -> capcut-mate/2026-06-15/video.mp4
# prod/capcut-mate -> prod/capcut-mate/2026-06-15/video.mp4
# /capcut-mate/ -> capcut-mate/2026-06-15/video.mp4(与上相同)
STORAGE_UPLOAD_PREFIX = os.getenv("STORAGE_UPLOAD_PREFIX", "")
# APIKEY启用配置-默认启用 -- 云渲染必需配置(环境变量 true / false,大小写不敏感)
ENABLE_APIKEY = os.getenv("ENABLE_APIKEY", "true").strip().lower() == "true"
# 文件下载大小限制(字节),默认200MB
DOWNLOAD_FILE_SIZE_LIMIT = int(os.getenv("DOWNLOAD_FILE_SIZE_LIMIT", str(200 * 1024 * 1024)))