docs(readme): 破折号/箭头/省略号/节号改 ASCII,消除 Gitea 混淆字符告警

This commit is contained in:
2026-09-15 21:25:56 +08:00
parent 9f08d316d0
commit 9c8379e5eb
+56 -56
View File
@@ -1,5 +1,5 @@
================================================================ ================================================================
OpenDance Studio —— Web 管理服务端 v0.2.0 使用说明 OpenDance Studio -- Web 管理服务端 v0.2.0 使用说明
================================================================ ================================================================
本服务端是 OpenDance Studio 三端中的第一端, 负责管理歌曲、VRM 模型与 本服务端是 OpenDance Studio 三端中的第一端, 负责管理歌曲、VRM 模型与
@@ -8,9 +8,9 @@ OpenDance Studio —— Web 管理服务端 v0.2.0 使用说明
重要: 本服务端 **不部署、不管理 MySQL**。数据库为部署方提供的现有实例, 重要: 本服务端 **不部署、不管理 MySQL**。数据库为部署方提供的现有实例,
连接信息通过 .env 注入。 连接信息通过 .env 注入。
---------------------------------------------------------------- --
一、部署到 Linux 服务器(业务服务, 不含反向代理) 一、部署到 Linux 服务器(业务服务, 不含反向代理)
---------------------------------------------------------------- --
职责边界 职责边界
本端**只提供业务服务**:NestJS API + 管理端页面。 本端**只提供业务服务**:NestJS API + 管理端页面。
@@ -60,15 +60,15 @@ OpenDance Studio —— Web 管理服务端 v0.2.0 使用说明
vi deploy/.env # 填写 DB_HOST / DB_PORT / DB_USER / DB_PASS / DB_NAME vi deploy/.env # 填写 DB_HOST / DB_PORT / DB_USER / DB_PASS / DB_NAME
脚本会依次: 脚本会依次:
校验环境与 .env → 创建服务用户与目录 → 复制程序文件 → 校验环境与 .env -> 创建服务用户与目录 -> 复制程序文件 ->
安装运行期依赖 → 执行 TypeORM 迁移 → 安装运行期依赖 -> 执行 TypeORM 迁移 ->
注册并启动系统服务(systemd / OpenRC / SysVinit / 后台进程)→ 等待健康检查 注册并启动系统服务(systemd / OpenRC / SysVinit / 后台进程)-> 等待健康检查
deploy/.env 初始化引导(deploy/init-env.sh) deploy/.env 初始化引导(deploy/init-env.sh)
缺 deploy/.env 时, install.sh 会先调用本脚本引导填写; 引导失败才中止安装 缺 deploy/.env 时, install.sh 会先调用本脚本引导填写; 引导失败才中止安装
(若安装目录里已有上次安装留下的 .env, 则直接复用, 不会重复提问)。 (若安装目录里已有上次安装留下的 .env, 则直接复用, 不会重复提问)。
也可以单独运行: 逐项询问数据库与端口, 回车保留默认值, 写盘前做必填项与 也可以单独运行: 逐项询问数据库与端口, 回车保留默认值, 写盘前做必填项与
端口范围校验, 并可用项目自带的 mysql2 做一次数据库连通性自检——口令只经 端口范围校验, 并可用项目自带的 mysql2 做一次数据库连通性自检--口令只经
环境变量传给子进程, 出错信息与摘要一律显示 ***。 环境变量传给子进程, 出错信息与摘要一律显示 ***。
bash deploy/init-env.sh # 交互引导(终端里逐项询问) bash deploy/init-env.sh # 交互引导(终端里逐项询问)
@@ -112,8 +112,8 @@ deploy/.env 初始化引导(deploy/init-env.sh)
对外访问 对外访问
由反向代理**按用途分别转发两个端口**: 由反向代理**按用途分别转发两个端口**:
浏览器管理界面 → http://<后端地址>:3001 浏览器管理界面 -> http://<后端地址>:3001
Windows/Godot 客户端与 Android App → http://<后端地址>:3000 Windows/Godot 客户端与 Android App -> http://<后端地址>:3000
配置样例与说明(含两个端口的转发写法): 配置样例与说明(含两个端口的转发写法):
deploy/proxy/nginx.conf.example nginx 站点配置 deploy/proxy/nginx.conf.example nginx 站点配置
deploy/proxy/web.config.example IIS(ARR + URL Rewrite)配置 deploy/proxy/web.config.example IIS(ARR + URL Rewrite)配置
@@ -164,9 +164,9 @@ deploy/.env 初始化引导(deploy/init-env.sh)
反代配置: 不在本机, 无需在此维护 反代配置: 不在本机, 无需在此维护
---------------------------------------------------------------- --
二、本地开发 二、本地开发
---------------------------------------------------------------- --
后端 后端
cd web-server cd web-server
@@ -180,9 +180,9 @@ deploy/.env 初始化引导(deploy/init-env.sh)
npm install npm install
npm run dev # http://localhost:5173(/api 与 /health 代理到 3000) npm run dev # http://localhost:5173(/api 与 /health 代理到 3000)
---------------------------------------------------------------- --
三、验证 三、验证
---------------------------------------------------------------- --
cd web-server cd web-server
npm run contracts:check # 契约版本一致性 npm run contracts:check # 契约版本一致性
@@ -197,9 +197,9 @@ deploy/.env 初始化引导(deploy/init-env.sh)
cd ../admin && npm run build # 管理端构建 cd ../admin && npm run build # 管理端构建
---------------------------------------------------------------- --
四、环境变量 四、环境变量
---------------------------------------------------------------- --
DB_HOST / DB_PORT / DB_USER / DB_PASS / DB_NAME DB_HOST / DB_PORT / DB_USER / DB_PASS / DB_NAME
现有 MySQL 实例连接信息(必填) 现有 MySQL 实例连接信息(必填)
@@ -238,7 +238,7 @@ deploy/.env 初始化引导(deploy/init-env.sh)
humanoid 骨骼映射不全时自动回退交付 GLB 并写进 conversion_note。 humanoid 骨骼映射不全时自动回退交付 GLB 并写进 conversion_note。
产物一律用 `assimp info` 回读校验 产物一律用 `assimp info` 回读校验
MODEL_CONVERT_PMX 压缩包内优先选用的 PMX 文件名(默认 Hatsune Miku.pmx, MODEL_CONVERT_PMX 压缩包内优先选用的 PMX 文件名(默认 Hatsune Miku.pmx,
大小写不敏感); 找不到时按「格式优先级 → 目录最浅 → 大小写不敏感); 找不到时按「格式优先级 -> 目录最浅 ->
文件最大」挑选 文件最大」挑选
MODEL_CONVERT_TIMEOUT_MS MODEL_CONVERT_TIMEOUT_MS
单次转换超时(毫秒, 默认 180000) 单次转换超时(毫秒, 默认 180000)
@@ -247,9 +247,9 @@ deploy/.env 初始化引导(deploy/init-env.sh)
CONTRACTS_DIR 可选: 契约目录, 设置后 /health 反映实时契约版本 CONTRACTS_DIR 可选: 契约目录, 设置后 /health 反映实时契约版本
(原生部署默认指向 /opt/opendance/contracts) (原生部署默认指向 /opt/opendance/contracts)
---------------------------------------------------------------- --
五、主要 API 五、主要 API
---------------------------------------------------------------- --
GET /health 健康检查(含数据库连通性) GET /health 健康检查(含数据库连通性)
GET /api/songs 曲目列表(分页 / 检索) GET /api/songs 曲目列表(分页 / 检索)
@@ -260,7 +260,7 @@ deploy/.env 初始化引导(deploy/init-env.sh)
POST /api/songs/:id/audio 上传音频 POST /api/songs/:id/audio 上传音频
GET /api/motions 动作列表 GET /api/motions 动作列表
POST /api/motions 上传动作 + 来源信息 POST /api/motions 上传动作 + 来源信息
POST /api/motions/:id/preprocess BVH/VMD/FBX → MediaPipe33 关键点 POST /api/motions/:id/preprocess BVH/VMD/FBX -> MediaPipe33 关键点
GET /api/motions/:id/keypoints 下载关键点序列(NDJSON) GET /api/motions/:id/keypoints 下载关键点序列(NDJSON)
GET /api/models 模型列表 GET /api/models 模型列表
POST /api/models 上传模型 + 来源信息(.glb/.vrm/.gltf POST /api/models 上传模型 + 来源信息(.glb/.vrm/.gltf
@@ -283,13 +283,13 @@ deploy/.env 初始化引导(deploy/init-env.sh)
(Godot 客户端用内置 GLTFDocument 加载 glTF/GLB/VRM, 见 (Godot 客户端用内置 GLTFDocument 加载 glTF/GLB/VRM, 见
opendance-windows/src/model/vrm_loader.gd, 本次无需改动)。 opendance-windows/src/model/vrm_loader.gd, 本次无需改动)。
glTF Binary .glb 主力(P0)—— **直接导入**, 不重编码 glTF Binary .glb 主力(P0)-- **直接导入**, 不重编码
VRM .vrm 主力(P0)—— 直接导入; GLB + VRM 扩展 VRM .vrm 主力(P0)-- 直接导入; GLB + VRM 扩展
(humanoid / 表情 / springBone / meta) (humanoid / 表情 / springBone / meta)
glTF .gltf P1 —— 直接导入(分离的 .bin / 贴图需随 .zip 一起上传) glTF .gltf P1 -- 直接导入(分离的 .bin / 贴图需随 .zip 一起上传)
MMD 压缩包 .zip P1 —— **自动搜索包内可用模型**(见下) MMD 压缩包 .zip P1 -- **自动搜索包内可用模型**(见下)
MMD 模型 .pmx P2(输入)—— 服务端转换, 优先 GLB、其次 VRM MMD 模型 .pmx P2(输入)-- 服务端转换, 优先 GLB、其次 VRM
FBX .fbx P2(输入)—— 服务端转换, 优先 GLB、其次 VRM FBX .fbx P2(输入)-- 服务端转换, 优先 GLB、其次 VRM
入库后**一律 status=pending(待审核)**: 上传不再自动发布、不再自动设为默认, 入库后**一律 status=pending(待审核)**: 上传不再自动发布、不再自动设为默认,
必须经审核通过(模型审核面板可勾选「同时设为全局默认模型」)才对客户端可见。 必须经审核通过(模型审核面板可勾选「同时设为全局默认模型」)才对客户端可见。
@@ -304,13 +304,13 @@ deploy/.env 初始化引导(deploy/init-env.sh)
模型压缩包(.zip)自动搜索与转换 模型压缩包(.zip)自动搜索与转换
上传的 .zip 不再"只找 .pmx", 而是**自动搜索包内可用模型**, 走 上传的 .zip 不再"只找 .pmx", 而是**自动搜索包内可用模型**, 走
"解压 → 选主模型 → 直接导入或转换 → 回读校验 → 入库", 而不是把压缩包当模型存下来。 "解压 -> 选主模型 -> 直接导入或转换 -> 回读校验 -> 入库", 而不是把压缩包当模型存下来。
选主模型 优先级 .vrm → .glb → .gltf → .pmx → .fbx; 同一优先级内按 选主模型 优先级 .vrm -> .glb -> .gltf -> .pmx -> .fbx; 同一优先级内按
"MODEL_CONVERT_PMX 指名字 → 目录最浅 → 文件最大"。 "MODEL_CONVERT_PMX 指名字 -> 目录最浅 -> 文件最大"。
命中 .vrm/.glb/.gltf 时**直接导入**(不重编码)。 命中 .vrm/.glb/.gltf 时**直接导入**(不重编码)。
转换 只有 .pmx/.fbx 需要转换。链路: assimp export → .glb(首选); 转换 只有 .pmx/.fbx 需要转换。链路: assimp export -> .glb(首选);
失败则 assimp export → .gltf, 再由 gltf-packer.ts 自行打包回 GLB; 失败则 assimp export -> .gltf, 再由 gltf-packer.ts 自行打包回 GLB;
MODEL_CONVERT_FORMAT=vrm 时在 GLB 之上补 VRMC_vrm 扩展封装成 MODEL_CONVERT_FORMAT=vrm 时在 GLB 之上补 VRMC_vrm 扩展封装成
VRM 1.0(humanoid 骨骼不全则回退交付 GLB, 缺失骨骼写进说明)。 VRM 1.0(humanoid 骨骼不全则回退交付 GLB, 缺失骨骼写进说明)。
校验 每一步产物**必须**用 `assimp info` 回读校验。Assimp 会"写出损坏文件" 校验 每一步产物**必须**用 `assimp info` 回读校验。Assimp 会"写出损坏文件"
@@ -319,10 +319,10 @@ deploy/.env 初始化引导(deploy/init-env.sh)
贴图 GLB 产物里 Assimp 会把贴图写成外部 URI(还带反斜杠), 服务端把 贴图 GLB 产物里 Assimp 会把贴图写成外部 URI(还带反斜杠), 服务端把
压缩包内 / .gltf 同目录的贴图内嵌进 GLB 的二进制块, 保证单文件可加载。 压缩包内 / .gltf 同目录的贴图内嵌进 GLB 的二进制块, 保证单文件可加载。
说明 每次尝试写入 models.conversion_note, 例如 说明 每次尝试写入 models.conversion_note, 例如
`Hatsune Miku.pmx → GLB, 已内嵌 2 张贴图`。 `Hatsune Miku.pmx -> GLB, 已内嵌 2 张贴图`。
溯源 压缩包原件以 model-archive 资产留存, 写入 models.source_asset_id; 溯源 压缩包原件以 model-archive 资产留存, 写入 models.source_asset_id;
迁移 AddModelConversionFields1789450000000。 迁移 AddModelConversionFields1789450000000。
失败 包内没有可用模型、Assimp 不可用、两条路径都失败 → HTTP 422, 失败 包内没有可用模型、Assimp 不可用、两条路径都失败 -> HTTP 422,
不产生模型记录。 不产生模型记录。
文件名编码 upload.util.ts 的 decodeUploadName() 修正 multipart 文件名的 文件名编码 upload.util.ts 的 decodeUploadName() 修正 multipart 文件名的
@@ -332,13 +332,13 @@ deploy/.env 初始化引导(deploy/init-env.sh)
新增字段 DTO/契约新增 conversionNote、fileSha256、stats、thumbnailUrl。 新增字段 DTO/契约新增 conversionNote、fileSha256、stats、thumbnailUrl。
实测(Assimp 6.0.4): 实测(Assimp 6.0.4):
- 上传含 `Hatsune Miku.pmx` 的 MMD 压缩包 → HTTP 201 / 0.86s、format=glb、 - 上传含 `Hatsune Miku.pmx` 的 MMD 压缩包 -> HTTP 201 / 0.86s、format=glb、
status=pending、conversionNote=`Hatsune Miku.pmx → GLB, 已内嵌 2 张贴图`。 status=pending、conversionNote=`Hatsune Miku.pmx -> GLB, 已内嵌 2 张贴图`。
分析结果: vertices=7155 triangles=9071 materials=3 textures=2 images=2 分析结果: vertices=7155 triangles=9071 materials=3 textures=2 images=2
nodes=240 bones=238 skins=1 morphTargets=0 humanoidMapped=0/22 drivable=false nodes=240 bones=238 skins=1 morphTargets=0 humanoidMapped=0/22 drivable=false
maxBoneDepth=23;missingRequiredBones 为全部 16 根 maxBoneDepth=23;missingRequiredBones 为全部 16 根
(日文 MMD 骨名无法映射到 humanoid, 审核界面会直接标红)。 (日文 MMD 骨名无法映射到 humanoid, 审核界面会直接标红)。
- 直接上传 .glb → HTTP 201 / 0.36s、conversionNote=`直接导入(GLB, 未做重编码)`, - 直接上传 .glb -> HTTP 201 / 0.36s、conversionNote=`直接导入(GLB, 未做重编码)`,
入库文件 sha256 与源文件**一致**(不重编码, 字节级保留)。 入库文件 sha256 与源文件**一致**(不重编码, 字节级保留)。
模型分析、缩略图与 3D 预览(入库后自动执行, 失败不影响入库) 模型分析、缩略图与 3D 预览(入库后自动执行, 失败不影响入库)
@@ -346,13 +346,13 @@ deploy/.env 初始化引导(deploy/init-env.sh)
节点 / 形变目标 / 动画 / 蒙皮骨骼数 / **骨骼树** / humanoid 覆盖 / 节点 / 形变目标 / 动画 / 蒙皮骨骼数 / **骨骼树** / humanoid 覆盖 /
可驱动性(缺哪些必需骨骼)/ warnings, 写入 models.stats 可驱动性(缺哪些必需骨骼)/ warnings, 写入 models.stats
(迁移 AddModelStats1789460000000, 新增 models.stats TEXT)。 (迁移 AddModelStats1789460000000, 新增 models.stats TEXT)。
缩略图 model-thumbnail.ts 用纯 TS 软件光栅化生成 PNG(读 GLB/glTF → 应用节点 缩略图 model-thumbnail.ts 用纯 TS 软件光栅化生成 PNG(读 GLB/glTF -> 应用节点
层级与蒙皮 → 包围盒自动构图 → 透视投影 → z-buffer 逐三角形平面着色 → 层级与蒙皮 -> 包围盒自动构图 -> 透视投影 -> z-buffer 逐三角形平面着色 ->
手写 PNG 编码),**零原生依赖**(不需要 canvas / headless-gl / puppeteer)。 手写 PNG 编码),**零原生依赖**(不需要 canvas / headless-gl / puppeteer)。
默认 512x512, 写入 models.thumbnail_asset_id / thumbnailUrl; 默认 512x512, 写入 models.thumbnail_asset_id / thumbnailUrl;
失败或非 glTF 容器时留空, 列表页退化为格式占位图。 失败或非 glTF 容器时留空, 列表页退化为格式占位图。
实测: 512x512 PNG / 15,043 字节, 目视确认为居中的 T-pose 角色图; 实测: 512x512 PNG / 15,043 字节, 目视确认为居中的 T-pose 角色图;
真实 10MB VRM(83 关节、5307 顶点)单张耗时 60–121ms(中位 79ms)。 真实 10MB VRM(83 关节、5307 顶点)单张耗时 60-121ms(中位 79ms)。
预览 管理端 3D 预览放开到 vrm/glb/gltf(.fbx 仍提示「仅归档, 请先转换为 预览 管理端 3D 预览放开到 vrm/glb/gltf(.fbx 仍提示「仅归档, 请先转换为
GLB/VRM」); 列表页显示 40px 小缩略图, 审核面板显示 116px 缩略图。 GLB/VRM」); 列表页显示 40px 小缩略图, 审核面板显示 116px 缩略图。
@@ -365,7 +365,7 @@ deploy/.env 初始化引导(deploy/init-env.sh)
骨骼预览 骨骼详细界面: 扁平骨骼树按 depth 缩进、显示骨骼名、是否参与蒙皮、 骨骼预览 骨骼详细界面: 扁平骨骼树按 depth 缩进、显示骨骼名、是否参与蒙皮、
humanoid 映射徽章、子节点数; 支持按名搜索(保留祖先链)、 humanoid 映射徽章、子节点数; 支持按名搜索(保留祖先链)、
「仅显示蒙皮骨骼」开关、限高滚动 + 只渲染前 400 行(千根骨骼不卡)。 「仅显示蒙皮骨骼」开关、限高滚动 + 只渲染前 400 行(千根骨骼不卡)。
通过 勾选「同时设为全局默认模型」→ 请求体带 `setPrimary:true` 通过 勾选「同时设为全局默认模型」-> 请求体带 `setPrimary:true`
(`POST /api/reviews/model/:id/approve`); 此时才写库 is_primary (`POST /api/reviews/model/:id/approve`); 此时才写库 is_primary
并把默认模型身份写进源码 src/config/default-model.ts。 并把默认模型身份写进源码 src/config/default-model.ts。
单独设置 `POST /api/models/:id/primary`(仅 published 允许, 否则 409)。 单独设置 `POST /api/models/:id/primary`(仅 published 允许, 否则 409)。
@@ -375,19 +375,19 @@ deploy/.env 初始化引导(deploy/init-env.sh)
GET /api/catalog/export 的 defaultModelId 按以下顺序解析: GET /api/catalog/export 的 defaultModelId 按以下顺序解析:
0. 环境变量 DEFAULT_MODEL_ID(且模型存在且已发布) 0. 环境变量 DEFAULT_MODEL_ID(且模型存在且已发布)
1. 源码种子 src/config/default-model.ts 的 DEFAULT_MODEL_SEED——按**上传压缩包的 1. 源码种子 src/config/default-model.ts 的 DEFAULT_MODEL_SEED--按**上传压缩包的
sha256** 匹配已发布模型(用户文件永远稳定; 不能用转换产物的 sha256 —— sha256** 匹配已发布模型(用户文件永远稳定; 不能用转换产物的 sha256 --
Assimp 每次导出的字节都略有不同), 换库 / 重建库后仍有效 Assimp 每次导出的字节都略有不同), 换库 / 重建库后仍有效
2. format='vrm' 且 published 且 is_primary=1 2. format='vrm' 且 published 且 is_primary=1
3. 任意 published 的 VRM(id 升序取第一个) 3. 任意 published 的 VRM(id 升序取第一个)
4. id 最小的已发布模型 4. id 最小的已发布模型
5. 无可用模型 → 客户端用内置占位模型 5. 无可用模型 -> 客户端用内置占位模型
源码种子 src/config/default-model.ts 当前为**空种子**(占位: id=null、sha256 空串), 源码种子 src/config/default-model.ts 当前为**空种子**(占位: id=null、sha256 空串),
此时 defaultModelId 直接从第 2 步的 VRM 优先规则开始解析; 按下面的方式设定默认 此时 defaultModelId 直接从第 2 步的 VRM 优先规则开始解析; 按下面的方式设定默认
模型后, 服务端会把种子写成真实内容。 模型后, 服务端会把种子写成真实内容。
实测(v0.2.0):`POST /api/reviews/model/22/approve` 带 `setPrimary:true` → 200, 实测(v0.2.0):`POST /api/reviews/model/22/approve` 带 `setPrimary:true` -> 200,
模型 status=published、isPrimary=true, 源码种子写入 sourceSha256=72eb6882…; 模型 status=published、isPrimary=true, 源码种子写入 sourceSha256=72eb6882...;
重建后 `GET /api/catalog/export` 的 defaultModelId 由 VRM 变为 **22** 重建后 `GET /api/catalog/export` 的 defaultModelId 由 VRM 变为 **22**
(库中另有 2 个已发布 VRM)。 (库中另有 2 个已发布 VRM)。
也可手工指定: POST /api/models/:id/primary。 也可手工指定: POST /api/models/:id/primary。
@@ -406,7 +406,7 @@ deploy/.env 初始化引导(deploy/init-env.sh)
--source-name "模型_初音未来Hatsune Miku_by_Boku_Wa_Luka.zip" \ --source-name "模型_初音未来Hatsune Miku_by_Boku_Wa_Luka.zip" \
--source-url "本地文件: 模型_初音未来Hatsune Miku_by_Boku_Wa_Luka.zip" \ --source-url "本地文件: 模型_初音未来Hatsune Miku_by_Boku_Wa_Luka.zip" \
--source-type other --source-type other
# 上传 → 服务端转换入库(pending)→ 把身份写进 src/config/default-model.ts # 上传 -> 服务端转换入库(pending)-> 把身份写进 src/config/default-model.ts
node scripts/import-default-model.mjs --write-source-only --model-id 22 node scripts/import-default-model.mjs --write-source-only --model-id 22
# 只根据已入库模型补写源码, 不调上传 API # 只根据已入库模型补写源码, 不调上传 API
@@ -419,7 +419,7 @@ deploy/.env 初始化引导(deploy/init-env.sh)
要让它在 `defaultModelId` 中生效, 仍需在管理端**审核通过**(勾选「同时设为全局 要让它在 `defaultModelId` 中生效, 仍需在管理端**审核通过**(勾选「同时设为全局
默认模型」)或调用 `POST /api/models/:id/primary`。 默认模型」)或调用 `POST /api/models/:id/primary`。
支持的动作格式(POST /api/motions 上传 → POST /api/motions/:id/preprocess 预处理) 支持的动作格式(POST /api/motions 上传 -> POST /api/motions/:id/preprocess 预处理)
BVH .bvh 内置纯 TS 解析器, 保留源帧率 BVH .bvh 内置纯 TS 解析器, 保留源帧率
VMD .vmd 内置解析(MikuMikuDance), 固定 30fps; VMD .vmd 内置解析(MikuMikuDance), 固定 30fps;
腿部按「足IK是否带位移」自动选 IK 或 FK 腿部按「足IK是否带位移」自动选 IK 或 FK
@@ -441,9 +441,9 @@ VMD 动作上传前后自查
它会打印头部 / 模型名 / 帧数 / 轨道数、未识别骨骼、走 IK 还是 FK、关键点 它会打印头部 / 模型名 / 帧数 / 轨道数、未识别骨骼、走 IK 还是 FK、关键点
序列异常统计与膝肘角分布。上传后再调用 /preprocess 走正式通路。 序列异常统计与膝肘角分布。上传后再调用 /preprocess 走正式通路。
---------------------------------------------------------------- --
六、目录结构 六、目录结构
---------------------------------------------------------------- --
project.yaml 任务清单与状态 project.yaml 任务清单与状态
DSH.md 本项目 DSH 执行约束 DSH.md 本项目 DSH 执行约束
@@ -452,10 +452,10 @@ VMD 动作上传前后自查
web-server/ NestJS 服务端源码 web-server/ NestJS 服务端源码
web-server/admin/ React 管理端 web-server/admin/ React 管理端
web-server/src/common/zip-reader.ts 纯 TS ZIP 读取器 web-server/src/common/zip-reader.ts 纯 TS ZIP 读取器
web-server/src/models/model-convert.ts .zip/.pmx/.fbx → GLB/VRM 转换 web-server/src/models/model-convert.ts .zip/.pmx/.fbx -> GLB/VRM 转换
web-server/src/models/gltf-packer.ts glTF(分离文件)→ GLB 打包 web-server/src/models/gltf-packer.ts glTF(分离文件)-> GLB 打包
web-server/src/models/glb-textures.ts GLB 贴图内嵌 web-server/src/models/glb-textures.ts GLB 贴图内嵌
web-server/src/models/vrm-writer.ts GLB → VRM 1.0 封装(写 VRMC_vrm 扩展) web-server/src/models/vrm-writer.ts GLB -> VRM 1.0 封装(写 VRMC_vrm 扩展)
web-server/src/models/model-inspector.ts 模型检查器(面数/骨骼树/humanoid 覆盖) web-server/src/models/model-inspector.ts 模型检查器(面数/骨骼树/humanoid 覆盖)
web-server/src/models/model-thumbnail.ts 纯 TS 光栅化缩略图(零原生依赖) web-server/src/models/model-thumbnail.ts 纯 TS 光栅化缩略图(零原生依赖)
web-server/src/config/default-model.ts 默认模型种子(服务端/CLI 写入) web-server/src/config/default-model.ts 默认模型种子(服务端/CLI 写入)
@@ -470,9 +470,9 @@ VMD 动作上传前后自查
deploy/proxy/ 反向代理配置说明(nginx / IIS, 仅供参考不部署) deploy/proxy/ 反向代理配置说明(nginx / IIS, 仅供参考不部署)
THIRD_PARTY.md 第三方开源项目声明 THIRD_PARTY.md 第三方开源项目声明
---------------------------------------------------------------- --
七、安全提示 七、安全提示
---------------------------------------------------------------- --
1. .env 已被 .gitignore 忽略, 禁止提交; 仓库中只保留 .env.example。 1. .env 已被 .gitignore 忽略, 禁止提交; 仓库中只保留 .env.example。
2. 数据库账号使用最小权限, 不授予 GRANT OPTION / FILE / SUPER。 2. 数据库账号使用最小权限, 不授予 GRANT OPTION / FILE / SUPER。
@@ -480,11 +480,11 @@ VMD 动作上传前后自查
4. 上传的模型与动作默认需填写来源五元组并通过审核后才对客户端可见。 4. 上传的模型与动作默认需填写来源五元组并通过审核后才对客户端可见。
**模型上传后一律 pending**: 不再自动发布、不再自动设为默认; 默认模型只在 **模型上传后一律 pending**: 不再自动发布、不再自动设为默认; 默认模型只在
审核通过时勾选「同时设为全局默认模型」(`setPrimary:true`)或调用 审核通过时勾选「同时设为全局默认模型」(`setPrimary:true`)或调用
`POST /api/models/:id/primary`(仅 published)时才设置(见 §五)。 `POST /api/models/:id/primary`(仅 published)时才设置(见 五)。
5. 未使用 SMPL 拓扑, 统一 MediaPipe 33 点, 规避非商用许可限制。 5. 未使用 SMPL 拓扑, 统一 MediaPipe 33 点, 规避非商用许可限制。
---------------------------------------------------------------- --
八、第三方开源声明 八、第三方开源声明
---------------------------------------------------------------- --
见 THIRD_PARTY.md, 或访问站点 http://<host>/ 的「关于」页面。 见 THIRD_PARTY.md, 或访问站点 http://<host>/ 的「关于」页面。