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.

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.

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/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