ai-chatbot/lib/video-canvas/director-glb.ts

43 lines
1.4 KiB
TypeScript

export const DIRECTOR_MAX_GLB_BYTES = 25 * 1024 * 1024;
/** Only self-contained GLB 2.0 files are accepted; external buffers/textures are not portable. */
export function validateDirectorGlb(buffer: ArrayBuffer) {
if (buffer.byteLength < 20 || buffer.byteLength > DIRECTOR_MAX_GLB_BYTES)
throw new Error("请上传 25 MiB 以内的有效 GLB 模型");
const view = new DataView(buffer);
if (
view.getUint32(0, true) !== 0x46546c67 ||
view.getUint32(4, true) !== 2 ||
view.getUint32(8, true) !== buffer.byteLength
)
throw new Error("文件不是有效的 GLB 2.0 模型");
const length = view.getUint32(12, true);
if (
view.getUint32(16, true) !== 0x4e4f534a ||
length % 4 ||
length > buffer.byteLength - 20
)
throw new Error("GLB 场景数据不完整");
let document: any;
try {
document = JSON.parse(
new TextDecoder().decode(new Uint8Array(buffer, 20, length)),
);
} catch {
throw new Error("GLB 场景数据无效");
}
if (
document?.asset?.version !== "2.0" ||
!Array.isArray(document.meshes) ||
!document.meshes.length
)
throw new Error("GLB 中没有可显示的网格");
for (const resource of [
...(document.buffers || []),
...(document.images || []),
]) {
if (resource.uri && !/^data:/i.test(resource.uri))
throw new Error("请将纹理和缓冲区嵌入 GLB 后重新上传");
}
return document;
}