Files
opendance-web/tasks/004-motion-upload.md

84 lines
3.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# T-WEB-004 动作数据上传 + 来源字段
- **状态**:done
- **依赖**:T-WEB-002
## 目标
上传动作文件(BVH / VMD / FBX / glTF / GLB / keypoints-json),**强制填写来源五元组**。
## load
```
DSH.md
contracts/rest-api.yaml # 锚点:#/paths/~1api~1motions
contracts/data-models.md # 锚点:3 Motion
contracts/model-formats.md # 锚点:2 动作格式、3 上传限制
web-server/src/motions/*
web-server/src/storage/storage.service.ts
web-server/src/preprocess/vmd-parser.ts # VMD 上传后的预处理链路
web-server/src/preprocess/mmd-skeleton.ts
web-server/src/preprocess/mmd-pose.ts
web-server/src/preprocess/retarget.ts # worldFramesToKeypointFrames()
```
## 端点
| 方法 | 路径 | 说明 |
|--|--|--|
| GET | `/api/motions` | 分页 + `q`/`songId`/`format`/`status` 过滤 |
| POST | `/api/motions` | multipart 上传 |
| GET | `/api/motions/:id` | 详情 |
| PATCH | `/api/motions/:id` | 更新元数据(含 `detachSong`) |
| DELETE | `/api/motions/:id` | 软删除 |
## 存储策略(`contracts/model-formats.md` 3)
```
${STORAGE_DIR}/{kind}/{yyyy}/{mm}/{sha256前2位}/{sha256}.{ext}
```
- 上传先落 `${STORAGE_DIR}/tmp`(multer diskStorage),避免大文件占用内存
- `StorageService` 流式计算 sha256;**相同内容只落盘一次**,复用 `assets` 记录
- 并发同文件上传靠 `assets.sha256` 唯一索引兜底,冲突后回退到已存在记录
- 路径永不使用原始文件名;`absolutePath()` 拒绝逃逸存储根目录
## 校验
- 扩展名白名单:`.bvh.vmd.fbx.gltf.glb.json`,其他 -> 400
- 来源五元组缺任一项 -> 400
- `songId` 指向不存在的曲目 -> 400
- 单文件上限 `UPLOAD_MAX_BYTES`(默认 512 MiB)
## VMD 支持(`.vmd`)
- 管理端上传控件已支持 `.vmd`(accept、格式筛选、中文标签「VMD(MMD)」)
- 入库后 `format=vmd`;预处理走内置链路,不依赖 Assimp:
`vmd-parser.ts`(二进制 + Shift-JIS + 贝塞尔插值)-> `mmd-skeleton.ts`(标准骨架)
-> `mmd-pose.ts`(FK + 腿部 IK + Z 镜像)-> `retarget.ts` 的
`worldFramesToKeypointFrames()`(与 BVH 共用骨盆归零 / 自适应缩放 / 投影 / 关节角)
- 固定 30 fps;腿部按 `足IK` 是否带位移自动选 IK 或 FK
- 上传后处理失败与 BVH 一致:写入 `preprocessState=failed` 与可读错误
## 验收
```bash
npm run test:smoke
```
冒烟 [2] 段落:上传 201、自动识别 `format=bvh`、`fileSize` 记录、缺来源 400、
`evil.exe` 400。
VMD 实测(用 `../示例文件/` 下的两个样本):
| 样本 | 帧数 | 腿部驱动 | 结果 |
|--|--|--|--|
| `【动作】霜雪千年.vmd`(0.79 MiB) | 2901 | `足IK` 驱动(IK) | 0 NaN / 0 越界,预处理约 0.4s |
| `恋爱循环.vmd`(20.24 MiB) | 4604 | 烘焙 FK | 0 NaN / 0 越界,预处理约 2.5s |
上传前可先用诊断工具自查(只读):
```bash
node scripts/inspect-vmd.mjs 动作.vmd [--frames N] [--json out.json]
```