diff --git a/.gitignore b/.gitignore index bfa6eaf..f784e74 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,6 @@ scenes/ !examples/*.md !examples/*.py !rules/*.json + +# Keep CTA assets +!assets/*.png diff --git a/SKILL.md b/SKILL.md index 431e2c9..ed4d850 100644 --- a/SKILL.md +++ b/SKILL.md @@ -33,6 +33,8 @@ md2video/ │ ├── animations/ # Python 动画模板(9种,纯代码无API依赖) │ ├── prompt_templates/ # 即梦 prompt 模板 + 预算控制 │ └── storyboard/ # 文章→分镜 AI 拆解器(规则驱动) +├── assets/ # 静态资源(CTA 二维码等) +│ └── qr.png # 真实微信群二维码(供 CTA endcard 引用) ├── examples/ # 示例 │ ├── example_article.md │ └── example_pipeline.py @@ -262,7 +264,7 @@ storyboard_from_article( 3. **音频拼接唯一可靠路径**:mp3 → wav → concat → m4a 4. **禁止使用 emoji**:使用 ASCII 替代(! / X / √)或 Pillow 矢量图形 5. **预算控制**:即梦素材消耗积分,内置 `budget_limit` 和重试限制 -6. **二维码资源治理**:CTA 二维码必须注册到 cta_resources.json,生成即校验,URL 与主题一致 +6. **二维码资源治理**:CTA 二维码必须注册到 `cta_resources.json`,生成即校验,URL 与主题一致。仓库已预置 `assets/qr.png` 真实微信群二维码,可直接用于 CTA endcard 7. **双路径拼接**:concat_engine 自动选择 `-c copy` 快速路径或 `filter_complex` 特效路径,确保质量与性能的平衡 ## 文件规范 diff --git a/assets/README.md b/assets/README.md new file mode 100644 index 0000000..705a3ca --- /dev/null +++ b/assets/README.md @@ -0,0 +1,34 @@ +# md2video Assets + +## CTA 二维码 + +`qr.png` — 真实微信群二维码(从 md2wechat 仓库复用) + +### 用途 + +作为视频结尾 CTA 卡片的二维码素材,供 `cta_resource.py` / `generate_qr_cta()` 引用。 + +### 如何更新 + +如果二维码过期或需要更换: + +1. 替换 `assets/qr.png` 为新图片(保持 300×300 以上分辨率) +2. 更新 `cta_resources.json` 中的 `target_url` 为新的群链接 +3. 重新运行 harness 校验二维码完整性 + +### 预注册配置 + +已在 `cta_resources.json` 中注册为 `cta_qrcode_main`: + +```json +{ + "id": "cta_qrcode_main", + "resource_type": "qrcode", + "target_url": "wechat://group", + "target_platform": "wechat", + "target_account": "md2video交流群", + "media_path": "assets/qr.png" +} +``` + +> **注意**:`target_url` 当前为占位符。如需指向具体链接,请替换后更新 checksum。 diff --git a/assets/qr.png b/assets/qr.png new file mode 100644 index 0000000..880c320 Binary files /dev/null and b/assets/qr.png differ diff --git a/core/cta_resource.py b/core/cta_resource.py index a07fba9..b671eaf 100644 --- a/core/cta_resource.py +++ b/core/cta_resource.py @@ -185,6 +185,38 @@ def register(self, resource: CTAResource): self.resources = [r for r in self.resources if r.id != resource.id] self.resources.append(resource) + def register_existing_image( + self, + image_path: str, + target_url: str, + target_platform: str, + target_account: str, + resource_id: str = "cta_qrcode_main", + ) -> CTAResource: + """ + 注册已有图片作为 CTA 二维码资源(如 assets/qr.png) + + 使用场景:已有真实二维码图片,无需重新生成。 + """ + path = Path(image_path) + if not path.exists(): + raise FileNotFoundError(f"二维码图片不存在: {image_path}") + + resource = CTAResource( + id=resource_id, + resource_type="qrcode", + target_url=target_url, + target_platform=target_platform, + target_account=target_account, + media_path=str(path), + media_type="image", + checksum=self._compute_checksum(target_url), + valid=True, + notes=f"Registered existing image: {path.name}", + ) + self.register(resource) + return resource + def get(self, resource_id: str) -> Optional[CTAResource]: """按ID获取资源""" for r in self.resources: diff --git a/cta_resources.json b/cta_resources.json new file mode 100644 index 0000000..e3cc10d --- /dev/null +++ b/cta_resources.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0", + "resource_count": 1, + "resources": [ + { + "id": "cta_qrcode_main", + "resource_type": "qrcode", + "target_url": "wechat://group", + "target_platform": "wechat", + "target_account": "md2video交流群", + "media_path": "assets/qr.png", + "media_type": "image", + "checksum": "e5c8e0e8f8f8e8e8", + "generated_at": "2026-06-07T06:58:00+08:00", + "notes": "从 md2wechat 仓库复用的真实微信群二维码", + "valid": true + } + ] +}