Save image and then retrieve via client side

If you need the thumbnails to match a configuration I would fire off a batch of WebGL renders so each configuration has an image attributed to it and we can query the Layers API for those images.

It should be a matter of simply making a GET request to a URL similar to something like:
https://{ENV}.threekit.com/api/layers/layer?bearer_token={TOKEN}&assetLayerConfiguration={CONFIG}&assetId={ASSETID}

A couple of things to note:

  1. If you are making this request from the browser, make sure your bearer token is the public token authorized for the domain.
  2. The assetLayerConfiguration will have to be encoded and stringified JSON: encodeURIComponent(JSON.stringify({key: value}))

Finally, this API will return an object similar to the following:

    "id": "f5529722-a3c4-4c1a-8dd7-d2a9c2071323",
    "assetId": "ed74e60a-4a2b-4826-8463-03dff52bfc84",
    "assetLayer": "ed74e60a-4a2b-4826-8463-03dff52bfc84",
    "assetVersion": "",
    "assetLayerConfiguration": {
        "String": "1"
    },
    "stageId": "",
    "stageConfiguration": {},
    "metadata": {},
    "orgId": "e1406626-3f0a-4eb8-aa9b-55b30bd0551d",
    "jobId": "0a03838b-5d29-4af7-a066-e0a4a6d6ba7a",
    "taskId": "f7776a25-5397-4be6-855f-f98dd8ffeefd",
    "fileId": "dc51740d-4bf0-49bb-b2b7-e1176818e1a3",
    "branch": "unpublished",
    "createdAt": "2021-02-12T19:14:39.240Z",
    "format": "png",
    "stageMetadata": null,
    "width": 2000,
    "height": 2000
}

To use the returned fileId as an image, you can retrieve it from our CDN:
https://{ENV}.threekit.com/api/files/{fileId}/content
https://preview.threekit.com/api/files/dc51740d-4bf0-49bb-b2b7-e1176818e1a3/content

Let me know if I can help further.

Hello @Will ,

we need to share the screenshot of the configured product along with the BOM. we have hosted the code on the github. Can you please suggest how we can get the snapshot of the configured product. i am not able to find player.snapshotAsync function.

I have edited your post to remove the link to your in-development project - Will

Hi Prashant, did you see the post directly above yours?

If you create webgl renders from the platform, it will create images of all your available configurations. Then using the layers API you can grab them by sending a config along with the call. Otherwise you can create a data-encoded image which you can do whatever you’d like:

let image = new Image();
let imgSrc = await player.snapshotAsync();
image.src = imgSrc;
// Either append the image or save it somehow
document.body.appendChild(image)

Hello Will,
The WebGL render option may not work for us as the client will keep on adding options so it will be difficult from maintenance.

I was not able to find the function player.SnapshotAsync in our repo app build.

Ah, yes I see now, the player variable is dependent on what you called your player in the embed promise. See the code below for reference and replace player with what you have the player called.

window
  .threekitPlayer({
    authToken: "TOKEN",
    el: document.getElementById("player"),
    stageId: "STAGEID",
    assetId: "ASSETID",
    showConfigurator: true,
    showAR: true,
  })
  .then(async (api) => {
    window.player = player;
    window.configurator = await api.getConfigurator();
  });

Thanks @Will its working now. only the issue is if the customer has rotated the model it give snapshot of the rotated model.

Any fix for that

Please refer to this thread:

The snapshot api will capture the image from current player canvas so you may want to switch to a specific or frame the camera before you take the snapshot

If you need specific cameras or viewpoints, you should investigate the asset-jobs technique to generate images and then use our files API to retrieve them. There is more information in the thread I linked.

Hello @Will,
Nice to see you, you are like everywhere at this forum… I have a question, Do I have to create a Layer first?
What I mean is I am trying to do an endpoint using nodejs to retrieve a image like a thumbnail or snapshot, I am trying this solution with postman because code is somewhat easy but isn’t working for me, using postman… my bearer_token is the one I just created, assetLayoutConfiguration its just a color parameter {“Color”: “Blue”} and the assetID I went to assets and copy the assetid of the asset url.

and I am retrieved this { "status": 404, "code": "layer_not_found", "message": "Layer not found" }
Any thoughts on that?

1 Like

Hey Carlos, you don’t necessarily need to create a layer. Can you let me know what endpoint you are trying to hit and what the body of your API call looks like?

There are a number of approaches to take that will give you a thumbnail or snapshot of the player. What are you trying to accomplish? I just want to make sure I send you in the right direction :+1:

Hello Will,
I am using this endpoint from
GET https://preview.threekit.com/api/layers/layer?bearer_token=[bearer_token]&assetLayerConfiguration=[assetLayerConfiguration]&stageConfiguration=[stageConfiguration]&metadata=[metadata]&resultType=[resultType]

Sometimes the endpoint fetches me a USDZ file format and sometimes I get a png… do you know how can I control it?

Got it. The layers service can do a lot - but, like you said, it is dependent that the ‘layer’ you are trying to retrieve has been created already (I misremembered in my earlier post). It’s important to note that a ‘layer’ can refer to several things:

  • A layer in a layered render
  • A complete render
  • An AR file

If you are trying to capture/create a render or snapshot of an item (and have not created any renders on-platform) you will have to follow a different path, you have two options.

