Communitygithub.com

doodle-comedy-series

白背景、黑线条、大头简笔画的吐槽短视频系列制作技能:选定主题、撰写脚本、绘制分镜、逐句配音、渲染成片、制作3:4封面,并生成视频号发布物料。支持单集或批量制作。

doodle-comedy-series とは?

这是一个专门用于生成“白底简笔吐槽短视频”系列的AI技能。它面向希望快速制作系列化、风格统一的吐槽短视频的内容创作者。该技能支持Claude Code等部署了`mcode-tools`的AI agent平台。其核心工作流程包括:根据梗味定选题、写脚本、绘制所有分镜画面(使用同一套绘图基元和字体)、逐句调用TTS合成配音、渲染带有字幕(行楷字体,红色关键词)的9:16竖屏视频、制作3:4封面、以及生成微信视频号发布所需的标题、描述、话题标签和置顶评论等全套物料。技能特别强调风格一致性,通过硬编码的绘图基元和严格的校验脚本(如重叠检查和字幕匹配检查)确保每一集视频在视觉和内容质量上都保持一致,并提供完善的错误处理机制来应对TTS限流等问题。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/inhai-wiki/doodle-comedy-series/tree/HEAD

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

白底简笔吐槽短视频系列

一条视频 = 一份稿 + 一组分镜 + 一条音轨 + 一张封面 + 一套发布物料。 全部用同一套绘图基元和字体画出来,所以系列里每一集风格一致、封面和正片零漂移。

产出契约

每一集必须交付这 5 组文件,缺一不可:

产出文件规格
字幕版成片out/<标题>_简笔吐槽_字幕版.mp41080×1440,30fps,H.264+AAC,约 68s
无字幕版成片out/<标题>_简笔吐槽_无字幕版.mp4同上,去掉字幕层
字幕文件out/<标题>.srt单行 ≤16 字,时间递增不重叠
3:4 封面out/<标题>_封面.png1080×1440,与正片同一套线条和字体
视频号物料project_*/publish.md + publish.json3 档标题、1 版描述、5–8 个话题、1 条置顶评论

另附 out/<标题>_预览.png(四格关键帧条),方便用户一屏看完一集。

环境

Python 3.10+、Pillow、NumPy、ffmpeg/ffprobe。先建虚拟环境,不动系统 Python:

python3 -m venv .venv && .venv/bin/pip install -r "$skill_dir/scripts/requirements.txt"

macOS 上 ffmpeg 常不在默认 PATH,先 export PATH="/opt/homebrew/bin:$PATH"。 配音走 mcode-tools(MiniMax TTS/ASR),需要 mcode-tools-master 技能在 PATH 上。

如果 python3 报 You have not agreed to the Xcode license agreements(退出码 69), 说明系统 Python 没装好,换一个能用的解释器建环境,例如 /opt/homebrew/bin/python3.13 -m venv .venv,不要去动 Xcode 的授权。

流程

1. 定选题与系列定位

单集:给一个梗味方向就行。多集:先给每集一个互斥的梗味,不要同一种笑法换皮。

  • 自嘲荒诞流(自己越讲越离谱)
  • 对话反转型(两人对话推进,最后一句翻盘)
  • 冷观察流(旁观式吐槽,克制冷幽默)
  • 荒诞设定流(把一个荒唐前提当真)

同一系列里至少有两种不同梗味相邻,视觉语言可以共用,叙事节奏不要雷同。

2. 写稿

读 references/writing-style.md。硬指标:

  • 一句一镜,约 40–45 句、480–520 字,落点约 68s(字数 ÷ 7.4 ≈ 秒数)。
  • 每个包袱必须有一个看得见的动作或道具变化兑现,不能只靠字幕说。
  • 结尾要翻转角色关系,留一句能单独截图的台词。
  • 写成 JSON:{"title": ..., "target_seconds": 68, "segments": [{"scene": ..., "text": ..., "red": [...]}]} scene 是画面 id,red 是要标红的词(必须原样出现在 text 里)。

