课程 PPT + 配音视频生成
一句话说明
输入一篇文章(或一份大纲),输出同目录的三件套:course.pptx(备注=配音脚本)、course.mp4(1080p · 逐页配音 · 烧录字幕)、prompt-list.md(逐页可复用提示词);精编模式另出 核心观点.md(观点主线 + 逐页时长分配)。
v1.1 的核心变化:画面不再只有一张脸。 主题、骨架、运镜、肌理四层各自可换,换一篇文章不用再吃同一套配色和同一个版式。
两种模式
| 精编短片(推荐 · 默认) | 标准课程 | |
|---|---|---|
| 体量 | ≤ 60 秒,8 页左右,口播 ≤ 270 字 | 5-10 分钟,12-16 页 |
| 画面 | 元素分步显现 + 页间转场 + 页级运镜 | 静态页 + 页间交叉溶解 |
| 链路 | build_content.py → make_video.py(逐帧渲染) |
build_content.py → render_pptx.py → make_video.py |
| 适用 | 短视频引流、单观点讲透、朋友圈/视频号投放 | 系统课、内部培训、交付客户 |
用户说「控制在 1 分钟以内」「要慢慢展现的效果」「带画面切换」→ 走精编模式。
画面系统(v1.1)
四层各自独立:可以只换一层,也可以整套换。这一节是「好不好看、够不够与众不同」的全部答案。
一、主题库 · 8 套(themes.py / references/themes.md)
一套主题 = 背景 / 卡片 / 描边 / 主文字 / 次要文字 / 强调色 1 / 强调色 2 / 胶囊底色 / 幕布色 / 默认肌理。换主题 = 整套画面换脸。
| id | 名称 | 适用 | 底 | 肌理 |
|---|---|---|---|---|
midnight |
深夜靛蓝 | 科技、方法论、通用(默认) | 深 | grid |
ink |
墨宣 | 文化、观点论述、有分量长文 | 浅 | paper |
amber |
琥珀暖夜 | 故事、人物、有烟火气 | 深 | noise |
mint |
薄荷晨光 | 教育、成长、健康清新向 | 浅 | dot |
neon |
霓虹赛博 | AI、前沿技术、硬核向 | 深 | scan |
paper |
纸感米白 | 商业、咨询、客户汇报 | 浅 | paper |
ocean |
深海 | 数据、趋势、财经向 | 深 | glow |
graphite |
石墨工业 | 工业、制造、B 端交付 | 深 | grid |
怎么切:改 build_content.py 顶部一行,或命令行临时指定——
PPT_THEME=ink python build_content.py # 出 PPT + 提示词
PPT_THEME=ink python make_video.py # 出片
⚠️ 两处必须用同一个 PPT_THEME,否则 PPT 与成片会是两套配色。
选哪套:python theme_pick.py --text "<文章正文>" 按调性关键词给前 3 名 + 理由;--show 顺便渲染候选对比图。
主题设计红线(改配色时别踩):
- 幕布色
curtain必须比页背景bg更深,否则章节转场「铺过」看不出来,整段白做。 - 浅底主题(
ink/mint/paper)的卡片用纯白,靠描边分层;卡片与背景太近,画面会糊成一片。 - 强调色 1 用于序号点、胶囊文字、下划线;强调色 2 用于橙色短线、幕布前缘。别把两者调成相近色,否则主次不分。
二、版式库 · 10 种骨架(layouts.py)
v1.0 只有「封面 + 卡片列表」两种骨架,所以什么文章出来都长一张脸。现在一页一个骨架:
| id | 名称 | 骨架 | 适合 |
|---|---|---|---|
cover |
封面 | 居中大标题 + 副标题 + 要点行 | 首屏 |
list |
卡片列表 | 纵排卡片 + 序号点 | 通用兜底 |
compare |
左右对开 | 两栏对撞 + 中间 VS | 新旧 / 正误 / 别人与自己 |
flow |
横向流程 | N 步并排 + 连接箭头 + 序号圆 | 四步法、步骤、流程 |
metric |
大数字 | 一个核心数字(自动解析)+ 后缀 + 小注 | 有量级的数据页 |
quote |
引语金句 | 居中大引语 + 引号装饰 + 落款 | 全片记忆点 |
timeline |
纵向时间轴 | 左侧轴线 + 圆点 + 右侧卡片 | 时间线、并列条目多 |
checklist |
清单勾选 | 勾选框图标 + 左侧竖条 | 自查、合规、发布前检查 |
cta |
行动号召 | 居中标题 + 横向行动项 | 收尾页(末页自动用) |
feature |
左图右文 | 左侧图位 + 右侧要点卡 | 配图页(需 image_file) |
怎么定:page["layout"] 显式指定优先;没写就按内容启发式(步骤句→flow、大数字→metric、对撞词→compare、≥4 条→timeline、末页→cta),再由 plan_pages() 压掉「同一骨架连着超过 2 页」。
python layout_pick.py # 看建议表
python layout_pick.py --avoid 1 # 同骨架不许连续出现
红线:
compare必须 2 条、flow/cta至少 2 条;条数不够会自动回落list(不会画出空卡)。feature没有image_file会回落list——别留一块空图位。- 版式几何统一用 inch 定义,
build_content.py(出 PPTX)与render_animated.py(出视频)共用同一份数据。改版式只改layouts.py一处,两边同时生效。
三、页级运镜 · 10 种(camera.py)
v1.0 全片所有页共用一条 ZOOM_FROM=1.038 曲线,等于每页镜头运动完全一样。现在:
中心推近 / 中心拉远 / 锚左上推 / 锚右下推 / 锚右上推 / 锚左下推 / 右摇 / 左摇 / 下俯 / 上仰——按页序号确定性轮换,相邻页必然不同。
⚠️ 红线(这是会糊的地方):
| 项 | 限值 | 原因 |
|---|---|---|
| 缩放上限 | ≤ 1.06 | 画面里是文字,超过就发虚 |
| 缩放下限 | ≥ 1.02 | 低于此值缩出边缘会露背景 |
| 平移 | ≤ ±14px | 再大会顶到 y<875 的字幕安全区 |
| 时长 | 不额外加 | 有 60 秒硬上限,加时会长出提语速重跑 |
关掉运镜:camera.CAMERA_ON = False。嫌渲染慢可把 camera.RESAMPLE 改成 Image.BILINEAR。
四、背景肌理 · 5 种(textures.py)
grid 细网格 / paper 纸纹 / noise 噪点颗粒 / dot 点阵 / scan 斜线扫描 / glow 径向光晕。
这是从「扁平 PPT」到「有质感的画面」最便宜的一跳。强度锁在 3%~8%(MAX_STRENGTH=0.08)——肌理不是图案,一旦压低文字对比度就得不偿失。深底走加色、浅底走减色,由主题自动决定。
五、配图(默认关闭)
两件事:图位(feature 版式)与出图提示词规则(build_visual_prompt.py)。
python build_visual_prompt.py --list # 12 种可选画风
python build_visual_prompt.py --style darktech --visual "一个人翻看一摞纸卡,暖黄台灯"
python build_visual_prompt.py --check --visual "..." # 只自检
出图提示词由脚本拼,不要手写——它固化了三条铁律:
- 只写看得见的具体物。禁「呈现 / 表现 / 传达 / 营造 / 体现 + 氛围 / 基调 / 科技感」这类总结句——画不出来,其中的抽象词还会被生成模型当成文字画进画面。
- 完全不提「文字」相关概念,连「无文字」也不写(出图没有反向提示,提了反而诱导它画字)。
- 屏幕 / UI / 照片类内容做画风适配转译:屏幕里的画面 → 手中的画框;数据 → 成摞纸卡或排开的圆点;要表达数量用「密密麻麻的众多人形」,不用写数字的标牌。
外加一段锁画风尾巴,防止人物被画成真人照片脸。--check 会自动拦下上述三类问题。
出好的图存进 job 目录,页面写 "image_file": "<绝对路径>" + "layout": "feature"。
默认不出图(生成图片有成本),只给提示词清单。
精编模式工作流 —— 两阶段,两个确认点
核心原则:先定 PPT,再做动画。
单元动画渲染要 3 分钟且逐帧出图,不能盲跑;版式没定就做动画,内容一改就得整片重渲。所以把流程拆成 A / B 两段,每段末尾必须先停下来跟用户交流确认。
阶段 A · PPT 定稿(没拿到「页面没问题」这句话之前,不碰动画)
| 步 | 动作 | 产出 |
|---|---|---|
| A0 | 建 job 目录:python workspace.py new --topic "<主题>"(打印的绝对路径就是 JOBDIR) |
JOBDIR |
| A1 | 先出观点,再出片:把原文压成「一句话核心 + 3-5 条观点主线 + 方法步骤」 | 核心观点.md |
| A2 | 选主题:python theme_pick.py --text "<正文>",确认 PPT_THEME |
— |
| A3 | 定骨架:python layout_pick.py,把要指定的写进 page["layout"] |
layout_plan.json |
| A4 | 口播字数定生死:+10% 语速下中文约 5.3 字/秒(270 字 ≈ 51 秒)。全片口播控在 250-270 字,按页分配(封面 25 字、常规页 30-45 字、方法页最多 55 字) |
— |
| A5 | 写内容源:改 PAGES(字段见下节)。这一步先不写 units——动画是阶段 B 的事 |
build_content.py |
| A6 | 生成:python build_content.py |
course.pptx + prompt-list.md |
| A7 | 预检:python preflight.py(有阻断项先改,别往下走) |
预检报告 |
| A8 | 出评审表:python work/ppt_review.py |
PPT评审表.html + work/pages/*.png |
| A9 | 停下来,把评审表交给用户,逐页确认版式与文案 | ← 确认点 ① |
| A10 | 有驳回 → 改 PAGES / layout / 主题 → 重跑 A6-A8 → 再确认 |
— |
A8 的脚本干三件事:把每页终态渲染成图(与成片同一套渲染器,所见即成片所见,不是另画一版预览)、跑程序化自检、生成浏览器可直接扫的评审表。
自检项(脚本自动判,不用肉眼):
| 项 | 判定 |
|---|---|
| 字段完整性 | idx/module/title/bullets/notes 齐全 |
| 标题长度 | 正文页 ≤ 16 字、封面副标题 ≤ 14 字 |
| 要点长度 | 单条 ≤ 18 字(超了会换行挤卡片) |
| 口播配额 | 封面 ≤ 25、常规 ≤ 45、方法页 ≤ 55、全片 ≤ 270 字 |
| 合规风险词 | 极限词 / 绝对化 / 收益承诺;「第一步」这类序数词自动豁免 |
| 来源标注 | 末页含「素材来源」行 |
| units 合法性 | id 合法 + 条数与要点匹配 |
| 版式合法性 | 未知版式 / feature 缺图(v1.1) |
| 出片配置 | 主题 / 纹理 / 转场 / 总时长估算(v1.1) |
A9 要跟用户确认的:① 标题有没有说清这一页的观点 ② 要点卡有没有撞字、截断、贴边 ③ 口播字数与画面对不对得上 ④ 来源标注在不在位 ⑤ 主题配不配这篇文章 ⑥ 骨架有没有连着几页一个样。
驳回怎么回退:只改 build_content.py 的 PAGES,不要去动 layouts.py 里的坐标常量来「迁就」文字——那些常量同时决定 PPTX 与成片两边的版式,改一处两处一起偏。
阶段 B · 单元动画(确认点 ① 通过后才开始)
| 步 | 动作 | 产出 |
|---|---|---|
| B1 | 写 units:给每页配与 bullets 一一对应的动画 id |
build_content.py |
| B2 | 定转场:TRANS_KIND = "chapter"/"slide"/"wipe"/"zoom" |
build_content.py |
| B3 | 出方案:python work/anim_plan.py |
动效方案.md |
| B4 | 停下来,确认动画方案 | ← 确认点 ② |
| B5 | 出片:python make_video.py(自带 60 秒硬校验:超时先收页尾停到 0.02s,再自动提语速重跑,最多 4 轮) |
course.mp4 |
| B6 | 出片时留日志:python make_video.py > work/build1.log 2>&1;再验收 python work/verify.py work/build1.log,必要时抽帧看图 |
验收报告 |
B3 的脚本会在渲染前挑出五类问题,别等出片后才发现:
| 问题 | 提示 |
|---|---|
| 整页同类 | 「全部 N 条都是 X——仍是整页一个动画」,建议让 1 条不同(流程页豁免) |
| 相邻重复 | 第 i、i+1 条同类,会显乱 |
| 未编排 | 回落 unit_default,等于没做单元动画 |
| 条数不匹配 | units 与要点数不一致,多的静默回落默认值 |
| 动画超时 | 动画收尾 > 该页配音时长,节奏会拖 |
B4 要跟用户确认的:整体调性(要不要更炫 / 更稳)、哪几条相邻重复要换、动画快慢、转场类型。
确认点速查
| 节点 | 命令 | 问什么 | 通过标志 |
|---|---|---|---|
| ① PPT 定稿 | work/ppt_review.py |
版式 / 文案 / 主题 / 骨架 / 合规 | 自检全过 + 用户说「各页没问题」 |
| ② 动画方案 | work/anim_plan.py |
调性 / 重复 / 时长 / 转场 | 用户确认动画编排 |
为什么必须停下来问:出片一次 3 分钟且中间产物不留档;版式错误留到成片才发现,等于把 3 分钟和一轮返工都浪费掉。评审表就是把这一轮省下来的,preflight.py 是把「能自动判的错」再往前挪一步。
内容字段(PAGES 每页一条)
| 字段 | 说明 |
|---|---|
idx / module |
页码;模块标签(如「01 痛点」),显示为左上角胶囊 |
title |
页面大标题(≤ 16 字) |
subtitle |
仅封面用(≤ 14 字) |
bullets |
3-4 条要点,每条 ≤ 18 字;末条以「素材来源」开头时自动转为右上角小字标注 |
notes |
口播文案(= PPT 备注),字数按上面配额控制 |
prompt |
{body, image, img_en},进 prompt-list.md |
cover |
封面页置 true |
layout |
版式 id(见版式库表),不写则按内容启发式 |
image_file |
配图路径(配 layout="feature" 用) |
units |
阶段 B 才填:与 bullets 一一对应的单元动画 id 数组,缺省回落 unit_default |
unit_default |
该页默认动画 id(默认 wipe) |
十种单元动画(render_animated.py)
页面级模板由 page_mode(page) 按位置自动挑(封面→横幕、末页→缩放推近、其余→扫描擦除);页间转场见下节。
卡片级单元动画(v1.1 共 10 种):
| id | 名称 | 单元怎么出来 | 适合 |
|---|---|---|---|
up |
卡片上滑 | 整卡淡入 + 上滑 14px | 最稳,什么内容都不挑 |
wipe |
扫描擦除 | 竖线从左扫过,扫到哪亮到哪 | 正文默认,像被现场写出来 |
pop |
弹入强调 | 0.86→1.06→1.00 回弹 | 论点句、金句、要重音的一条 |
slide |
侧向滑入 | 从一侧滑入 118px 并淡入 | 并列条目、横向流程 |
flip |
折卡展开 | 竖折痕展开(横向压扁→撑开),带高光 | 对照 / 步骤分解 |
iris |
光圈揭示 | 圆形光圈由小放大揭开 | 配图页、氛围页 |
type |
打字机 | 序号与文字逐字显现 | 短句、标题式要点 |
stroke |
描边生长 | 卡片边框描出、文字后到 | 流程节点、需要"被画出来"感 |
step |
三段递进 | 序号先亮 → 卡片铺开 → 文字跟上 | 方法论四步、需讲逻辑顺序的页 |
draft |
线稿落定 | 暗态出现 → 底色转实 → 文字由低对比提亮 | 要点页、金句页;"从草稿到定稿"的过程感 |
draft 是本版新增的双层揭示:观感从「元素冒出来」变成「先被写出来、再被看清」。它只影响自己这一条,其余 9 种动画的观感与终态完全不变。
编排思路:一页内至少让 1 条与普通卡片不同(多为中间那条或末条),否则仍是「整页一个动画」。常见组合——流程页全 step;论点页 wipe/pop/wipe;清单页 step/stroke/up/pop;讲述型页面 draft/wipe/draft;要点页按位置轮转(同一页内不要连用两个同类动画)。
显现节奏由字数驱动(v1.1):layouts.unit_timeline() 按要点字数分配间隔——长句占更多时间、短句一带而过,比 v1.0 的固定间隔自然。总跨度夹在 UNIT_SPAN_MAX=1.60s 内,保证动画不拖过配音。
时长旋钮(render_animated.py 顶部):UNIT_DUR 各动画时长、UNIT_ROLE 各角色的进度区间(如 step 的 dot=(0,0.30) / bg=(0.20,0.72) / text=(0.52,1.00))。调角色区间比调总时长更能改观感,且不会影响终态。draft 的落定区间在 DRAFT_SETTLE_BG / DRAFT_SETTLE_TEXT。
离场:EXIT_ON(默认开)让单元在页尾 0.30s 内上移淡出,页间衔接不显得硬切。片尾页不退场——最后一眼要停留。页框(标题、胶囊)也不退场,避免画面空掉。
调性红线:单卡动画别超 0.66s(比页面模板长会拖);pop 缩放别超 1.08;iris/flip 每页限 2 个;type 只给 ≤12 字的短句。
页间转场(4 种,v1.1)
build_content.py 的 TRANS_KIND 切换:
| kind | 表现 | 适合 |
|---|---|---|
chapter |
色块横向铺过 + 模块名闪现 + 拉开 | 默认,整片立刻贵一档 |
slide |
旧页左移、新页从右推入,带橙色分割线 | 章节之间、语气转折 |
wipe |
新页自上而下擦除,带橙色前缘 | 同主题递进 |
zoom |
旧页放大淡出 → 新页从 94% 放大进入 | 强调、情绪高点 |
⚠️ chapter 的视觉要件少一个就"看不出铺过":
- 幕布底色必须比页背景更深(主题里已配好;改主题时别把两者调近)。
- 前缘要有一段 260px 橙色渐变带(左透右实,
k*k曲线)+ 8px 亮边,才有"刀光扫过"的感觉。纯细线太弱。 - 模块名字号加强档 84px,下划线宽 = 字宽 ×0.86,线高 8px。
- 铺满期停留需 ≥0.20s,否则大字来不及被看清。
- 转场加长会整体拉长成片:7 段 ×0.16s ≈ +1.12s,必须同步把起始语速调高、页尾停顿调低,否则卡不进 60 秒。
动画参数 —— 两档预设
标准档(默认,稳妥)与加强档(用户要"更炫"时切)。切换时改下表全部旋钮 + 转场时长,两者要一起动,只改一半会显得割裂。
| 常量 | 标准档 | 加强档 | 说明 |
|---|---|---|---|
FADE |
0.42s | 0.46s | 单元素淡入时长 |
TITLE_DELAY |
0.14s | 0.14s | 标题相对页首延迟 |
UNIT_STAGGER |
0.30s | 0.26s | 相邻单元显现间隔(基准值,实际由字数权重分配) |
ZOOM_FROM / ZOOM_T |
1.030 / 0.85s | 1.055 / 0.95s | 入场缓动缩放幅度与时长 |
SWEEP_T |
0.22s | 0.30s | 扫描线扫过一张卡的时间 |
COVER_DELAY |
0.34s | 0.34s | 横幕后内容统一延后量 |
页首交叉溶解 XFADE |
0.40s | 0.16s | make_video.py。有页间章节遮罩时反而要调小 |
页间转场 TRANS |
0.50s | 0.50s | make_video.py |
运行参数(make_video.py 顶部常量)
| 常量 | 默认 | 说明 |
|---|---|---|
VOICE |
zh-CN-XiaoxiaoNeural | 配音音色。女声候选:zh-CN-XiaoyiNeural(更清亮)、zh-CN-XiaoshuangNeural(更活泼);男声:zh-CN-YunxiNeural、zh-CN-YunjianNeural |
<rate> / <tail_pad> |
标准档 +14% / 0.08s;加强档 +18% / 0.04s | 由 main() 统一调度,超 60 秒先收页尾停到 0.02s、再每轮提语速 4% |
FPS |
30 | 帧率 |
SUB_FONT_SIZE / SUB_BOTTOM |
44 / 1000 | 字幕字号与底线 y |
MAX_DUR |
60.0 | 成片硬上限(秒) |
版式硬规则(踩过的坑)
- 字幕安全区:字幕底线 y=1000,两行时顶部约 y=884;页面内容必须收在 y<875(≈ y<6.08in),
layouts.py的内容区常量已按此约束。 - 字幕时间必须用页内时间:字幕时间轴是相对本页音频的,渲染循环里要拿
t_local(帧时间 - 本页起点)去匹配,用全局时间会导致第一页之后字幕全丢。 - 单位换算:渲染器画布 1920px 对应 13.333 inch →
_pin(inch)=inch*144;PPT 侧 7.5 inch 对应 1080px。版式几何一律用 inch 定义,两边各自换算,写坐标别把 inch 当 px 用。 - 颜色常量是元组:喂给演示文稿库必须过
rgb()包装(RGBColor类型校验会直接抛错)。 - 描边取值要容错:
shp.line.color.rgb在未设线时抛AttributeError,必须 try 包裹。 - 逐帧渲染走管道:帧直接以
rawvideo rgb24写进 ffmpeg stdin,不要落盘 PNG 序列(1800 帧会占用数 GB)。 - 不要用
-shortest:会截断段长;改用-t指定总时长。 - 扫描擦除必须按 x 裁切,不能整体淡入:整卡 alpha 渐显会让右半边一起半亮,"扫过才亮"的效果就没了。做法是按
cut = l + w * sw限制右边界——卡片矩形画到 cut(未满宽时不加圆角),文字用textlength逐字裁,圆点等 cut 过中心再画。 - 浅底主题的扫描线要换色:白线在浅色背景上看不见,
_draw_element已按BC.LIGHT自动切深色。 - 页间转场要计入音轨段长:插了
TRANS秒的遮罩帧,音频就必须同长静音,否则音画错位。做法是每页给一个slot = dur + TRANS,wav 用-t slot补静音,视频 offset 也按 slot 递增。 - 动画帧序列是逐帧写管道的:转场帧与页面帧同一条 stdin 流,帧序号
written必须连续推进,插转场后别忘了更新written与prev_snap(后者要用新页首帧,否则下一帧会从空态跳变)。 slide/wipe/zoom转场的新页首帧要取t=0,与后续渲染连续;换成"稍后时刻"会让新页开头闪一下又消失。paste必须显式传 mask(图像库 ≥10):img.paste(layer, (x, y))不带 mask 会把 RGBA 当 RGB 贴,整块内容变黑块。所有带透明图层的贴合都要写img.paste(layer, (x,y), mask or layer)。- box 坐标语义全局统一为
(x0,y0,x1,y1):_draw_element()内部再换算成「左上+宽高」。两套语义混用会画出巨型椭圆/错位文字。传给Image.new的坐标必须先int(round()),float 会抛TypeError。 - 单元内容要画到带
PAD(22px)外扩的独立图层,再对整块图层做外部变换;掩膜还要与图层自身 alpha 相乘(ImageChops.multiply(mask, layer.split()[3])),否则外扩区贴成黑边。flip类动画的文字须后置叠加(OVERLAY_TEXT),否则会在细线卡片上浮着一整行字。 - 离场的 alpha 要在外部变换之后、掩膜相乘之前施加,顺序错了
iris类动画的退场会被掩膜吃掉。
耗时基线
精编模式(60 秒片)实测约 3-4 分钟:TTS 8 条约 10 秒,逐帧渲染约 1800 帧 + libx264 medium 编码约 2.5 分钟;开运镜后每帧多一次重采样,约 +1 分钟。务必后台运行,不要在前台等;标准课程片按成片时长的 1.4-1.5 倍估。
嫌慢的两个旋钮:camera.RESAMPLE = Image.BILINEAR、camera.CAMERA_ON = False。
交付与排错
- 阶段 A 交付:
course.pptx、prompt-list.md、核心观点.md、PPT评审表.html(含work/pages/*.png逐页预览)、layout_plan.json。 - 阶段 B 交付:
course.mp4、动效方案.md。PPTX 与 MP4 必须同名同目录。 - 中间产物在
work/(audio / pages / 抽帧 / 校验脚本);work/audio/*.mp3每次build()开头会清空,避免改文案后复用旧配音。 - 脚本分工:
- 内容与配置:
build_content.py(内容源 + 主题 + 转场开关 + 角色取色 + PPTX 渲染) - 画面系统:
themes.py主题 ·layouts.py版式 ·camera.py运镜 ·textures.py肌理 ·build_visual_prompt.py出图提示词 - 渲染:
render_animated.py(视频渲染引擎)·render_pptx.py(PPTX 转图)·make_video.py(配音合成出片) - 选配与预检:
theme_pick.py·layout_pick.py·preflight.py·workspace.py - 开发自检:
layout_show.py(9 种版式对照图)·theme_show.py(8 套主题对照图) - 校验:
work/anim_plan.py(动画编排表)·work/verify.py(抽帧程序化验收) - 完整性:
scripts/verify_integrity.py(改完文件要--regen,发布前须 PASS) - 路径约定:
build_content.py / render_animated.py / make_video.py放项目根,其余校验类脚本放项目work/下(本文档命令均按此写)。技能包里的副本在scripts/,新项目开工时先复制过去。 - job 目录:
python workspace.py new --topic "<主题>"按「主题-时间戳」建目录并记账(job.json),所有素材都落在里面,换一篇文章不会覆盖上一篇。workspace.py list看历史。 - 解释器:需
图像库 / 演示文稿库 / 语音合成库 / 视频编码库 / 数值计算库五个运行依赖齐全,缺哪个装哪个。跑全链路前先确认这五个都能 import。 - 报错排查顺序:① 字体路径是否存在 ②
语音合成库是否联网可用 ③ ffmpeg 是否可执行 ④ 路径含中文/空格时用绝对路径 ⑤ 缺数值计算库就换解释器。 - 合规:所有表述原创重述;引用他人内容在页面标注来源;不整句复制;数据观点可溯源。
发布与迭代(skillhub)
本技能可上架到技能市场。发布前跑一键改造器,它会补齐市场必填字段、清洗 description、把说明文字里的外部库名换成通用名、出上传用图标、打包并回读体检:
cd ~/.workbuddy/skills/ppt-course-video
python scripts/publish_pack.py --check # 只体检,不写文件
python scripts/publish_pack.py # 改造 + 打包
python scripts/publish_pack.py --ver 1.1.0 # 升版本重改造 + 重打包
python scripts/publish_pack.py --pack-only # 内容没改,只重打包
- 只有一份技能目录:
~/.workbuddy/skills/<slug>/就是权威源。不要造__skillhub之类的副本——同名多副本会导致调用到旧版本。 - 市场必填字段:
name/slug/displayName/version/description/tags/category,缺一个上架会被拦。tags是检索主入口,别省。 slug与displayName分工:slug是英文标识(目录名、包文件名都跟着它),不要改成中文;displayName是市场列表与搜索里展示的名字。改展示名只需改 SKILL.md 的displayName一行,然后--pack-only重打包。- description 与 license 一律用双引号包裹,值里不写 markdown 星号:市场按纯文本渲染;裸值里出现「半角冒号+空格」会让 frontmatter 直接解析失败。触发词要写全,市场靠它命中问答。
- 打包不带安装侧缓存:
_icon.png/_meta.json/_skillhub_meta.json是客户端安装技能时才生成的本地文件,带上去会被判「不允许的文件类型」。 - 打包走白名单 + 黑名单:只收常见文档 / 脚本 / 图片后缀;自动排除备份件(
*.bak*.tmp*_bak)、临时件、隐藏文件、段印文件。打包后二次体检,包内一旦出现非标准文件就exit 3。 - 跨平台可运行是发布底线:字体走候选链(Windows 微软雅黑 → macOS 苹方 → Linux 思源黑体),脚本里不写死单机路径。改完请在干净目录验一遍。
- 上架通道:客户端技能管理页的上传入口,选技能目录或本包上传。
- 发布物:
~/.workbuddy/skills/dist/<slug>-v<版本>.zip。
品牌
对外交付文件保留「内容原创重述 · 本文档由 PPT生成视频专家 自动生成」署名(右上角)。技能迭代只体现「小段笔记 / 安粉传媒」自有标识,不出现任何外部归因表述。
<!-- ppt-course-video | fingerprint:206510782e475a9f | 归属:小段笔记 | 篡改将导致完整性校验失败 -->