Files
Genarrative/docs/technical/CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md
五香丸子 5cc8293380
Some checks failed
CI / verify (push) Has been cancelled
feat: add child motion picture book stage tooling
2026-05-10 23:10:24 +08:00

22 KiB
Raw Blame History

儿童动作识别互动玩法 Demo 热身关开发规格文档

日期2026-05-09
关联设计文档:CHILD_MOTION_DEMO_WARMUP_LEVEL_DESIGN_2026-05-09.md
适用范围:儿童动作识别互动玩法 Demo 固定启动热身关
文档性质:开发落地规格
说明:本文只将已确认的热身关设计内容拆解为工程可执行规格,不新增未确认的玩法、文案或视觉设计。

1. 开发目标

热身关作为 Demo 启动后的固定流程,需要完成以下开发目标:

  1. 调用摄像头并识别用户和环境。
  2. 使用横屏比例展示热身关。
  3. 在屏幕中央地面生成绿色圆环,引导用户到达建议位置。
  4. 将用户实际位置生成角色剪影。
  5. 只对摄像头背景做虚化处理,表达隐私保护、屏蔽环境干扰,并营造空间感。
  6. 按固定步骤完成站位、招手、左右移动、挥动左右手、原地跳跃检测。
  7. 记录用户左右移动距离、挥动手臂空间和跳跃空间。
  8. 将记录结果仅保存在当前 Demo 体验会话内。
  9. 后续关卡使用热身记录的边界进行安全提醒和暂停恢复。
  10. 热身结束后进入关卡选择。

当前阶段先落浏览器本地 Demo。浏览器摄像头视频流仅作为舞台背景热身动作检测以本地 mocap 动作数据源为准,通过 useMocapInput 连接 http://127.0.0.1:8876/stream 对应的 WebSocket 流,消费 general.body.center_norm 身体中心、手势、左右手坐标和跳跃事件推进站位、招手、左右手挥动与原地跳跃步骤。正式语音播报接口继续预留适配层,不阻塞前端热身流程、调试输入和页面表现骨架落地。

2. 非目标范围

热身关当前不包含以下内容:

  1. 不接入创作模块。
  2. 不作为可配置玩法模板提供给创作者。
  3. 不允许跳过步骤。
  4. 不允许系统自动进入下一步。
  5. 不设置动作检测最长等待时间。
  6. 不做特定用户识别。
  7. 不跨会话保存左右空间边界、手臂挥动空间和跳跃空间。
  8. 不对手部细节进行识别,只对肢体进行区分。
  9. 本阶段不处理无硬件、拒绝摄像头、多人入镜、识别丢失等异常流程;这些问题记录为待决策事项,后续硬件与摄像头方案稳定后再重新设计。

3. 运行入口与流向

3.1 入口

用户进入 Demo 后,先进入热身关。

3.2 出口

用户完成热身关所有步骤后,进入关卡选择。

当前后续游戏仍在设计中。热身结束后可先展示“开始游戏”按钮作为关卡选择占位,用户点击后进入下一关占位界面。

3.3 固定流程顺序

热身关必须按照以下顺序执行:

进入热身关
↓
到达中央绿色圆环并保持 2 秒
↓
招手 / 摆手
↓
热身说明
↓
向左一步,到达左侧绿色圆环并保持 2 秒
↓
回到中间,到达中央绿色圆环并保持 2 秒
↓
向右一步,到达右侧绿色圆环并保持 2 秒
↓
回到中间,到达中央绿色圆环并保持 2 秒
↓
挥动左手
↓
挥动右手
↓
原地跳一下
↓
播放热身结束特效和结束语音
↓
进入关卡选择

4. 页面基础表现规格

4.1 横屏比例

热身关需要使用横屏比例制作和展示,适用于电视屏幕、电脑屏幕等环境。

4.2 摄像头画面处理

用户进入热身关时调用摄像头。

