Save image and then retrieve via client side

wstm
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.

Comments

25 comments

  • Comment author
    wstm

    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.

    0
  • Comment author
    William Thompson

    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)
    
    0
  • Comment author
    wstm

    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?

    0
  • Comment author
    William Thompson

    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?

    0
  • Comment author
    wstm

    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

    0
  • Comment author
    William Thompson

    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.

    0
  • Comment author
    Prashant

    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

    0
  • Comment author
    William Thompson

    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)
    
    0
  • Comment author
    Prashant

    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.

    0
  • Comment author
    William Thompson

    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();
      });
    
    
    0
  • Comment author
    Prashant

    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

    0
  • Comment author
    William Thompson

    Please refer to this thread:

    Yes, I believe it is dependent on what is visible to the eye or browser. Per our snapshot docs: 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 You can do a quick test if you have a player on your site using this code in the console: let image = new Image(); let imgSrc = await player.snapshotAsync(); image.src = imgSrc; // Either append the image or save it somehow document.body.appendC…

    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.

    0
  • Comment author
    cmontiel

    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?

    0
  • Comment author
    William Thompson

    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

    0
  • Comment author
    cmontiel

    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?

    0
  • Comment author
    William Thompson

    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.

    0
  • Comment author
    cmontiel

    @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.

    0
  • Comment author
    William Thompson

    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
          }
        }
      }
    }
    0
  • Comment author
    cmontiel

    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.

    0
  • Comment author
    William Thompson

    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.

    0
  • Comment author
    cmontiel

    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.

    0
  • Comment author
    cmontiel

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

    0
  • Comment author
    William Thompson
     
    cmontiel:

    I got the server response, how do I fetch the snapshot at the json file?

    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

    0
  • Comment author
    cmontiel

    Thank you very much

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

    CM.

    0
  • Comment author
    William Thompson

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

    0

Please sign in to leave a comment.