-
released this
2026-09-15 21:53:29 +08:00 | 42 commits to main since this releaseOpenDance Studio — Web 管理服务端 v0.2.0
三端开发顺序中的阶段一交付物:NestJS + TypeORM + 现有 MySQL 实例。
v0.2.0 主要变更
- GLB / VRM 确定为模型主力格式,服务端与客户端分别落实支持库;
- 模型管理:
.glb/.vrm直接导入;.pmx/.fbx服务端优先转 GLB、其次 VRM;
压缩包自动搜索包内可用模型;入库自动生成缩略图与模型分析; - 模型审核:上传一律
pending,审核界面含骨骼详细预览(评分基础); - 新增历史模型回填(
POST /api/models/:id/reanalyze+scripts/reanalyze-models.mjs); - 契约升至
rest-api/data-models/model-formats 0.4.0、database 0.3.0。
1. 模型格式策略
上传 服务端行为 .glb/.vrm/.gltf直接导入,不重编码(GLB 含 VRM 扩展会自动识别为 VRM) .pmx/.fbx转换: assimp → .glb→(失败)→ .gltf后自行打包成 GLB →(MODEL_CONVERT_FORMAT=vrm时)补VRMC_vrm扩展产出 VRM 1.0.zip自动搜索包内可用模型: .vrm→.glb→.gltf(直接导入)优先,其次.pmx→.fbx(转换)。同优先级内:指名字 → 目录最浅 → 文件最大每一步都用
assimp info回读校验(Assimp 会写出损坏文件),贴图内嵌进 GLB;
压缩包原件作为model-archive资产留存溯源。客户端支持库:Windows 客户端用 Godot 内置
GLTFDocument加载 glTF/GLB/VRM;
服务端的 humanoid 候选表与客户端humanoid_map.gd逐字对齐,并有单测断言两边一致。2. 自动缩略图与模型分析
- 缩略图(
model-thumbnail.ts):纯 TypeScript 软件光栅化(z-buffer + Lambert +
完整蒙皮矩阵),零原生依赖。512×512 PNG 写入models.thumbnail_asset_id。 - 模型分析(
model-inspector.ts):面数 / 顶点 / 网格 / 材质 / 贴图 / 形变目标 /
动画 / 节点 / 骨骼与骨骼树 / humanoid 覆盖 / 可驱动性,写入models.stats。 - 两者失败都不阻断入库。
3. 模型审核(本次重点)
- 上传的模型状态一律
pending:不再自动发布、不再自动设默认。 - 审核界面新增模型面板:体积、格式、容器、VRM 版本、面数/顶点/网格/材质/贴图/
骨骼/节点/形变目标/动画、humanoid 覆盖进度、可驱动性结论(缺哪些必需骨骼)、
warnings,以及骨骼详细预览(层级缩进、蒙皮/humanoid 徽章、子节点数、
搜索保留祖先链、仅看蒙皮、限高滚动 + 只渲染前 400 行)。 - 通过审核时可勾选**「同时设为全局默认模型」**(
setPrimary=true);单独设置用
POST /api/models/:id/primary(仅published,否则 409)。
为什么骨骼是审核重点:客户端按骨骼名映射 humanoid 规范(22 根,16 根为驱动
33 点所必需)。实测日文 MMD 骨名的 PMX 转 GLB 后覆盖 0/22 → 无法驱动;
某 VRM 只有 7/22;Bip001*命名的 FBX 转 GLB 后 17/22。审核时就能拦下来。4. 历史模型回填(升级必做一次)
升级后旧模型还没有分析与预览图:
cd /opt/opendance/web-server node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000 # 回填全部缺 stats 的 node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000 --dry-run # 只列清单 node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000 --force # 全部重算实测(真实 21 MB VRM / 290 骨骼):回填出面数 53552、顶点 44662、骨骼 290、
humanoid 7/22,并重建 512×512 缩略图。
文件在存储中丢失时接口返回 409 并说明原因(不会用全 0 结果覆盖已有数据);
StorageService.persistBuffer在 sha256 去重命中但文件不存在时会自愈补写
(避免换过STORAGE_DIR、或只恢复数据库后出现"静默全 0 分析")。5. 实测数据
上传 MMD 压缩包(含 Hatsune Miku.pmx) → HTTP 201 / 0.86s / format=glb / status=pending → conversionNote = Hatsune Miku.pmx → GLB,已内嵌 2 张贴图 → 分析:vertices=7155 triangles=9071 bones=238 humanoid=0/22 drivable=false → 缩略图:512×512 PNG / 15,043 字节(目视确认为带蒙皮的 T-pose 角色图) 直接上传 GLB → HTTP 201 / 0.36s / conversionNote = 直接导入(GLB,未做重编码) → 入库文件 sha256 与源文件完全一致(证明没有重编码) 审核 → POST /api/reviews/model/22/approve { setPrimary: true } → 200 → status=published、isPrimary=true;源码种子写入 sourceSha256=72eb6882… → 重建后 GET /api/catalog/export 的 defaultModelId 由 VRM 变为 22 缩略图性能(真实 10MB VRM / 83 关节 / 5307 顶点):60–121ms(中位 79ms) 契约校验 ✓ rest-api/data-models/model-formats 0.4.0、database 0.3.0;路由 30 条一致 类型检查 ✓ tsc --noEmit 通过(strict) 单元测试 ✓ 168 / 168 通过(10 个文件) 生产构建 ✓ nest build + vite build 通过6. 部署更新
cd /root curl -LO https://gitea.kasugano.cn/zijunchiang/opendance-web/releases/download/v0.2.0/opendance-web-v0.2.0.tar.gz curl -LO https://gitea.kasugano.cn/zijunchiang/opendance-web/releases/download/v0.2.0/SHA256SUMS sha256sum -c SHA256SUMS cp /opt/opendance/deploy/.env /root/opendance-env.bak.$(date +%s) # 先备份现网配置 tar -xzf opendance-web-v0.2.0.tar.gz && cd opendance-web-v0.2.0 cp /opt/opendance/deploy/.env deploy/.env grep -q '^ADMIN_PORT=' deploy/.env || echo 'ADMIN_PORT=3001' >> deploy/.env grep -q '^HOST=' deploy/.env || echo 'HOST=0.0.0.0' >> deploy/.env grep -q '^MODEL_CONVERT_FORMAT=' deploy/.env || echo 'MODEL_CONVERT_FORMAT=glb' >> deploy/.env bash deploy/install.sh # 会执行新迁移 AddModelStats # 回填历史模型(一次即可) cd /opt/opendance/web-server && node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000前置:PMX/FBX 转换需要 Assimp(
apt-get install -y assimp-utils libassimp6);
.glb/.vrm直接导入不需要 Assimp。已知事项
- 缩略图是纯色块着色的 T-pose 轮廓图,用于列表页快速辨识;精细预览由管理端
three.js 实时渲染(已放开vrm/glb/gltf,FBX 仍不支持)。 - PMX → GLB 会丢失物理、IK、toon/sphere 贴图、面部表情等 MMD 专有特性,
属格式能力差异(见contracts/model-formats.md§1.1)。 - 模型授权信息需部署方核实后再通过审核。
Downloads