50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
import { join } from 'path'
|
|
import { existsSync } from 'fs'
|
|
import { execFile } from 'child_process'
|
|
import { promisify } from 'util'
|
|
|
|
const execFileAsync = promisify(execFile)
|
|
|
|
/**
|
|
* Compress a GLTF/GLB model using Blender's Draco compression.
|
|
* Returns { success: true } on success, or { success: false, error } on failure.
|
|
* Callers should fall back to the original file on failure.
|
|
*/
|
|
export async function compressWithBlender(
|
|
inputPath: string,
|
|
outputPath: string,
|
|
): Promise<{ success: boolean; error?: string }> {
|
|
const blenderPath = process.env.BLENDER_PATH || 'blender'
|
|
const scriptPath = join(process.cwd(), 'scripts', 'compress.py')
|
|
|
|
if (!existsSync(scriptPath)) {
|
|
return { success: false, error: 'scripts/compress.py introuvable' }
|
|
}
|
|
|
|
try {
|
|
await execFileAsync(
|
|
blenderPath,
|
|
[
|
|
'--background',
|
|
'--python', scriptPath,
|
|
'--',
|
|
'-i', inputPath,
|
|
'-o', outputPath,
|
|
'--draco-level', '7',
|
|
'--texture-size', '512',
|
|
'-q',
|
|
],
|
|
{ timeout: 120_000 },
|
|
)
|
|
|
|
if (!existsSync(outputPath)) {
|
|
return { success: false, error: "Blender n'a pas produit de fichier compresse" }
|
|
}
|
|
|
|
return { success: true }
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err)
|
|
return { success: false, error: `Compression Blender echouee: ${message}` }
|
|
}
|
|
}
|