Skip to main content
POST
/
api
/
render
Multi-Character Render
curl --request POST \
  --url https://apis.viggle.ai/api/render \
  --header 'Authorization: Bearer <token>'
Render a multi-person template scene with different avatars for each tracked person. Map each segment UUID to a different character using the character_mapping form field.
How Character Mapping WorksEach person in the scene has a segment UUID from the template. Use character_mapping to assign different avatars to each person. The mapping is passed as a JSON string in a form field.

Mapping Options

Partial Mapping

You don’t need to map all segments. Unmapped people retain their original appearance:
curl -X POST "https://apis.viggle.ai/api/render" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d "scene_id=scene_770e8400e29b41d4" \
  -d 'character_mapping={"person_a1b2c3d4":"char_alice"}'
# person_e5f6g7h8 and person_i9j0k1l2 keep original appearance

Same Avatar for Multiple People

Map multiple segments to the same character ID:
curl -X POST "https://apis.viggle.ai/api/render" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d "scene_id=scene_770e8400e29b41d4" \
  -d 'character_mapping={"person_a1b2c3d4":"char_alice","person_e5f6g7h8":"char_alice","person_i9j0k1l2":"char_bob"}'

Examples

import requests
import json
import time

BASE = "https://apis.viggle.ai"
headers = {"Authorization": "Bearer YOUR_API_KEY"}

# Map each person in the scene to a character
character_mapping = {
    "person_a1b2c3d4": "char_alice",
    "person_e5f6g7h8": "char_bob",
}

# 1. Start multi-character render
resp = requests.post(
    f"{BASE}/api/render",
    headers=headers,
    data={
        "scene_id": "scene_770e8400e29b41d4",
        "character_mapping": json.dumps(character_mapping),
        "background_mode": "original",
    },
).json()

if "detail" in resp:
    raise Exception(f"Error {resp['detail']['error_code']}: {resp['detail']['message']}")

job_id = resp["job_id"]
print(f"Job created: {job_id}")

# 2. Poll until complete (no auth required)
while True:
    status = requests.get(f"{BASE}/api/render/{job_id}").json()
    if status["status"] == "complete":
        break
    elif status["status"] == "failed":
        raise Exception(f"Error {status.get('error_code')}: {status.get('error')}")
    time.sleep(5)

# 3. Download (auth required)
video = requests.get(
    f"{BASE}/api/render/{job_id}/download",
    headers=headers,
    allow_redirects=True,
    stream=True,
)
with open("output.mp4", "wb") as f:
    for chunk in video.iter_content(chunk_size=8192):
        f.write(chunk)

print("Saved output.mp4")

Complete Workflow

1

Obtain your character and scene IDs

Get preprocessed character IDs and a multi-person template scene ID. You can import a template from viggle.ai to get a scene with segment UUIDs for each tracked person.
2

Create character mapping

import json

character_mapping = {
    "person_a1b2c3d4": "char_alice",
    "person_e5f6g7h8": "char_bob"
}
3

Start render job

job = requests.post(
    f"{BASE}/api/render",
    headers=headers,
    data={
        "scene_id": scene_id,
        "character_mapping": json.dumps(character_mapping),
        "background_mode": "original"
    }
).json()
4

Poll for completion and download

# Status endpoint is open (no auth needed)
while True:
    status = requests.get(f"{BASE}/api/render/{job['job_id']}").json()
    if status["status"] == "complete":
        break
    elif status["status"] == "failed":
        raise Exception(status.get("error_message"))
    time.sleep(3)

# Download from cdn_url
video = requests.get(status["cdn_url"])
with open("output.mp4", "wb") as f:
    f.write(video.content)