3. 切分镜

"$python_bin" "$skill_dir/scripts/build_segments.py" --story story.json --out project_ep2

字幕按标点切成 ≤16 字一行;渲染器一行放不下 17 字以上。切分点挑「接近 10 字」的 标点,避免把词劈开(「大型预付」不能切成「大型预」「预付」);引号里的短句整段不拆, 不会切出以 」 开头的行。脚本会校验红词在字幕里、切分没丢字、没出现纯标点空字幕, 并打印预估时长:字数 ÷ 7.4 ≈ 秒数,偏离目标 ±10% 会给出警告——按提示加减句子, 不要靠改语速硬凑。

4. 画分镜

在 project_ep2/scenes.py 里写 scene_<id>(c, t, d) 函数,并在文件末尾重定义 SCENES 字典(只含本集的 id)。绘图基元见 scripts/render/doodles.py。

  • person(c,x,y,s,expr,boss,pose,t,arms,legs):头心在 (x,y),身体到 y+307*s,expr 取 dead/sad/happy/angry/shocked/sleep,pose 取 stand/shrug/point/phone/pockets/walk。
  • woman(c,x,y,s,expr,t):妈妈造型(发髻 + 裙子)。
  • speech(c,x,y,w,h,tail,size):气泡;c.text((x,y),'字',size) 是居中锚点。
  • c.curve 只接受 4 个控制点;c.text 不支持描边和多行。

改完先过两道门:

"$python_bin" "$skill_dir/scripts/check_overlap.py" project_ep2/scenes.py   # 静态布局审计
"$python_bin" "$skill_dir/scripts/check_project.py" project_ep2             # 接触表目检

check_overlap.py 抓文字压人物、文字互相重叠、元素超出安全带。它已经识别两种 「看起来重叠但其实不是」的情况:if/else 里互斥的换字,以及白底色块盖住旧元素。 所以报出来的基本是真问题——退出码非 0 就先修,不要直接渲染。

check_project.py 先查字幕,再出接触表:字幕拼起来必须和台词是同一句话 (允许人工润色过的标点,但不许多字、少字、换词),也不许出现没有字的空字幕; 不通过就直接退出,不会浪费时间去渲染接触表。

确实要保留的重叠(例如画在人物身上的挂牌徽章),在 scenes.py 里显式登记:

OVERLAP_ALLOW = {"three_years", "me_too"}

接触表要逐镜看:画面和这句台词对得上吗?道具画清楚了吗?

5. 配音

"$python_bin" "$skill_dir/scripts/build_voice.py" --project project_ep2 --speed 1.5 --gap 0.10

逐句合成是这套流程的关键:每一句单独 TTS,裁掉首尾静音后用固定间隔拼接, 所以每句的起止时间已知,asr.json 直接按这些时间构造,字幕对齐零误差, 不需要词级 ASR。

  • 默认音色 lengdan_xiongzhang(冷淡学长),用户指定别的就用别的。
  • TTS 有短周期限流(HTTP 429)。脚本用固定 10 秒间隔重试——固定间隔比递增退避有效得多。
  • 单集约 40–45 句,全程约 15 分钟,后台跑。
  • 合成完用 scripts/tts.py asr --file project_ep2/voice.wav 抽查一遍。
  • 近音误识(「办事/办事时」)只改 ASR 结果里的字,不改稿、不重录。

6. 时间轴、渲染与验收

"$python_bin" "$skill_dir/scripts/deliver.py" project_ep2 <标题> --target 68
"$python_bin" "$skill_dir/scripts/verify.py" project_ep2

deliver.py 会按目标时长反算 atempo(speed = 原始音轨 / (目标 - 尾留)), 生成时间轴、字幕、混音,渲染字幕版和无字幕版,并把成片和 SRT 归档到 out/。

verify.py 查:编码参数、全片解码、字幕时序与长度、ASR 回听。 验收全绿才算做完;解码失败、字幕时序有问题必须修完重渲。

7. 封面

封面不用 AI 生图,用正片同一套绘图基元和字体重画,风格零漂移。

