Save image and then retrieve via client side

Is it possible to use the pure client side Configurator API in the browser to save a snapshot of the rendered model and then retrieve it? Or do I have to use the serverside api? I am using Axios.

This is definitely possible from the client-side API. If you have an embedded player you can do a quick test with these 4 lines of code and it will capture the current contents in the player:

let image = new Image();
let imgSrc = await player.snapshotAsync();
image.src = imgSrc;
document.body.appendChild(image)

this looks like the image data encoded which works pretty good. How do i grab the file path to this image instead off of your cdn?

There are a couple of approaches you can take calling other APIs from the browser. Are these snapshots or thumbnails images that have been pre-rendered on Threekit or are you trying to create the images dynamically?

This is to allow the customer to share the item via social media. For example I need to provide image path for facebook or twitter to reference as the image to use in the their feeds. I also need to pass around image path via a url param for use in other parts in our application

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.