Communitygithub.com

Block Town

将用户的一个创意想法,制作成一段完整的 Roblox 风格 3D 竖屏故事视频(1080x1920 MP4)。涵盖规则、脚本、专属旁白配音、代码构建的世界与角色(Blender + Three.js 渲染)、镜头、生活层、手机屏幕与道具、卡拉 OK 字幕、音效、稳定的人声混音和音乐文件。

Block Town 是什么?

Block Town 是一个完整的 AI 代理技能,用于将用户的一个简单创意(如“在这个小镇”或“在这个世界”的故事)自动生成为一段 Roblox 风格的 3D 竖屏故事视频。该技能将视频制作流程分解为七个明确的阶段(门),从构思规则和脚本开始,到配音、3D 场景设计、镜头制作,最后通过基于 Three.js 的高效渲染管线输出最终视频。它集成了代码驱动的世界构建(Blender)、角色动画、“生活层”(如呼吸、摇摆、飘浮标签)以及旁白配音生成(Fish Audio)和音效库(ElevenLabs)。该技能强调原创性,严格禁止使用其他创作者的资产,并专注于通过代码生成所有视觉和听觉元素。它支持 Roblox 风格(圆头、动漫脸、塑料质感)和较旧的“方块”风格,并可输出带卡拉 OK 字幕、平衡音量和可选的色彩分级与 60fps 运动模糊的最终视频。从构思到完成,一条 66 秒的视频通常需要 10-12 分钟的处理时间。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/chihabMe/block-town/tree/HEAD

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Block Town 是做什么的?

这个文件夹是整个工具包:小镇、演员阵容、他们的动作方式、渲染器、配音、音效、音乐设置,以及从一个想法到完成竖屏视频的完整步骤。该技能文件夹是包含此文件的目录,下文称为 SKILL。剧集文件位于该文件夹之外(由用户命名文件夹),下文称为 EPISODE。请使用绝对路径。

创建前请阅读:docs/ROBLOX_LOOK.md(世界、演员、道具、镜头制作方式), docs/RENDER.md(Three.js 渲染器、生活层、标签、手机屏幕和打印道具), docs/SCRIPT.md(故事撰写方式),docs/VOICE.md(配音和音乐),docs/SOUND.md(音效、 ElevenLabs、稳定人声混音)。docs/PROMPTS.md 包含每个阶段的提示。docs/GUIDE.md 是原始的 方块外观手册:地图、pose()、移动和相机规则仍然适用。

视频制作方式(自 ep05 起)

Blender 根据剧集的 Python 代码构建并摆放所有内容;Three.js 绘制最终帧。Blender 自身的 渲染器仅用于设计稿和镜头剧照。

episode.py ──(Blender: 构建小镇,摆放每一帧,生活层)──> 烘焙: scene.glb + anim.bin + materials.json
           ──(头less Chrome 中的 Three.js)──> EPISODE/frames/f_####.jpg  (~0.1-0.15 秒一帧)
           ──(finish.py: 字幕,平衡的人声,音效,音乐)──> EPISODE/<name>.mp4 和 <name>_music.mp4

一段 66 秒的剧集从帧到完成 MP4 文件大约需要 10-12 分钟(Blender EEVEE 需要约 3 小时)。

禁止事项

  • 禁止使用 Roblox 目录物品、下载的模型、来自其他创作者的视频素材、故事或音频。画面中的一切 均由代码构建或由 blockworld/pictures.py 绘制。可以研究病毒视频的工艺,但绝不重复使用。
  • 未经用户同意,禁止调用付费 API。Fish Audio(配音)和 ElevenLabs(音效)需要付费:运行前需告知 费用。sfx_gen.py 会检查剩余余额并在达到预留值前停止;未经询问,切勿提高预留值或循环生成以“重试”。 下载任何内容前需征询同意。
  • 此工具包中不包含音乐和参考配音片段。音乐仅来自用户提供的文件,且仅用于 _music.mp4 副本。 如果该文件是从其他创作者的视频中截取的,必须明确说明 _music.mp4 不得发布:请发布纯净的 <name>.mp4,并在 TikTok 的声音选择器中添加歌曲。
  • 不要更改八个常驻角色(颜色、发型、服装):blockworld/town.py。
  • 不要将已在进行中的剧集切换到其他外观。
  • 不要使用未经解释的抽象图形。在两个小人之间画一道光束、一条线或一个光晕并不能告诉观众任何信息 (ep05 中“发出每一根金条”的光束被理解为“一条蓝线”)。展示事物本身:从标签中飞出的金条,递减的计数器, 显示相关信息的手机屏幕。