摄像头画面处理要求:

  1. 识别用户和环境。
  2. 将用户实际位置生成角色剪影。
  3. 只对摄像头背景做虚化处理。
  4. 用户角色剪影用于表达用户在画面中的实际位置。
  5. 背景虚化用于表达对用户隐私的保护、屏蔽周围环境干扰,并营造空间感。

4.3 绿色圆环

绿色圆环用于指引用户到达指定位置。

绿色圆环出现位置包括:

  1. 屏幕中央位置的地面。
  2. 屏幕中心向左一个身位,约半米的地面位置。
  3. 屏幕中心向右一个身位,约半米的地面位置。

“约半米”技术上以角色剪影移动距离为准,后续根据体验调校。

4.4 绿色圆环选中状态

用户到达绿色圆环后,绿色圆环进入 2 秒选中状态。

用户需要在绿色圆环内保持 2 秒,才算完成该位置检测。

5. 通用交互规则

5.1 不允许跳过

每个步骤都必须由用户完成。

系统不提供跳过,也不自动进入下一步。

5.2 引导动画规则

每个动作等待 3 秒后可以播放对应引导动画。

当前不设置最长等待时间。

5.3 手势检测规则

招手 / 摆手、挥动左手、挥动右手三类动作需要有动作区分。

检测只区分肢体,不识别手部细节。

5.4 手势引导规则

挥动哪只手,就使用对应手的引导。

6. 状态机规格

6.1 状态列表

热身关至少需要支持以下流程状态:

状态 ID 状态名称 进入条件 完成条件 下一状态
warmup_enter 进入热身关 用户进入 Demo 摄像头调用并展示中央绿色圆环 center_arrive
center_arrive 到达中央圆环 中央绿色圆环出现 用户到达中央圆环并保持 2 秒 wave_greeting
wave_greeting 招手教学 中央圆环完成并播放圆圈消失特效 用户完成招手 / 摆手 warmup_intro
warmup_intro 热身说明 招手 / 摆手完成 播放热身说明文案与语音 move_left
move_left 向左一步 热身说明完成 用户到达左侧圆环并保持 2 秒 return_center_1
return_center_1 回到中间(一) 向左一步完成 用户到达中央圆环并保持 2 秒 move_right
move_right 向右一步 回到中间(一)完成 用户到达右侧圆环并保持 2 秒 return_center_2
return_center_2 回到中间(二) 向右一步完成 用户到达中央圆环并保持 2 秒 wave_left_hand
wave_left_hand 挥动左手 回到中间(二)完成 用户完成挥动左手 wave_right_hand
wave_right_hand 挥动右手 挥动左手完成 用户完成挥动右手 jump_once
jump_once 原地跳一下 挥动右手完成 用户完成原地跳一下 warmup_finish
warmup_finish 热身结束 原地跳一下完成 播放热身结束特效和结束语音 level_select
level_select 关卡选择 热身结束 进入关卡选择 -

6.2 状态推进约束

  1. 状态必须按顺序推进。
  2. 用户未完成当前状态检测目标时,不进入下一状态。
  3. 位置类状态必须满足“到达绿色圆环并保持 2 秒”。
  4. 动作类状态没有最长等待时间。
  5. 动作类状态等待 3 秒后可以播放对应引导动画。

6.3 开发者调试输入

本地 Demo 需要支持开发者调试模式,用于无摄像头和自动化验证场景。

调试映射如下:

  1. A 键映射用户向左移动。
  2. D 键映射用户向右移动。
  3. 鼠标左键按下并拖动映射左手轨迹。
  4. 鼠标右键按下并拖动映射右手轨迹。
  5. 空格键映射原地跳跃。

调试输入只作为本地 Demo 与测试辅助,不代表正式动作识别硬件口径。正式摄像头接入后,位置、手势和跳跃判断需要按摄像头硬件调教结果重新校准。

7. 分步骤开发规格

7.1 进入热身关

