3D Model Generation

The Scenario API extends beyond static image generation to support dynamic content creation, including 3D model generation. These advanced functionalities often involve longer processing times and utilize a flexible "custom" endpoint, requiring a job polling mechanism to retrieve the final results. This guide will explain how to initiate 3D model generation, monitor their progress, and retrieve the completed assets.

The Custom Endpoint

For specialized generation tasks like 3D models, the Scenario API provides a versatile custom endpoint. This endpoint allows you to interact with specific models tailored for these complex outputs.

POST https://api.cloud.scenario.com/v1/generate/custom/{modelId} - API Reference

Where {modelId} is the identifier for the specific video or 3D model generation model you wish to use (e.g., model_hunyuan-3d-v2-1 for a 3D model). Find the full list of available model IDs here: https://docs.scenario.com/docs/3d-models-parameters-reference

Request Body for Custom Generation

The payload for the custom endpoint will vary depending on the modelId and the type of generation (video or 3D). However, common parameters often include:

ParameterTypeDescription
imagestringThe asset ID of an input image to be used as a reference for 3D model generation.
stepsintegerThe number of processing steps for the generation. Higher values can lead to higher quality but longer processing times.
guidanceScalenumberControls how closely the generation follows the prompt.
targetFaceNumintegerThe target number of faces for the generated 3D model.

Note: You can find the full list of parameters here: https://docs.scenario.com/docs/3d-models-parameters-reference

Job Polling: Retrieving Asynchronous Results

When you make a request to the custom endpoint, you will receive a jobId immediately, but the actual generation will happen in the background. You then need to periodically poll a separate endpoint to check the status and retrieve the final asset.

Polling Endpoint

GET https://api.cloud.scenario.com/v1/jobs/{jobId} - API Reference

Polling Response

The response from the polling endpoint will contain the current status of your job. You should continue polling until the status field indicates success or failed.

{
  "job": {
    "jobId": "job_abc123def456",
    "status": "processing", // Can be \"queued\", \"processing\", \"success\", \"failed\", \"canceled\"
    "progress": 0.5, // Optional: progress percentage
    "metadata": {
      "assetIds": []
    }
  },
  "creativeUnitsCost": 5
}

Once the status is success, the metadata.assetIds field will contain the IDs to your generated video or 3D model assets.

Code Example: 3D Model Generation with Hunyuan 3D v2.1

This example demonstrates generating a 3D model using the model_hunyuan-3d-v2-1 model and then polling for the result.

Initial Request (cURL)

curl -X POST \
  -u "YOUR_API_KEY:YOUR_API_SECRET" \
  -H "Content-Type: application/json" \
  -d 
\"{
    "image":"asset_1gHMbHjSjWYLyAnd7ZxzPkcQ",
    "paint":false,
    "steps":30,
    "guidanceScale":7.5,
    "targetFaceNum":40000
}\" \
  https://api.cloud.scenario.com/v1/generate/custom/model_hunyuan-3d-v2-1?projectId=yourprojectid

Python

import requests
import time

api_key = "YOUR_API_KEY"
api_secret = "YOUR_API_SECRET"
project_id = "yourprojectid"

# Step 1: Initiate 3D Model Generation
custom_model_id = "model_hunyuan-3d-v2-1"
initial_url = f"https://api.cloud.scenario.com/v1/generate/custom/{custom_model_id}?projectId={project_id}"
headers = {"Content-Type": "application/json"}

payload = {
    "image": "asset_1gHMbHjSjWYLyAnd7ZxzPkcQ", # Replace with your asset ID
    "paint": False,
    "steps": 30,
    "guidanceScale": 7.5,
    "targetFaceNum": 40000
}

print("Initiating 3D model generation...")
initial_response = requests.post(initial_url, headers=headers, json=payload, auth=(api_key, api_secret))

