Issues decoding/parsing response from Stability 3D API

I’ve been attempting to parse the response from the stable-fast-3d response.

I have not been able to successfully load the glb file or the gltf assets.

I am unsure of the methods I should be using to convert the string response into a readable glb or gltf file.
Per the StabilityAI docs: ‘The output is a binary blob that includes a glTF asset, including JSON, buffers, and images. See the GLB File Format Specification for more details.’

I am using threejs library to read the response.

There are four methods that I used that have all led to errors; they are detailed below.

  1. Blob using type ‘model/gltf-binary’ then parsing the Array buffer from the blob

Using the response from the API, create blob instance with ‘model/gltf-binary’
var blob = new Blob([response], {type: ‘model/gltf-binary’});
Get array buffer from blob
const buffer = await blob.arrayBuffer();
Using GLTFLoader from three.js library, parse the buffer.
const loader = new GLTFLoader();
loader.parse(buffer, ‘’, (gltf) => {console.log(gltf);}, (error) => {console.log(‘error’, error); });
This parse method leads to the error below:
RangeError: Offset is outside the bounds of the DataView
at DataView.prototype.getUint32

  1. Blob using type 'application/octet-stream then parsing the Array buffer from the blob
    Using the response from the API, create blob instance with ‘application/octet-stream’
    var blob = new Blob([response], {type: ‘application/octet-stream’});
    Same as Step 2 in 1.2.
    Same as Step 3 in 1.3.
    Parse method leads to the error below:
    Error: THREE.GLTFLoader: JSON content not found.
    at new GLTFBinaryExtension

  2. Loading file from blob with type ‘model/gltf-binary’
    Using the response from the API, create blob instance with ‘model/gltf-binary’
    var blob = new Blob([response], {type: ‘model/gltf-binary’});
    Download the file.
    Pass this file to the GLTFLoader .load method.
    loader.load( // resource URL ‘/dist/response_3d_gltf-binary.glb’, // called when the resource is loaded function ( gltf ) { console.log(gltf); }, // called while loading is progressing function ( xhr ) { console.log( ( xhr.loaded / xhr.total * 100 ) + ‘% loaded’ ); }, // called when loading has errors function ( error ) { console.log(error); console.log( ‘An error happened’ );
    });
    Error below occurs when attempting to load file
    Error: THREE.GLTFLoader: JSON content not found.
    at new GLTFBinaryExtension (GLTFLoader.js:1320:13)

    at GLTFLoader.parse

  3. Loading file from blob with type ‘application/octet-stream’
    Using the response from the API, create blob instance with ‘application/octet-stream’
    var blob = new Blob([response], {type: ‘application/octet-stream’});
    Download the file.
    Pass this file to the GLTFLoader .load method.
    Error below occurs when attempting to load file
    RangeError: Offset is outside the bounds of the DataView
    at DataView.prototype.getUint32 ()

    at new GLTFBinaryExtension (GLTFLoader.js:1302:37)

    at GLTFLoader.parse

I also passed these files from the API response to a GLTF validator. Pics of the validation errors are attached.




Following. Ran into the same issue. Didn’t find a solution yet

Can you post one of the files themselves?

temp1.glb (1.4 MB)
Here’s an example

The validation errors in your screenshots, and for the attached GLB, suggest major errors within the files. Personally, I would not bother trying to load these files into a custom three.js app until you’re sure that they’re working in existing viewers and (preferably) the official glTF validator.

Aside – I’m not sure what the API could be returning that would require you to construct a Blob… What is the type of that ‘response’ object? I would be expecting an ArrayBuffer or Uint8Array from an API that claims to return a GLB. But this might be secondary to the validation errors above.

1 Like

Yeah I looked at that provided glb, and it looks like an actual glb, just the data is like… wrong.

@JonathanG Can you grab an example file from the original repo / and/or link the repo?

@manthrax That’s a file created from blob response from Stable Fast 3d API.
https://platform.stability.ai/docs/api-reference#tag/3D
@donmccurdy the API response is a blob, see the link above.

I’m certain it’s not related to threejs. The response, or my code to create the file, are wrong.

Does your code look like this example?

import axios from "axios";
import FormData from "form-data";
import fs from "node:fs";

const payload = {
    image: fs.createReadStream("./cat-statue.png"),
};

const response = await axios.postForm(
    `https://api.stability.ai/v2beta/3d/stable-fast-3d`,
    axios.toFormData(payload, new FormData()),
    {
        validateStatus: undefined,
        responseType: "arraybuffer",
        headers: {
            Authorization: `Bearer sk-MYAPIKEY`,
        },
    },
);

if (response.status === 200) {
    fs.writeFileSync("./3d-cat-statue.glb", Buffer.from(response.data));
} else {
    throw new Error(`${response.status}: ${response.data.toString()}`);
}

(especially the error check, and just writing/processng the response.data as an array?)

Pretty much yes

export const uploadGLBFromBinary = async (binary: Buffer | ArrayBuffer) => {
  const buffer = Buffer.from(binary);
  const filename = uuidv4();
  const filePath = path.join(os.tmpdir(), `${filename}.glb`);

  fs.writeFileSync(filePath, buffer);

  // Create the file object
  const fileToBeUploaded = {
    filePath,
    basename: filename,
    mimetype: "model/gltf-binary",
    extension: "glb",
    filename: `${filename}.glb`,
  };

  try {
    return await processUpload(fileToBeUploaded);
  } catch (error) {
    console.error("Error uploading GLB file: ", error);
    throw new Error("Error uploading GLB file: " + error);
  } finally {
    fs.unlinkSync(filePath);
  }
};

During my testings I do not unlink the filePath

What’s processUpload look like?

It uploads the files to Cloudinary, but I test the files before the upload (save them locally) and get the same results as @Nathan_Chesmar shows