展示内容

  • 调用摄像头。
  • 识别用户和环境。
  • 屏幕中央地面显示绿色圆环。
  • 用户实际位置显示为角色剪影。
  • 只对摄像头背景做虚化。

文案与语音

欢迎你,小朋友,见到你真开心
请你来到圆圈这里和我打个招呼吧

检测目标

用户到达中央绿色圆环并保持 2 秒。

完成反馈

播放圆圈消失特效。


7.2 招手教学

展示内容

播放招手的手势引导。

用户进入该步骤 3 秒仍未完成动作时,可以播放引导动画。

检测目标

用户完成招手 / 摆手手势。

完成后

进入热身说明。


7.3 热身说明

文案与语音

你好呀小朋友,为了你玩的安全和开心,先来和我一起热个身吧

完成后

进入“向左一步”。


7.4 向左一步

展示内容

屏幕中心向左一个身位,约半米的地面位置出现新的绿色圆圈。

文案与语音

向左一步

检测目标

用户到达左侧绿色圆环并保持 2 秒。

完成反馈

真棒

数据记录

记录本次向左移动距离,作为后续关卡中的左侧空间边界参考。


7.5 回到中间来(一)

展示内容

场地中心位置出现绿色圆圈。

文案与语音

回到中间来

检测目标

用户到达中央绿色圆环并保持 2 秒。

完成反馈

真棒

7.6 向右一步

展示内容

屏幕中心向右一个身位,约半米的地面位置出现新的绿色圆圈。

文案与语音

向右一步

检测目标

用户到达右侧绿色圆环并保持 2 秒。

完成反馈

真棒

数据记录

记录本次向右移动距离,作为后续关卡中的右侧空间边界参考。


7.7 回到中间来(二)

展示内容

场地中心位置出现绿色圆圈。

文案与语音

回到中间来

检测目标

用户到达中央绿色圆环并保持 2 秒。

完成反馈

真棒

7.8 挥动左手

展示内容

播放伸展手臂挥动左手的手势引导。

用户进入该步骤 3 秒仍未完成动作时,可以播放引导动画。

文案与语音

挥动左手

检测目标

用户完成挥动左手。

完成反馈

真棒

数据记录

记录用户挥动左手的空间,保存为该用户对应的行为坐标。


7.9 挥动右手

展示内容

播放伸展手臂挥动右手的手势引导。

用户进入该步骤 3 秒仍未完成动作时,可以播放引导动画。

文案与语音

挥动右手

检测目标

用户完成挥动右手。

完成反馈

真棒

数据记录

记录用户挥动右手的空间,保存为该用户对应的行为坐标。


7.10 原地跳一下

展示内容

播放跳跃姿势引导。

用户进入该步骤 3 秒仍未完成动作时,可以播放引导动画。

文案与语音

原地跳一下

检测目标

用户完成原地跳一下。

数据记录

记录用户跳跃空间,保存为该用户对应的行为坐标。

完成反馈

播放热身结束特效、上浮字幕和语音:

真厉害,你是我见过最聪明的小朋友
别走开,现在开始我们的游戏吧

完成后

进入关卡选择。

8. 当前 Demo 体验会话数据

8.1 保存范围

以下数据仅在当前 Demo 体验会话内保存:

  1. 左侧空间边界。
  2. 右侧空间边界。
  3. 左手挥动空间。
  4. 右手挥动空间。
  5. 跳跃空间。

当前 Demo 体验会话数据需要满足:

  1. 用户刷新产品或退出产品后失效。
  2. 用户只关闭当前游戏关卡并重新进入时,可以直接来到开始游戏界面,不强制重复热身。
  3. 首版可使用前端运行时内存或同等生命周期容器保存;不得跨产品刷新持久化保存。

8.2 当前 Demo 体验会话定义

“当前 Demo 体验会话”指用户本次打开并体验 Demo 的过程。