在 project_ep2/cover.py 里写 illustration(c)(绘图基元已注入命名空间), 在 project_ep2/cover.json 里写文案行:

{"lines": [
  {"text": "相亲现场", "size": 146, "y": 170, "red": []},
  {"text": "我妈给我报了七个", "size": 96, "y": 312, "red": ["七个"]},
  {"text": "见家长见姥姥", "size": 64, "y": 1196, "red": []},
  {"text": "八十七了也不催生", "size": 64, "y": 1280, "red": ["催生"]}
]}
"$python_bin" "$skill_dir/scripts/make_cover.py" project_ep2

版面规则见 references/cover-design.md。封面必须单独看一眼再交付。

8. 视频号发布物料

先要素材,再写文案:

"$python_bin" "$skill_dir/scripts/make_metadata.py" project_ep2

脚本会打印全稿、红词、高频词和结尾三句。据此写:

  • 标题 3 档,带 emoji 钩子,每档 ≤22 字最好(超出仍可,硬上限 100 字)。
  • 描述 1 版定稿,2–3 行,第一行是钩子,话题以 #话题 内联在正文里。
  • 话题标签 5–8 个,必须都出现在描述里(脚本会校验)。
  • 置顶评论 1 条,引导补充或自嘲。

写好后:

"$python_bin" "$skill_dir/scripts/make_metadata.py" project_ep2 \
  --titles "标题一" "标题二" "标题三" \
  --desc "描述正文 #话题1 #话题2" \
  --tags "话题1" "话题2" \
  --comment "置顶评论"

规则细节见 references/publish-channels.md。产物 publish.md / publish.json。

硬约束

  • 画布 1080×1440(3:4),30fps,纯白底,轮廓 4–6px 黑线,大圆头细身体。
  • 主体集中在 y=400–1050,上方留白;字幕带从 y=1084 开始,字号下限 54。
  • 字幕用行楷(Xingkai),白字加深色软阴影,包袱关键词标红。
  • 字幕一行 ≤16 字,渲染器放不下更长的。
  • 不把正文烧进画面,字幕单独一层渲染。
  • 封面必须和正片同一套字体和线条,不允许换风格。
  • 保留已有成片;改稿用新项目目录,不覆盖已交付的集。

失败处理

  • TTS 一直 429:脚本已固定间隔重试 40 次。仍失败就降速到 1.4 再跑,或分批跑 (--limit N 续跑,缓存会跳过已合成的句子)。
  • prepare.py 报 ASR 不一致:说明 asr.json 和稿子对不上,通常是改稿后没重配音。 重跑 build_voice.py,不要用 --allow-asr-mismatch 糊过去。
  • render.py 报字幕过长:某条 caption 超了 16 字,回 build_segments.py 改切分规则。
  • check_overlap.py 非 0:按报出的 scene id 逐个改坐标,直到退出码为 0。
  • 配音没听完就别说听检通过;没完整看片别说完整观看。交付记录只写实际做过的验证。

参考

Windows (win32) platform notes

Windows 下的等价做法:

  • 虚拟环境:py -3 -m venv .venv,之后用 .venv\Scripts\python.exe 替代 $python_bin。
  • 依赖:.venv\Scripts\pip.exe install -r "<skill_dir>\scripts\requirements.txt"。
  • ffmpeg/ffprobe 直接装进 PATH(winget install Gyan.FFmpeg),无需加 /opt/homebrew/bin; 但 scripts/deliver.py、scripts/make_preview.py、scripts/verify.py 里的 ffmpeg 路径是硬编码的 macOS 绝对路径,改成 ffmpeg / ffprobe 即可跨平台。
  • scripts/build_voice.py 依赖 mcode-tools 在 PATH 上,以及 curl;Windows 10 1803+ 自带 curl,若缺失可用 Invoke-WebRequest -OutFile <path> <url> 代替。
  • 路径分隔符:所有脚本用 pathlib 处理,传参时给引号包裹路径即可。

関連スキル