外观

新剧集使用 Roblox 外观:build_town(..., style="roblox")。圆头配动漫脸,多层头发, 印花衣服,闪亮塑料,太阳/雾/雨氛围,3 字卡拉 OK 字幕。较旧的 方块外观(方块头, 纯色)仍然适用于以该风格开始的剧集:不带 style 的 build_town(...) 会生成方块外观, 因此在新剧集中务必写上 style="roblox"。

质量标准(用户拒绝或要求的内容)

  • 没有任何东西是静止的。 使用生活层进行渲染(BT_LIFE=1,render_threejs.sh 中的默认设置): 呼吸、瞥视、重心转移、每次剪辑时的弹跳、摄像机晃动和推近、摇曳的树木、飘动的云彩、漂浮的标签、 旋转的加载转圈、脉动的 Wi-Fi 信号环、弹跳的信号格。一个只有摄像机缓慢移动的镜头是弱镜头: 让它有自己的动作。
  • 标签和气泡永远不被遮挡,也永远不会被裁剪。 生活层将它们绘制在所有内容之上,将它们提升到头发之上, 并将它们保持在 TikTok 安全区域内(x 5-85%,y 在字幕上方)。自动检查两个标签是否重叠(目前尚未自动化)。
  • 每个屏幕看起来都像一部真实的手机:使用 big_phone(screen=...) 并配合 pictures.py 中的图片 (状态栏、“无服务”、应用布局、一只手持握手机),绝不是一个带有 3D 文字的白盒子。手持手机显示锁屏。
  • 道具在手机大小下可读:纸质地图是真实绘制的地图(paper_map()),标志牌完全在画面内 (拉远摄像机:一个 10 个单位的标志牌在 9:16 比例下需要约 25 个单位的距离)。
  • 配音音量永不降低。 finish.json 中 {"voice": "vo/voice_level.wav", "loudness": "static"}:旁白 逐句进行电平平衡,混音使用单一固定增益,因此响亮的音效不会导致人声音量下降。衡量标准:整个视频的 短期响度应保持在 ±1 dB 以内,目标为 -14 LUFS。
  • 没有叠加或刺耳的音效。 每个时刻一个音效;音效长度不超过时刻本身;半秒内不要出现两个“错误”音效。

制作剧集:七道门

每道门后停下来,展示结果,然后等待用户。当存在真正的创意选择时,提供两个或三个选项,并说明你推荐哪一个。

门你制作的内容向用户展示
1 规则三个规则(来自用户的想法或 docs/SCRIPT.md 测试),每个规则包含一个氛围和一个地标创意一个表格
2 脚本EPISODE/script.txt(每行一个句子)和 EPISODE/SCRIPT.md:选项 A 和 B,节奏表,评分脚本
3 配音vo.py、words.py、voice_check.py(免费 Fish 试听)、level_voice.pyvo/voice.wav 及其数值
4 设计EPISODE/design/episode.py:每个新地标、道具、服装和角色的一张剧照;EPISODE/pictures.json 和 pictures.py(每个手机屏幕和打印道具)DESIGN_SHEET.jpg + 屏幕截图
5 剧照EPISODE/episode.py(包含所有镜头);check;剧照;修复;contact_sheet.pyCONTACT_SHEET.jpg
6 钩子前约 15 秒:render_threejs.sh EPISODE 0 F1,声音提示,finish.pyMP4 文件
7 完整视频render_threejs.sh EPISODE,音效,finish.py(纯净文件 + 音乐文件);批准后,付费配音试音两个 MP4 文件