当用户关闭 Demo、刷新页面、退出当前体验流程、重新进入 Demo或更换设备后系统不再沿用上一次热身记录的数据需要重新完成热身关并重新记录。

8.3 仅会话内保存原因

采用仅当前 Demo 体验会话内保存的原因:

  1. 每名用户的身高、体型、动作幅度不同,安全边界和行为坐标会发生变化。
  2. 当前 Demo 不做特定用户识别,无法确认下一次体验的是否仍是同一名用户。
  3. 用户所处的体验环境可能变化,包括房间大小、摄像头位置、屏幕位置和站立距离。
  4. 为保证安全,每次体验都需要重新对环境和距离进行安全检查。

9. 后续关卡安全边界使用规则

后续关卡需要使用热身关记录的左右空间边界进行安全判断。

9.1 覆盖安全边界线

当用户身体主体覆盖安全边界线时,对应侧屏幕边缘出现虚影提醒。

9.2 超出安全边界线

当用户身体主体超出安全边界线时:

  1. 关卡内容暂停。
  2. 屏幕虚化。
  3. 屏幕中央地面出现绿色圆圈。
  4. 屏幕提示文案:
小朋友,要注意安全哦
  1. 用户需要回到中心绿色圆圈并保持 2 秒后,才能继续游戏内容。

10. 识别能力清单

热身关需要接入或实现以下识别能力:

  1. 摄像头调用。
  2. 用户识别。
  3. 环境识别。
  4. 用户实际位置识别。
  5. 用户是否到达中央绿色圆环位置。
  6. 用户是否在绿色圆环内持续保持 2 秒。
  7. 用户是否到达左侧约半米绿色圆环位置。
  8. 用户是否到达右侧约半米绿色圆环位置。
  9. 招手 / 摆手手势识别。
  10. 挥动左手识别。
  11. 挥动右手识别。
  12. 原地跳跃姿势识别。
  13. 用户左右移动距离记录。
  14. 用户挥动手臂空间记录。
  15. 用户跳跃空间记录。
  16. 用户身体主体覆盖安全边界线判断。
  17. 用户身体主体超出安全边界线判断。
  18. 用户回到中心绿色圆环并保持 2 秒判断。

11. 表现能力清单

热身关需要实现以下表现能力:

  1. 横屏比例显示。
  2. 摄像头背景虚化。
  3. 用户位置生成角色剪影。
  4. 屏幕中央地面绿色圆环。
  5. 左侧约半米地面绿色圆环。
  6. 右侧约半米地面绿色圆环。
  7. 绿色圆环 2 秒选中状态。
  8. 圆圈消失特效。
  9. 招手手势引导。
  10. 伸展手臂挥动左手手势引导。
  11. 伸展手臂挥动右手手势引导。
  12. 跳跃姿势引导。
  13. 热身结束特效。
  14. 上浮字幕。
  15. 语音播报。
  16. 安全边界虚影提醒。
  17. 关卡暂停时屏幕虚化。
  18. 关卡暂停时屏幕中央地面绿色圆圈。
  19. 关卡暂停提示文案。

角色剪影、绿色圆环、虚影提醒、圆圈消失特效、手势引导动画和热身结束特效的正式视觉资源将通过 gpt-image-2 设计和生成。本地 Demo 阶段可以先使用 CSS、Canvas 或临时占位资源实现相同交互位置与状态,不把占位资源写死为正式资产。

12. 固定文案与语音清单

以下文案需要作为屏幕中上方浮现文字,并同步语音播报。

正式语音播报后续接入语音播报功能接口。本地 Demo 阶段保留播报适配层与调用点,可先只展示文字,不强制生成或播放正式语音资产。

欢迎你,小朋友,见到你真开心
请你来到圆圈这里和我打个招呼吧
你好呀小朋友,为了你玩的安全和开心,先来和我一起热个身吧
向左一步
真棒
回到中间来
真棒
向右一步
真棒
回到中间来
真棒
挥动左手
真棒
挥动右手
真棒
原地跳一下
真厉害,你是我见过最聪明的小朋友
别走开,现在开始我们的游戏吧
小朋友,要注意安全哦

