fix(models): Assimp 缺失时给出可操作报错,部署脚本自动安装
现象:服务器未安装 Assimp,上传 PMX 压缩包只得到 GLB 直出:导出失败(ENOENT):spawn assimp ENOENT glTF 直出:导出失败(ENOENT):spawn assimp ENOENT 用户看不出缺什么、怎么装,也不知道只传 glb/vrm 其实不需要它。 修复: 1. 新增 src/common/assimp.ts:按 ASSIMP_BIN -> PATH -> /usr/bin、/usr/local/bin 等常见目录定位可执行文件(只认文件,不认同名目录),转换前先预检; 找不到就一次性给出各发行版安装命令、查过的路径与替代办法, 不再打两条 ENOENT。动作预处理(FBX/glTF -> BVH)复用同一文案。 2. 新增 deploy/assimp-lib.sh:install.sh 按发行版自动安装 (apt-get / dnf / yum / zypper / apk / pacman),装在非常规目录时把绝对 路径写入 deploy/.env 的 ASSIMP_BIN;装不上只告警不中止,可用 SKIP_ASSIMP_INSTALL=1 跳过。check-access.sh 自检增加 Assimp 一行。 3. /health 增加 assimp.path;管理端「概览 -> 服务健康」显示 Assimp 状态, 不可用时给出安装提示。 4. 新增 test/assimp-locate.spec.ts 13 项;强化「assimp 不存在」用例断言安装命令。 测试规模 12 文件 / 193 项。 5. 版本 0.2.2,README(.md/.txt)/DSH.md 同步(前置要求、FAQ、环境变量说明)。
This commit is contained in:
@@ -4,6 +4,8 @@ import { existsSync } from 'node:fs';
|
||||
import { basename, extname, join } from 'node:path';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
import { assimpMissingMessage, resolveAssimpBinary } from '../common/assimp';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
export const ASSIMP_CONVERT_TIMEOUT_MS = 120_000;
|
||||
@@ -31,10 +33,8 @@ export async function convertToBvhWithAssimp(
|
||||
} catch (error) {
|
||||
const err = error as NodeJS.ErrnoException & { stderr?: string };
|
||||
if (err.code === 'ENOENT') {
|
||||
throw new BadRequestException(
|
||||
`未找到 Assimp 可执行文件「${assimpBin}」。FBX / glTF 动作预处理需要 Assimp(BSD-3-Clause),` +
|
||||
'请安装后设置 ASSIMP_BIN 环境变量;BVH 动作无需 Assimp。',
|
||||
);
|
||||
const location = resolveAssimpBinary(assimpBin);
|
||||
throw new BadRequestException(assimpMissingMessage(assimpBin, location.searched));
|
||||
}
|
||||
const detail = (err.stderr ?? err.message ?? '').toString().trim().slice(0, 500);
|
||||
throw new BadRequestException(`Assimp 转换失败:${detail || '未知错误'}`);
|
||||
@@ -47,16 +47,4 @@ export async function convertToBvhWithAssimp(
|
||||
}
|
||||
|
||||
/** 探测 Assimp 是否可用(用于 /health 与部署自检) */
|
||||
export async function detectAssimp(assimpBin: string): Promise<{ available: boolean; version?: string; error?: string }> {
|
||||
try {
|
||||
const { stdout } = await execFileAsync(assimpBin, ['version'], { timeout: 10_000 });
|
||||
const version = stdout.split(/\r?\n/).find((line) => line.toLowerCase().includes('assimp')) ?? stdout.trim();
|
||||
return { available: true, version: version.trim() };
|
||||
} catch (error) {
|
||||
const err = error as NodeJS.ErrnoException;
|
||||
return {
|
||||
available: false,
|
||||
error: err.code === 'ENOENT' ? `未安装(${assimpBin})` : (err.message ?? '未知错误'),
|
||||
};
|
||||
}
|
||||
}
|
||||
export { detectAssimpBin as detectAssimp } from '../common/assimp';
|
||||
|
||||
Reference in New Issue
Block a user