Skip to main content

Video to motion

Convert 2D video files into high-quality 3D character animations. Video-to-motion is perfect for extracting motion from existing video content and applying it to your 3D characters.

Overview

Video-to-motion processes video files asynchronously. Unlike text-to-motion, video-to-motion returns a job that you'll need to poll to check when processing is complete.

Duplicate uploads: If you upload the same video file while a job for that file is already running, or if it was successfully processed in the last 24 hours or failed in the last hour, the API returns the existing job instead of throwing an error. Use the returned job ID to poll for status as usual.

Multiple models: The API supports two video-to-motion models. Pass an optional model parameter:

  • video-to-motion-v1 — video-to-motion-v1
  • video-to-motion-v2 — video-to-motion-v2 fast (preview)

Different models may offer different quality/speed tradeoffs. If omitted, the default model is used.

Step-by-step tutorial

Step 1: Prepare your video file

Choose a video of you or someone else performing the motion you want to create. The video should be a single, continuous shot, with movement clearly visible and centered in the frame.

Video requirements:

  • Supported formats: .mp4, .mov, .avi
  • Video parameters: 2-60 seconds, 24-120 fps, 300px to 4096px resolution
  • Camera: Use a stable, flat surface or tripod
  • Framing: Keep your whole body in view
  • Start position: Begin standing with both feet on the ground
  • Subject: Ensure only one person is in the video
  • Clothing: Wear well-fitting, distinct colors
  • Background: Plain, contrasting, and well-lit
  • Lighting: Avoid direct sunlight or harsh shadows

You can upload a file directly or provide a URL.

# Set your API key and video file path
API_KEY="{{apiKey}}"
VIDEO_FILE="/path/to/your/video.mp4"

Step 2: Upload video and create motion

Upload your video file using the GraphQL multipart request spec. This creates a job that will process your video. To use a specific model, add model: "video-to-motion-v1" or model: "video-to-motion-v2" to the variables.

curl -X POST https://uthana.com/graphql \
  -u $API_KEY: \
  -F 'operations={
    "query": "mutation ($file: Upload!, $motion_name: String!) { create_video_to_motion(file: $file, motion_name: $motion_name) { job { id status } } }",
    "variables": { "file": null, "motion_name": "My Video Motion" }
  }' \
  -F 'map={ "0": ["variables.file"] }' \
  -F '0=@'"$VIDEO_FILE"

Step 3: Poll for job completion

Video-to-motion processing happens asynchronously. Poll the job status until it's complete.

JOB_ID="your-job-id"

# Poll until job is complete
while true; do
  RESPONSE=$(curl -s https://uthana.com/graphql \
    -u $API_KEY: \
    -H "Content-Type: application/json" \
    -d "{\"query\": \"query { job(job_id: \\\"$JOB_ID\\\") { id status result } }\"}")

  STATUS=$(echo "$RESPONSE" | jq -r '.data.job.status')
  echo "Job status: $STATUS"

  if [ "$STATUS" = "FINISHED" ] || [ "$STATUS" = "FAILED" ]; then
    break
  fi

  sleep 5  # Wait 5 seconds before checking again
done

# Get the final result
echo "$RESPONSE" | jq '.data.job'

Step 4: Download your motion

Once the job is finished, extract the motion ID from the result and download it.

CHARACTER_ID="cXi2eAP19XwQ"  # Default character, or use your own
MOTION_ID=$(echo "$RESPONSE" | jq -r '.data.job.result.motion.id')

# Download 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 motion.fbx

Job statuses

  • RESERVED: Job has been created and is waiting to start
  • READY: Job is ready to be processed
  • FINISHED: Job completed successfully
  • FAILED: Job failed (check the result field for error details)

Error handling

Check for errors in the job result:

if [ "$STATUS" = "FAILED" ]; then
    echo "Job failed:"
    echo "$RESPONSE" | jq '.data.job.result'
fi

Next steps