13. 开发验收标准

13.1 热身流程验收

  1. 用户进入 Demo 后先进入热身关。
  2. 热身关使用横屏比例展示。
  3. 摄像头被调用。
  4. 用户位置显示为角色剪影。
  5. 摄像头背景被虚化。
  6. 中央、左侧、右侧绿色圆环可以按流程出现。
  7. 用户到达每个绿色圆环后,需要保持 2 秒才算完成。
  8. 每个步骤未完成时不能跳过,也不能自动进入下一步。
  9. 动作等待 3 秒后可以播放对应引导动画。
  10. 所有固定文案可以展示并语音播报。
  11. 完成全部热身步骤后进入关卡选择。

13.2 数据记录验收

  1. 完成向左一步后,可以记录左侧空间边界。
  2. 完成向右一步后,可以记录右侧空间边界。
  3. 完成挥动左手后,可以记录左手挥动空间。
  4. 完成挥动右手后,可以记录右手挥动空间。
  5. 完成原地跳一下后,可以记录跳跃空间。
  6. 以上数据仅在当前 Demo 体验会话内保存。
  7. 重新进入 Demo 后,不沿用上一次热身记录,需要重新完成热身关。

13.3 后续关卡安全边界验收

  1. 用户身体主体覆盖安全边界线时,对应侧屏幕边缘出现虚影提醒。
  2. 用户身体主体超出安全边界线时,关卡内容暂停。
  3. 关卡暂停时,屏幕虚化。
  4. 关卡暂停时,屏幕中央地面出现绿色圆圈。
  5. 关卡暂停时,展示提示文案:
小朋友,要注意安全哦
  1. 用户回到中心绿色圆圈并保持 2 秒后,游戏内容继续。

14. 不确定项与补充确认

当前需求已明确本文所需的热身关开发规格。

以下内容作为待决策事项保留,后续硬件、摄像头和正式关卡设计稳定后再补充:

  1. 具体接入的动作识别 SDK、硬件接口和摄像头接口。
  2. 无硬件、摄像头拒绝授权、多人入镜、识别不到用户、跟踪丢失等异常流程。
  3. 角色剪影、圆环、虚影提醒、特效、手势引导动画的正式资源文件命名。
  4. 绿色圆环、角色剪影、安全边界在线性空间或屏幕坐标中的正式计算公式。
  5. 正式关卡选择页与后续游戏关卡的具体页面结构。

15. 第 3 项本地 Demo 落地记录

本地浏览器 Demo 入口已落在:

/child-motion-demo

当前实现范围:

  1. src/ChildMotionDemoApp.tsx 挂载独立 Demo 应用壳。
  2. src/components/child-motion-demo/childMotionWarmupModel.ts 维护热身步骤、圆环目标、2 秒保持判定、热身校准记录和当前运行时会话完成标记。
  3. src/components/child-motion-demo/ChildMotionWarmupDemo.tsx 实现横屏舞台、背景虚化占位层、角色剪影、绿色圆环、手势引导、热身记录面板、热身完成后的“开始游戏”按钮和下一关占位界面。
  4. src/services/child-motion-demo/childMotionDebugInput.ts 保留开发者调试输入适配层,后续可被正式动作识别 SDK 适配层替换或并行接入。
  5. src/routing/appRoutes.tsx 新增 /child-motion-demo 独立路由,并复用 VITE_ENABLE_EDUTAINMENT_ENTRY 开关;开关关闭时不允许通过该直达路径进入 Demo。

当前调试输入:

  1. A 键映射用户向左移动,松开后回到中心。
  2. D 键映射用户向右移动,松开后回到中心。
  3. 鼠标左键按下并拖动映射左手轨迹。
  4. 鼠标右键按下并拖动映射右手轨迹。
  5. 空格键映射原地跳跃。

