Spaces:
Sleeping
Sleeping
File size: 5,678 Bytes
9557505 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
import { Client } from "@gradio/client";
import dotenv from "dotenv";
dotenv.config();
const TENCENT_3D_SPACE = "tencent/Hunyuan3D-2.1";
const HF_TOKEN = process.env.HF_TOKEN || process.env.hface;
export interface Tencent3DResult {
modelFile: Blob | File | Buffer | null;
htmlOutput: string;
meshStats: any;
seed: number;
}
export async function generate3DModel(
imageBuffer: Buffer,
filename: string,
mimetype: string
): Promise<Tencent3DResult | null> {
try {
console.log(`Connecting to Tencent 3D API for: ${filename}`);
const connectOptions: any = {};
if (HF_TOKEN) {
connectOptions.hf_token = HF_TOKEN;
console.log(` Using HF_TOKEN for authentication`);
} else {
console.warn(` No HF_TOKEN found in environment variables (checked HF_TOKEN and hface)`);
}
const client = await Client.connect(TENCENT_3D_SPACE, connectOptions);
const imageBlob = new Blob([imageBuffer], { type: mimetype });
console.log(`Generating 3D model for: ${filename}`);
const result = await client.predict("/shape_generation", {
image: imageBlob,
mv_image_front: imageBlob,
mv_image_back: imageBlob,
mv_image_left: imageBlob,
mv_image_right: imageBlob,
steps: 30,
guidance_scale: 5,
seed: 1234,
octree_resolution: 256,
check_box_rembg: true,
num_chunks: 8000,
randomize_seed: true,
});
console.log(`3D model generated successfully for: ${filename}`);
const data = result.data as any[];
return {
modelFile: data[0] || null,
htmlOutput: data[1] || "",
meshStats: data[2] || null,
seed: data[3] || 1234,
};
} catch (error: any) {
console.error(`Error generating 3D model for ${filename}:`, error.message);
return null;
}
}
export async function convert3DModelToBase64(
modelFile: Blob | File | Buffer | any
): Promise<string | null> {
try {
let buffer: Buffer;
if (modelFile instanceof Buffer) {
buffer = modelFile;
} else if (modelFile instanceof Blob) {
const arrayBuffer = await modelFile.arrayBuffer();
buffer = Buffer.from(arrayBuffer);
} else if (modelFile instanceof File) {
const arrayBuffer = await modelFile.arrayBuffer();
buffer = Buffer.from(arrayBuffer);
} else if (modelFile && typeof modelFile === 'object') {
// Handle Gradio client file objects
if (typeof modelFile.arrayBuffer === 'function') {
const arrayBuffer = await modelFile.arrayBuffer();
buffer = Buffer.from(arrayBuffer);
} else if (modelFile.value) {
// Gradio file component returns { value: url or object, __type__: "file" }
let fileUrl: string;
if (typeof modelFile.value === 'string') {
fileUrl = modelFile.value;
} else if (modelFile.value && typeof modelFile.value === 'object' && modelFile.value.url) {
fileUrl = modelFile.value.url;
} else if (modelFile.value && typeof modelFile.value === 'object' && modelFile.value.path) {
// Server-side file path
const fs = require('fs');
buffer = fs.readFileSync(modelFile.value.path);
const base64 = buffer.toString("base64");
return `data:model/gltf-binary;base64,${base64}`;
} else {
console.error("Unsupported file value format:", typeof modelFile.value, modelFile.value);
return null;
}
try {
const response = await fetch(fileUrl);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const arrayBuffer = await response.arrayBuffer();
buffer = Buffer.from(arrayBuffer);
} catch (fetchError: any) {
console.error("Error fetching 3D model from URL:", fetchError.message);
return null;
}
} else if (modelFile.url) {
// Gradio returns file objects with URL - fetch the file
try {
const response = await fetch(modelFile.url);
const arrayBuffer = await response.arrayBuffer();
buffer = Buffer.from(arrayBuffer);
} catch (fetchError: any) {
console.error("Error fetching 3D model from URL:", fetchError.message);
return null;
}
} else if (modelFile.data) {
// Handle if it's wrapped in a data property
if (Buffer.isBuffer(modelFile.data)) {
buffer = modelFile.data;
} else if (typeof modelFile.data === 'string') {
// If it's already a base64 string or URL
if (modelFile.data.startsWith('data:')) {
return modelFile.data;
}
buffer = Buffer.from(modelFile.data, 'base64');
} else {
buffer = Buffer.from(modelFile.data);
}
} else if (modelFile.path) {
// If it's a file path (server-side), read it
const fs = require('fs');
buffer = fs.readFileSync(modelFile.path);
} else {
// Try to convert the object to buffer
try {
buffer = Buffer.from(modelFile);
} catch {
console.error("Unsupported file type for 3D model conversion:", typeof modelFile, modelFile.constructor?.name);
return null;
}
}
} else {
console.error("Unsupported file type for 3D model conversion:", typeof modelFile);
return null;
}
const base64 = buffer.toString("base64");
return `data:model/gltf-binary;base64,${base64}`;
} catch (error: any) {
console.error("Error converting 3D model to base64:", error.message);
return null;
}
}
|