
想把一段机器人仿真记录剪成一支讲解短片,常见的做法是在剪辑软件里手动变速、切镜头、加字幕,做完之后很难再说清:片中哪一帧对应原始记录里的哪一个采样,慢放有没有丢帧或补帧。Robot Reel 的 agent director 把这件事拆成一份可以被程序核对的分镜计划:由用户或经 MCP 接入的语言模型写出简报和镜头,验证器检查镜头是否不重不漏地覆盖整段记录,再由 Blender 搭出可编辑的工程并渲染成片。本文依据固定在 commit c4bbdbb 的 docs/director.md 和示例分镜 examples/contact-storyboard.json,讲分镜合同的规则、帧映射怎样手算核对、从计划到成片的命令,以及 MCP 服务器的权限边界。
文中的数字和功能描述都来自项目自己的文档([O],项目自述),本站没有运行这些命令,也没有重新渲染。Robot Reel 的整体介绍见 Robot Reel:把机器人策略仿真变成可逐帧核对的回放与三维场景;本文只讲 director 这一项新功能。
示例成片:两次制动试验,四个镜头
文档链接的 director 演示页上是一支 7 秒的短片,素材是仓库里已有的一对相互独立的一维 MuJoCo 制动试验。短片有四个镜头:全景、跟拍、半速接触和俯视;180 个源采样全部保留,排进 210 个输出帧。文档称,在保存的 Blender 5.2.1 LTS 工程里检查了全部 420 个车辆采样、四处剪切点和跟拍相机。
这里要分清两件事。MuJoCo 是产生记录的仿真器,Blender 只是按保存的采样回放。文档写明,director 不合成新的物理。课程 物理AI实验室 1.4:仿真器地图,手算步长代价、找出接触分叉点,再给三个提速数字标清基线 讲过,换一个引擎重算,接触那一下的轨迹可能分叉;这里的成片不重算,所以画面里的接触就是记录里的那次接触,片子也不会比记录本身更“真”。
分镜合同:一份能被程序核对的计划
计划使用 schema robot-reel-director-1,包含简报(brief)、标题、主题(midnight 或 daylight)和 1–8 个镜头。每个镜头有 start、不含在内的 end、camera、rate 和 caption。规则只有几条:
- 相机只能是
overview、tracking、impact、top之一。 - 速率只能是 1 或 0.5;半速时每个采样恰好复制一次。
- 镜头必须按顺序覆盖整段源记录,不能有空隙,也不能重叠。
示例计划的标题是 “One decision. Two outcomes.”,主题 midnight,四个镜头如下(字幕为原文):
| 镜头 | start–end | camera | rate | caption |
|---|---|---|---|---|
| 1 | 0–60 | overview | 1 | Same start. Different braking decisions. |
| 2 | 60–96 | tracking | 1 | Follow the measured approach. |
| 3 | 96–126 | impact | 0.5 | Recorded contact, slowed to half speed. |
| 4 | 126–180 | top | 1 | Two outcomes. Every source sample retained. |
每个镜头的 end 都等于下一个镜头的 start,最后一个镜头结束于 180,这就是“不重不漏”。合同限制得很窄,能写进计划的只有剪切点、相机、速率和字幕。所以违反合同的错误能被机械地查出来:比如漏掉 126–130 这一段,或者给出 0.25 倍速,都直接违反合同,不需要人逐帧看片才能发现。但剪切点和相机是否适合简报,验证器并不检查;例如把接触镜头放在远离记录中接触的位置,照样满足所有规则。
帧映射:手算一遍
生成的 film.json 把每个输出帧映射到它的源帧和仿真器时间戳。文档写明三点:输出帧编号从 0 开始,Blender 帧从 1 开始;慢放期间片内时间和仿真时间有意不同;验证器会重新计算这份映射,不接受重新算过哈希、但内容前后矛盾的 JSON。
按上面的规则可以手算出示例的映射(下面是本文的推算,不是项目给出的表):
- 镜头 1:源采样 0–59,1 倍速,占输出帧 0–59,共 60 帧。
- 镜头 2:源采样 60–95,占输出帧 60–95,共 36 帧。
- 镜头 3:源采样 96–125 共 30 个,半速时每个出现两次,占输出帧 96–155,共 60 帧;输出帧 96 和 97 都对应源采样 96,输出帧 155 对应源采样 125。
- 镜头 4:源采样 126–179,占输出帧 156–209,共 54 帧。
合计 60 + 36 + 60 + 54 = 210 帧,与文档的 210 个输出帧一致;按 30 fps 是 7 秒,与“7 秒短片”一致。其中半速镜头在片中占 2 秒。由于 Blender 从 1 开始计帧,源采样 96 第一次出现在 Blender 第 97 帧。本文封面左下写着 “SOURCE 096”,右上写着 “SHOT 3 / 0.5x”,与这张映射相符。
这样手算的意义在于:核对的人不必相信成片,只要拿计划和 film.json 就能逐帧对上源记录。源轨迹及其校验和留在 bundle 的 source/ 目录里。
从计划到成片
文档给出的示例构建步骤如下,在仓库根目录执行。计划导出和验证只用 Python 标准库:
python3 -m robot_reel.cli direct docs/compare/braking --inspect
python3 -m robot_reel.cli direct docs/compare/braking \
--plan examples/contact-storyboard.json --output artifacts/director
python3 -m robot_reel.cli direct artifacts/director --verify
blender --background --python artifacts/director/build_directed_scene.py -- \
--bundle artifacts/director --output artifacts/director/reel.blend
blender --background --python scripts/check_director_blender.py -- \
--bundle artifacts/director --blend artifacts/director/reel.blend \
--report artifacts/director/animation-check.json
blender --background --python scripts/render_blender_preview.py -- \
--blend artifacts/director/reel.blend --frames artifacts/director/frames \
--scale 100 --samples 6 --threads 2
按顺序是:查看记录;按计划写出 bundle;验证 bundle;在 Blender 里搭出工程 reel.blend;在工程里做动画检查并写出报告;逐帧渲染。文档要求用 CPU Cycles 渲染;核对过的示例是 960×540、30 fps,采样保持不变(constant sample hold),不加运动模糊。保存的工程里有程序化材质、源遥测、全部相机绑定,以及嵌入的计划和映射 JSON。字幕在打包时烧进 MP4,在原生工程里以时间轴标记的标签保存,不是动画文字对象。
在装好常规 Robot Reel 运行环境后,打包成站点:
python scripts/build_director_site.py --bundle artifacts/director \
--output artifacts/director-site
打包器要求先有原生检查报告和全部渲染帧,才开始编码;它生成视频、海报、预览、交互页面、校验和与 project.zip。Linux 上默认字体是 DejaVu Sans,其他系统用 --font PATH 指定。生成的 index.html 要和它的媒体文件放在一起打开。
复现时要注意两处文档没有写的内容:文档说示例工程在 Blender 5.2.1 LTS 中检查过,但上面的命令没有固定 Blender 的安装版本;“常规 Robot Reel 运行环境”怎样安装,这份文档也没有展开。另外,第四条命令让 Blender 执行 bundle 里生成的 build_directed_scene.py,这是本机代码执行;本站建议只对自己生成、或审过的 bundle 运行它。
接入智能体:MCP 服务器做什么、不做什么
在常规 Robot Reel 环境中执行 pip install -e '.[director]'。文档称 MCP SDK 固定为 2.1.1,与现有的 Strands 运行时兼容。MCP 客户端配置为本地 stdio 服务器,把两个绝对路径换成自己的检出目录和解释器:
{
"mcpServers": {
"robot-reel-director": {
"command": "/absolute/path/robot-reel/.venv/bin/python",
"args": ["-m", "robot_reel.cli", "mcp", "--root", "/absolute/path/robot-reel"]
}
}
}
文档的示例请求是:检查 docs/compare/braking,先给出两次试验,跟拍接近过程,慢放记录到的接触,最后展示两种结果;保留全部源采样,把分镜写到 artifacts/my-directed-film。简报由接入的语言模型解读,两个工具分工明确:
inspect_recording返回记录中实际的事件帧和结果摘要,模型可以据此选择剪切点。create_storyboard校验类型化的计划,并写出一个新的 bundle。
边界同样写得清楚:工具只处理相对于配置根目录的路径,拒绝符号链接和 .. 逃逸,拒绝写入非空的输出目录;服务器不执行 shell 命令、任意 Python 或 Blender。上一节的构建和渲染命令是智能体或用户随后显式执行的步骤。仅仅启动这个 MCP 服务器不会产生任何模型调用。完整的 stdio 集成测试是 python scripts/check_director_mcp.py,文档说它也在 CI 中运行。
演示网站上没有托管语言模型,只展示渲染好的示例。页面上的编辑器下载的是一份用于新渲染的计划;在编辑器里改动,不会改变当前展示的成片或它的源元数据。
局限 / 注意
- director 目前只支持制动记录和制动对比,不能为任意机器人编排镜头,也不合成新的物理。Blender 只回放保存的采样。
- 字幕是编辑性的表述,不是经过独立核实的陈述。例如 “Different braking decisions” 是对两次试验的概括,验证器只核对帧映射,不核对字幕说得对不对。要把文字说法对回记录,见 对照原始机器人录像核对模型解释:Robot Reel 的 review-claims 能证明什么。
- 校验和只说明文件前后一致,不证明内容的独立真实性。
- 7 秒、210 帧、420 个车辆采样和 Blender 检查结果是项目在自己环境中的记录;第三节的逐镜头帧号是本文按合同规则做的推算。本站没有重新执行构建或渲染。
- 源记录是一维制动仿真;画面中的车道、车身和方块是渲染出的三维造型,不是真车试验,也不是硬件安全验证。
链接
- docs/director.md:agent director 说明(commit c4bbdbb)
- examples/contact-storyboard.json:示例分镜计划
- director 演示页
- 封面原图:docs/director/poster.png
- LICENSE(Apache-2.0)
- Robot Reel:把机器人策略仿真变成可逐帧核对的回放与三维场景
- 对照原始机器人录像核对模型解释:Robot Reel 的 review-claims 能证明什么
- 物理AI实验室 1.4:仿真器地图,手算步长代价、找出接触分叉点,再给三个提速数字标清基线
- 物理AI实验室:一套每个数字都能核对的物理 AI 课程(课程大纲)



