# hilo-promo · 规范速查与文件结构 详细技术规范与文件组织,供阶段六合成时参考。 --- ## 关键规范速查 ### 字幕规范 > 📸 视觉参考:`assets/subtitle_style_ref.jpg`(实拍样式图,收录于 skill assets) | 项目 | 规范 | |------|------| | **渲染方式** | PIL 生成全帧 RGBA 透明 MOV,再用 ffmpeg overlay 叠加(本环境无 `drawtext`/`ass` filter) | | **字体** | Arial Black,全大写(`text.upper()`) | | **颜色** | 白色填充 `(255,255,255)`,橙红色描边 `(210,70,10)`,`stroke_width=4` | | **自适应字号** | 从 56pt 开始逐步缩小(52→48→44→40→36→32→28→24),直到文字宽度 ≤ **756px**(画面宽 70%) | | **左右边距** | 每侧留白 15-20%;最大文字宽度 = `1080 × 0.70 = 756px` | | **竖向位置** | 文字**底边**在 `y = 1344`(画面高度 70%,位于数字人 PiP 上方) | | **显示方式** | **逐句单行**:一次只显示一句话,句与句之间无重叠;长句拆成短语分时段显示 | | **时间戳来源** | 先用 `audio_transcribe_lyrics` 获取句级时间戳,再按自然语义拆成 5-7 词的短语,时长按字符数比例分配 | | **无背景条** | 文字直接叠加在视频画面上,不加半透明底条 | **PIL 渲染核心代码:** ```python font, tw, fs = fit_font(text, max_w=756) # 自适应字号 x = (1080 - tw) // 2 # 水平居中 y = 1344 - fs # 底边对齐 y=1344 draw.text((x, y), text.upper(), font=font, fill=(255,255,255,255), stroke_width=4, stroke_fill=(210,70,10,255)) ``` ### 数字人 PiP 规范 > ⚠️ **`pip_clean.mov` 易过度抠像(alpha 全零)**,阶段七合成时改用 `talking_head_green.mp4` + ffmpeg `chromakey` 实时抠像,更可靠。 | 项目 | 规范 | |------|------| | **抠像方式** | ffmpeg `chromakey` 实时抠绿幕(阶段七合成时内联,无需预处理) | | **绿幕颜色** | 采样视频角落像素确定实际颜色(AI 生成绿幕通常为 RGB≈56,138,61 = `0x388A3D`) | | **⚠️ similarity** | **必须 ≤ 0.10**(深色皮肤角色 YUV 距离仅 0.25,similarity=0.15 即开始抠掉人物;切勿使用 0.2 以上) | | **blend** | `0.02`(边缘锐利,减少半透明残边) | | **缩放** | `scale=400:-2`(宽 400px = 画面宽 37%,高度保持比例,约 541px) | | **位置** | `overlay=x=0:y=H-h`(左对齐,底部与视频底边齐平) | | **起始时间** | `enable='lte(t\,{voiceover_end})'`(第 0s 出场,口播结束即消失) | | **图层顺序** | **数字人必须在最上层**(覆盖字幕层之上) | | **幕色选择** | 默认绿幕 `#00FF00`;角色服装含绿色调时改用蓝幕 `#0000FF` | **阶段七 filter_complex 片段:** ``` [2:v]chromakey=0x388A3D:0.10:0.02,scale=400:-2[pip_keyed]; [v_sub][pip_keyed]overlay=x=0:y=H-h:enable='lte(t\,13.735)':format=auto[v_out] ``` **similarity 诊断方法:** ```python # 提取单帧检查抠像结果 ffmpeg -ss 3 -i talking_head_green.mp4 -frames:v 1 -vf "chromakey=COLOR:SIM:0.02" test.png # 用 PIL 检查 non-zero alpha 像素数 # 正常:~55-65% 像素可见(人物占画面大部分区域) # 过度抠像:< 5% 像素可见 → 降低 similarity ``` ### 教程段规范 | 项目 | 规范 | |------|------| | tut_002 时长 | **1-1.5s,严禁超过 2s** | | tut_004 | **不展示静态原图**;上传动画结束即为确认状态 | | 教程 overlay | **必须预拼接为单一 tut_combined.mp4**,禁止分段 overlay | | 教程结束衔接 | 教程段结束后立即切回写真照片,无缝衔接 | ### 音频规范 | 项目 | 规范 | |------|------| | 语音收尾 | **截断而非 fade out**:尾板开始时直接截断口播,**禁止 fade out** | | BGM 音量 | `volume=0.15`,不可盖过口播 | | voice_id | 根据角色性别,调用声音列表工具(如 `get_voice_id`)选择合适的声音 | | 尾板音频 | 用 `amix` 混合,保留尾板自身声音 | | **音效保留** | 原 skill 中的所有音效必须保留(如闪光灯音效、转场音效等) | **口播超过 6s 时的画面循环处理**(数字人视频生成上限 ~5.88s): ```bash ffmpeg -stream_loop N -i talking_head_green.mp4 -i voiceover.mp3 \ -map 0:v -map 1:a -c:v libx264 -c:a aac -shortest -t {实际音频时长} output.mp4 ``` ### 图片转场规范 - 写真图之间**必须使用 xfade 转场**(`slideleft` / `slideright` / `fadeblack`) - **禁止硬切** --- ## 文件组织总览 ``` {project_name}/ ├── fonts/ ├── brief.md # 需求摘要 ├── character.jpg # 角色形象图 ├── character_prompt.txt # 生图提示词 ├── digital_person/ │ ├── green_screen.jpg # 绿幕肖像(Step 1) │ ├── talking_head_green.mp4 # official 图音视频(口型同步,Step 2) │ ├── pip_clean.mov # 抠像后透明视频(Step 3) │ └── talking_head_preview.mp4 # 5s demo 预览 ├── photos/ # 换脸写真 │ ├── photo_01.jpg │ ├── photo_02.jpg │ └── photo_03.jpg ├── voiceover.mp3 # 口播语音 ├── voiceover_script.txt # 口播文案 ├── voiceover_subtitle.json # 字幕时间戳 ├── final.mp4 # 最终视频 └── final_4x5.mp4 # 4:5 裁切版 ``` > ⚠️ **合成时音频处理**:数字人视频(talking_head_green.mp4)**自带音频**,合成时直接使用该音频,不要分离音频再混合,避免口型错位。 --- ## 导出剪映/CapCut 使用 clip-export skill 与 `scripts/export_to_jianying.py` 导出工程到剪映/CapCut 进行精细调整。 脚本已内置多路径自动查找 `jy_wrapper`(同级 `../clip-export/scripts/`、`~/.claude/skills/clip-export/scripts/` 等),无需手动指定路径。 ### 使用方式 ```bash python scripts/export_to_jianying.py \ --project-name "my_promo" \ --photos photos/photo_01.jpg photos/photo_02.jpg photos/photo_03.jpg \ --digital-person digital_person/talking_head_green.mp4 \ --voiceover voiceover.mp3 \ --bgm bgm.mp3 \ --subtitles voiceover_subtitle.json ``` > 若找不到 `jy_wrapper`,脚本会打印安装提示;也可通过 `JY_WRAPPER_PATH` 环境变量手动指定 `clip-export/scripts/` 目录路径。 --- ## 合成命令参数 ### 动作模板合成 ```bash python scripts/composite.py action \ --dance ./dance_video.mp4 \ --tutorial ./tutorial_segment.mp4 \ --voiceover ./voiceover.mp3 \ --bgm ./bgm.mp3 \ --subtitle-json ./voiceover_subtitle.json \ --endcard ./assets/endcard_en.mp4 \ --output ./final.mp4 ``` ### 图片模板合成 ```bash python scripts/composite.py image \ --photos ./photos/photo_01.jpg ./photos/photo_02.jpg ./photos/photo_03.jpg \ --tutorial ./tut_combined.mp4 \ --pip ./digital_person/pip_clean.mov \ --voiceover ./voiceover.mp3 \ --bgm ./bgm.mp3 \ --subtitle-json ./voiceover_subtitle.json \ --endcard ./assets/endcard_en.mp4 \ --output ./final.mp4 ``` > 所有路径均相对于 `{project_name}/` 项目目录。`--photos` 传入所有写真图,顺序即展示顺序;`--pip` 仅图片模板需要传入。