Retargeting | Uthana API Docs

On this page

Apply motions generated with Uthana to your custom 3D characters. Retargeting automatically adapts animations to work with different character skeletons and proportions.

Overview

When you generate a motion with Uthana, it's created for a specific character skeleton. Retargeting allows you to apply that same motion to any character you've uploaded, automatically adapting the animation to match different bone structures and proportions.

Learn more about Retargeting.

How retargeting works

  1. Generate or select a motion: Create a motion using text-to-motion, locomotion, or video-to-motion, or use an existing motion
  2. Choose your character: Select the character you want to apply the motion to
  3. Download the retargeted motion: The motion is automatically retargeted when you download it with a specific character ID

Step-by-step tutorial

Step 1: Upload your character

First, upload your custom character model. Uthana will automatically rig it if needed.

See the Auto-rig / add a character guide for detailed instructions on uploading characters, including supported formats, auto-rigging options, and code examples for all languages.

After uploading, save the character ID from the response. You'll need it for retargeting motions.

Step 2: Generate a motion

Generate a motion using Text to motion, Locomotion, or Video to motion. Save the motion ID from the response—you'll need it for downloading the retargeted motion.

Step 3: Download retargeted motion

When you download a motion with a specific character ID, Uthana automatically retargets it to that character's skeleton.

# Download retargeted motion as FBX (filename is customizable)
curl -L "https://uthana.com/motion/file/motion_viewer/$CHARACTER_ID/$MOTION_ID/fbx/motion.fbx" \
  -u $API_KEY: \
  -o retargeted-motion.fbx

# Download retargeted motion as GLB (filename is customizable)
curl -L "https://uthana.com/motion/file/motion_viewer/$CHARACTER_ID/$MOTION_ID/glb/motion.glb" \
  -u $API_KEY: \
  -o retargeted-motion.glb
import asyncio
from uthana import Uthana

client = Uthana("{{apiKey}}")

async def main():
    # Download retargeted motion as FBX for a specific character
    fbx_data = await client.motions.download(CHARACTER_ID, MOTION_ID, output_format="fbx")
    with open("retargeted-motion.fbx", "wb") as f:
        f.write(fbx_data)

# Download retargeted motion as GLB
    glb_data = await client.motions.download(CHARACTER_ID, MOTION_ID, output_format="glb")
    with open("retargeted-motion.glb", "wb") as f:
        f.write(glb_data)

asyncio.run(main())
import { UthanaClient } from "@uthana/client";

const client = new UthanaClient(process.env.UTHANA_API_KEY!);

// Download retargeted motion as FBX for a specific character
const fbxBuffer = await client.motions.download(CHARACTER_ID, MOTION_ID, { output_format: "fbx" });

// Download retargeted motion as GLB
const glbBuffer = await client.motions.download(CHARACTER_ID, MOTION_ID, { output_format: "glb" });
import { useUthanaClient } from "@uthana/react";

function DownloadRetargetedMotion({
  characterId,
  motionId,
}: {
  characterId: string;
  motionId: string;
}) {
  const client = useUthanaClient();

async function download(format: "glb" | "fbx") {
    const buffer = await client.motions.download(characterId, motionId, { output_format: format });
    const mime = format === "glb" ? "model/gltf-binary" : "application/octet-stream";
    const url = URL.createObjectURL(new Blob([buffer], { type: mime }));
    const a = document.createElement("a");
    a.href = url;
    a.download = `retargeted-motion.${format}`;
    a.click();
  }

return (
    <div>
      <button onClick={() => download("fbx")}>Download FBX</button>
      <button onClick={() => download("glb")}>Download GLB</button>
    </div>
  );
}
public async Task<byte[]> DownloadRetargetedMotionAsync(string characterId, string motionId, string format = "fbx", string filename = "motion")
{
    var downloadUrl = $