门的详细信息在 docs/PROMPTS.md 中(提示 1 运行整个过程)。复制 examples/ep05-wifi 开始:这是一个 以此方式完成的剧集示例,包含其设计稿、42 个镜头、手机图片、提示和设置。

付费最终版本是重新录制:再次运行 words.py 和 level_voice.py,然后运行 check,并重新渲染 (镜头跟随单词时间)。因此,在门 3 批准免费版本的时间,但若用户想发布,请在门 6 之前进行付费版本。

命令

# 配音(门 3)
python3 SKILL/blockworld/vo.py EPISODE                 # 使用 Fish "Roblox" 配音录制一次(vo_config.json)
python3 SKILL/blockworld/vo.py EPISODE --post-only     # 对已保存的录制重新调整紧密度/临场感/语速,无新 API 调用
python3 SKILL/blockworld/words.py EPISODE              # 单词时间 -> vo/times.json
python3 -I SKILL/blockworld/voice_check.py EPISODE     # 检查语速、停顿、亮度是否在病毒视频范围内
python3 -I SKILL/blockworld/level_voice.py EPISODE     # 将每个句子平衡到相同电平 -> vo/voice_level.wav

# 道具图片(门 4)
python3 -I SKILL/blockworld/pictures.py EPISODE        # EPISODE/pictures.json -> EPISODE/pictures/*.png

# 镜头(门 4-5):Blender,始终通过 run.py 并带 --factory-startup 参数运行
blender -b --factory-startup --python-exit-code 1 -P SKILL/blockworld/run.py -- EPISODE check
BT_LIFE=1 blender -b --factory-startup --python-exit-code 1 -P SKILL/blockworld/run.py -- EPISODE stills [shot ...]
blender -b --factory-startup --python-exit-code 1 -P SKILL/blockworld/run.py -- EPISODE frame 12.5
python3 -I SKILL/blockworld/contact_sheet.py EPISODE   # 每个镜头一张带编号的剧照 -> CONTACT_SHEET.jpg

# 最终帧(门 6-7):Three.js
bash SKILL/blockworld/render_threejs.sh EPISODE              # 所有帧 -> EPISODE/frames/(66 秒约 10 分钟)
bash SKILL/blockworld/render_threejs.sh EPISODE F0 F1        # 仅 F0..F1(钩子、重新制作的镜头)

# 音效(门 6-7):参见 docs/SOUND.md
python3 -I SKILL/blockworld/sfx_gen.py --credits             # 查看 ElevenLabs 剩余积分数
python3 -I SKILL/blockworld/sfx_gen.py el-tag-pop ep07-...   # 从 sfx/ELEVENLABS_LIST.md 生成命名音效
python3 -I SKILL/blockworld/cues.py EPISODE cues_spec.json   # 按单词生成的提示("say": "froze")-> EPISODE/cues.json