当前硬件和动作检测接口接入:

  1. 浏览器摄像头视频流已接入舞台背景。
  2. 热身关全流程已通过 src/services/useMocapInput.ts 接入本地 mocap WebSocket /stream;动作数据源状态优先于浏览器背景摄像头状态展示。
  3. mocap 包支持从 general.body.center_norm 读取身体中心,位置类步骤使用该身体中心更新角色剪影横向位置并完成圆环保持检测。
  4. mocap 包支持从 actions/action/gesture/gestures/event/name/type 读取动作名,并支持 hands[]leftHand/rightHandleft_hand/right_hand 读取左右手坐标。
  5. hands[].landmarks 存在时优先用手腕和 MCP 点计算掌心中心;掌心点不足时退回 wrist landmark再退回 hand 直出坐标。
  6. wave_greeting 可由 wave/wave_greeting/hand_wave/open_palm 等动作或 open palm 手势完成。
  7. wave_left_handwave_right_hand 优先消费对应左右手动作名;当硬件只持续输出手部坐标时,也可以根据连续手部横向轨迹完成挥手检测。
  8. jump_once 消费 jump/jump_once/hop 等跳跃动作事件完成。
  9. 键盘 A/D/Space 与鼠标左右键拖拽仍保留为本地 Demo 调试兜底,不代表正式硬件口径。

当前未接入但已保留边界:

  1. 正式语音播报接口暂不接入,当前先展示热身文案。
  2. 正式 gpt-image-2 视觉资源暂不接入,当前使用 CSS 占位表达相同位置和状态。
  3. 后续关卡安全边界暂停逻辑暂未落地,当前只完成热身记录和下一关按钮占位。

16. 当前视觉资产与生图口径补充

儿童动作 Demo 的视觉口径已经统一收敛到绘本风格草地舞台:

  1. 舞台主环境采用卡通绘本风格、明亮草地、天空、小山坡和树木的组合,默认背景环境需要保证中心与下方前景留空,便于角色轮廓和地面指示环叠加。
  2. src/index.css 中的热身舞台、摄像头背景层、地面、角色轮廓、地面圆环、开始按钮和横屏提示均按绘本草地风格重做,未生成真实背景图时由 CSS 兜底。
  3. 真实背景图的默认输出路径固定为 public/child-motion-demo/picture-book-grass-stage.webp
  4. 生成脚本固定为 scripts/generate-child-motion-demo-assets.mjs,并通过 npm run assets:child-motion-demo 触发;脚本使用 gpt-image-2-all 调用 VectorEngine POST /v1/images/generations
  5. 当前本机工作区未检测到 VECTOR_ENGINE_BASE_URLVECTOR_ENGINE_API_KEY,因此暂时只能完成 dry-run 或代码层接入,不能直接产出真实 image-2 资产。
  6. 若后续补齐 VectorEngine 私密配置,再运行 live 生成即可把真实绘本背景写入上述固定路径,页面会自动读取。

已执行的定向验证命令:

npx eslint src/components/child-motion-demo/ChildMotionWarmupDemo.tsx src/components/child-motion-demo/childMotionWarmupModel.ts src/components/child-motion-demo/ChildMotionWarmupDemo.test.tsx src/components/child-motion-demo/childMotionWarmupModel.test.ts src/services/child-motion-demo/childMotionDebugInput.ts src/services/child-motion-demo/childMotionDebugInput.test.ts src/services/child-motion-demo/index.ts src/ChildMotionDemoApp.tsx src/routing/appRoutes.tsx src/routing/appRoutes.test.ts --ext .ts,.tsx --max-warnings 0
npx vitest run src/components/child-motion-demo/childMotionWarmupModel.test.ts src/components/child-motion-demo/ChildMotionWarmupDemo.test.tsx src/services/child-motion-demo/childMotionDebugInput.test.ts src/routing/appRoutes.test.ts
npm run check:encoding