if initial_response.status_code == 200:
    initial_data = initial_response.json()
    job_id = initial_data.get("job").get("jobId")
    if job_id:
        print(f"3D model generation job initiated. Job ID: {job_id}")
        
        # Step 2: Poll for Job Status
        polling_url = f"https://api.scenario.com/v1/jobs/{job_id}"
        status = "queued"
        while status not in ["success", "failure", "canceled"]:
            print(f"Polling job {job_id}... Current status: {status}")
            time.sleep(3) # Wait for 3 seconds before polling again
            
            polling_response = requests.get(polling_url, auth=(api_key, api_secret))
            if polling_response.status_code == 200:
                polling_data = polling_response.json()
                status = polling_data.get("job").get("status")
                progress = polling_data.get("job").get("progress", 0) * 100
                print(f"Progress: {progress:.2f}%")
                
                if status == "success":
                    asset_ids = polling_data.get("job").get("metadata").get("assetIds", [])
                    print(f"3D model generation completed! Asset IDs: {asset_ids}")
                elif status in ["failure", "canceled"]:
                    print(f"3D model generation failed or canceled: {polling_data.get("job").get("error")}")
            else:
                print(f"Error polling job status: {polling_response.status_code} - {polling_response.text}")
                break
    else:
        print("Error: No jobId returned in the initial response.")
else:
    print(f"Error initiating 3D model generation: {initial_response.status_code} - {initial_response.text}")

Node.js

const fetch = require("node-fetch");

const apiKey = "YOUR_API_KEY";
const apiSecret = "YOUR_API_SECRET";
const projectId = "yourprojectid";

const credentials = Buffer.from(`${apiKey}:${apiSecret}`).toString("base64");

async function generate3DModel() {
  const customModelId = "model_hunyuan-3d-v2-1";
  const initialUrl = `https://api.cloud.scenario.com/v1/generate/custom/${customModelId}?projectId=${projectId}`;
  const headers = {
    "Content-Type": "application/json",
    Authorization: `Basic ${credentials}`,
  };

  const payload = {
    image: "asset_1gHMbHjSjWYLyAnd7ZxzPkcQ", // Replace with your asset ID
    paint: false,
    steps: 30,
    guidanceScale: 7.5,
    targetFaceNum: 40000,
  };

  console.log("Initiating 3D model generation...");
  try {
    const initialResponse = await fetch(initialUrl, {
      method: "POST",
      headers: headers,
      body: JSON.stringify(payload),
    });

    const initialData = await initialResponse.json();

    if (initialResponse.ok) {
      const jobId = initialData.job.jobId;
      if (jobId) {
        console.log(`3D model generation job initiated. Job ID: ${jobId}`);

        const pollingUrl = `https://api.scenario.com/v1/jobs/${jobId}`;
        let status = "queued";

        while (!["success", "failure", "canceled"].includes(status)) {
          console.log(`Polling job ${jobId}... Current status: ${status}`);
          await new Promise(resolve => setTimeout(resolve, 3000)); // Wait for 3 seconds

          const pollingResponse = await fetch(pollingUrl, {
            headers: { Authorization: `Basic ${credentials}` },
          });
          const pollingData = await pollingResponse.json();

          if (pollingResponse.ok) {
            status = pollingData.job.status;
            const progress = (pollingData.job.progress || 0) * 100;
            console.log(`Progress: ${progress.toFixed(2)}%`);

            if (status === "success") {
              const asset_ids = polling_data.get("job").get("metadata").get("assetIds", []);
              console.log("3D model generation completed! Asset IDs:", asset_ids);
            } else if (["failure", "canceled"].includes(status)) {
              console.error(`3D model generation failed or canceled: ${pollingData.job.error}`);
            }
          } else {
            console.error(`Error polling job status: ${pollingResponse.status} - ${JSON.stringify(pollingData)}`);
            break;
          }
        }
      } else {
        console.error("Error: No jobId returned in the initial response.");
      }
    } else {
      console.error(`Error initiating 3D model generation: ${initialResponse.status} - ${JSON.stringify(initialData)}`);
    }
  } catch (error) {
    console.error("Network or other error:", error);
  }
}

generate3DModel();