# 完成(门 6-7)
python3 -I SKILL/blockworld/finish.py EPISODE                # 字幕 + 配音 + 音效(包括循环背景音)+ 音乐 -> 输出 MP4
  • check 不渲染任何内容:它运行每个镜头,打印镜头表格,并警告超过 2.5 秒的镜头。
  • 自动剧照检查(blockworld/stillcheck.py,自 ep08 起):在每个镜头中调用 focus(character, tag, ...)。 check 和 stills 随后会报告面部被遮挡(被柱子、人物、标签或角色自身手臂遮挡)、面部位于字幕条下方、 标签超出安全区域(x 5-85%,位于 TikTok 顶部栏和字幕之间)、标签相互覆盖,以及任何距离镜头 1 个单位内的物体。 结果写入 EPISODE/still_check.txt。在显示剧照之前修复每一行问题,然后仍需查看剧照:该检查不判断构图或 图片是否传达了台词含义。
  • 60 fps 带运动模糊(可选):在 finish.json 中设置 "render_fps": 240, "blur": 4,将以每秒 240 帧渲染, 并将每 4 帧平均为 1 帧 60 fps 输出。渲染时间约为每秒视频 1.6 分钟。
  • 色调转折(可选):在 finish.json 中设置 "grade": {"word": 24, "ramp": 0.5, "saturation": 0.6, "brightness": -0.05, "cool": 0.1, "vignette": true},将从该脚本单词(故事的转折点)开始,使画面变得更冷、 更暗、更平。字幕不进行色调调节。使用 finish.py EPISODE --plain 还会输出 <name>_plain.mp4 (30 fps,无模糊,无语调调节),以便进行对比。
  • ep08(episodes/ep08-price-tags-10s)是上述功能的 10 秒测试,带有约 1 秒的镜头。
  • stills 为每个镜头写入两张半尺寸的 Blender 图片(镜头进度的 30% 和 85%)到 EPISODE/stills/ 目录。 使用 BT_LIFE=1,使标签的放置方式与最终渲染相同。在展示任何图像之前,请先查看每张剧照。
  • 如果你的命令超时,render_threejs.sh 会在后台运行(66 秒视频约需 10 分钟)。它会在首次使用时安装两个 npm 包(blockworld/threejs/),并且需要 Chrome 或 Chromium(设置 CHROME=/path 以选择特定版本)。 烘焙文件保存在 EPISODE/threejs/;在用户接受视频后,删除该目录和 frames/ 目录。
  • 对 episode.py、布景或图片进行任何更改后:重新运行 render_threejs.sh(烘焙会读取代码;运行之间 没有缓存)。
  • render_all.sh(Blender EEVEE 帧)仅保留用于对比:每帧约 3-6 秒。
  • 关于钩子:使用 render_threejs.sh EPISODE 0 F1,其中 F1 是大约 15 秒后第一次剪辑之前的帧, 然后运行 finish.py(它会使用已存在的帧),并重命名 MP4 文件,以免完整视频覆盖它。
  • 在整个视频中观帧(每个镜头至少一帧),并在宣布完成前测量响度。如果你无法收听,请明确说明, 并列出你检查的其他内容。

文件位置

路径内容
blockworld/town.py街道、演员阵容、pose()、灯光、相机、build_town(style=...)
blockworld/roblox.pyRoblox 外观:rchar、塑料、氛围、rule_sign、giant_clock、puddles
blockworld/rprops.py现成道具:信号格标签和飞出金条代币、带真实屏幕和手的手机、发光和打印图片、折叠地图、海报、绶带、高顶帽、公交车、门、光束、鸽子、Wi-Fi 塔
blockworld/pictures.py、blockworld/pictures/根据 pictures.json 绘制手机屏幕、锁屏和地图;工具包的默认图片
blockworld/anim.py单词时间帮助函数、卡片(标签、气泡)、stand、walk、跑步者
blockworld/life.py生活层(BT_LIFE=1):空闲动作、相机、场景摆动、加载转圈、标签放置
blockworld/threejs/渲染器:bake.py(Blender 端)、scene.html + capture.mjs(Three.js 端)
blockworld/render_threejs.sh烘焙+绘制,制作最终帧的标准方式
blockworld/vo.py、words.py、voice_check.py、level_voice.py配音、单词时间、配音检查、电平平衡
blockworld/sfx_gen.py、sfx/ELEVENLABS_LIST.mdElevenLabs 音效:生成器和提示列表
blockworld/finish.py字幕、配音、音效(包括循环背景音)、音乐、稳定混音、输出 MP4
blockworld/cues.py按单词生成的提示列表 -> cues.json
sfx/音效:Pixabay 音效集(sfx/CREDITS.md);ElevenLabs 音效生成后存放在此处,命名为 el-*.mp3 / epNN-*.mp3(截至 ep05 尚未包含)
examples/ep05-wifi完整的剧集示例(Roblox 外观,Three.js 渲染器)
examples/ep00-roblox-look、examples/ep01-introRoblox 外观和方块外观的简短演示

相关技能