Option #1 - create a snapshot from the player API. This can be done in several lines of code. Keep in mind, this will capture and create an image of exactly what is in the player at that moment. If you have a certain angle in mind, set a camera position before creating the snapshot.

Option #2 - Server side approach. You can create renders by hitting our asset-jobs API

I think either of those may be a better option for you. Let me know if this is helpful.

@Will ,
I was about to post a thread but I think it is better to place questions here.
My approach is to create a snapshot using nodejs, the instructions in my mind are the following:

  1. Create a Layer (a .png render with user input)
    POST https://preview.threekit.com/api/layers?bearer_token=[bearer_token]
  2. Fetch the layer by ID
    GET https://preview.threekit.com/api/layers/layer?bearer_token=[bearer_token]&assetLayerConfiguration=[assetLayerConfiguration]&stageConfiguration=[stageConfiguration]&metadata=[metadata]&resultType=[resultType]
  3. Check if the returned image is .png

I am stuck on the first point, I am getting 403 forbidden and I already added the information, maybe the project has a miss on the configurations?
Bearer token accepts localhost domain but isn’t working… how do I check if the endpoint is working?
Project is: SCS unlimited.

CM.

Can you please elaborate on what you are trying to accomplish? If you are trying to create a snapshot, you can use the Server side approach by hitting our asset-jobs API, which renders an asset using WebGL - what exactly are you trying to do with the layers API?

For the unauthorized issue - when you are using our Server-Side APIs you must use a private token, not a public token.

The asset jobs endpoint: https://preview.threekit.com/api/asset-jobs/:assetId/render/webgl/image?cache=[cache]&wait=[wait]

Body:

  "orgId": "string",
  "configuration": {},
  "stageId": "string",
  "stageConfiguration": {},
  "sync": true,
  "settings": {
    "output": {
      "resolution": {
        "width": 512,
        "height": 512
      }
    }
  }
}

Will, thanks for your patience.
The private token worked for me, now I am trying to retrieve layer’s snapshot…
First I created the layer, here’s the output:

{"id":"260b534f-b37a-4872-a705-b88917cc8d18",
"assetId":"57d1eaaf-5c15-4984-b60d-3944e3b6262d",
"assetLayer":"57d1eaaf-5c15-4984-b60d-3944e3b6262d"
,"assetVersion":"",
"assetLayerConfiguration":
{"Select Color":{"b":0.1450980392156863,"g":0.1450980392156863,"r":0.3058823529411765}},
"stageId":"","stageConfiguration":{},
"metadata":{},"orgId":"fc1f1d00-5484-4460-8ac8-53b3189c5a2d",
"jobId":"",
"taskId":"",
"fileId":"",
"branch":"unpublished",
"createdAt":"2021-08-27T18:28:54.856Z","format":"png","stageMetadata":null,"width":null,"height":null}

Then I retrieved by Id and I am searching the url of the png layer generated:

So as you can see I am searching the layer png url so I can have a snapshot of an asset… I don’t know if you got me this time hehe.

Thanks for your fast communication I appreciate it.

Can you let me know why you are using the layers service rather than the asset-jobs API I suggested? I want to make sure I give you the right resources.

I am trying the approach right now, bearer token should be private too, right?
I am fetching 403 error with nodejs, let me work further and I will giving feed back.

Always, appreciate your help.

I got the server response, how do I fetch the snapshot at the json file? :slight_smile:
@Will

Great! When you POST to the asset-jobs API it will return you an object like this:

    "files": [
        "ddd5ef25-8692-4803-b827-fbd805aea778"
    ],
    "fileId": "ddd5ef25-8692-4803-b827-fbd805aea778",
    "jobId": "e4692b9d-426a-4810-9739-277958b3eda1",
    "job": {
        "_id": "e4692b9d-426a-4810-9739-277958b3eda1",
        "runs": [
            {
                "results": {
                    "files": [
                        {
                            "id": "ddd5ef25-8692-4803-b827-fbd805aea778"
                        }
                    ]
                }
            }
        ]
    }
}

the ID that is in the files array is the FileID that you just created. If you would like to see the information on that file, you can use that ID in an endpoint like this:
https://preview.threekit.com/api/files/${FILE_ID} which will give you JSON about the file:

{
"id": "ddd5ef25-8692-4803-b827-fbd805aea778",
"userId": null,
"filename": "Golf Bag.png",
"createdAt": "2021-08-26T20:08:59.228Z",
"size": 91894,
"hash": "sha256-58fc0f0896d2c470cc9334d5686a9ecaa030e27e5bea18459c6497f49f3c59e9",
"extension": ".png",
"encodings": {
"raw": {
"size": 91894
}
},
"orgId": "e07b8a6e-2281-4173-99ee-088c67fc745c",
"mimeType": "image/png"
}

and to get the image itself, use the same endpoint but add /content to the end.
https://preview.threekit.com/api/files/${FILE_ID}/content

Here is a render I just created:
https://preview.threekit.com/api/files/ddd5ef25-8692-4803-b827-fbd805aea778/content

Thank you very much

Now I can finish to construct the logic, 100k kudos to you :smiley:

CM.

1 Like

Fantastic! Please feel free to reach out if you have any additional questions.

1 Like