Process animations and retarget them onto any humanoid character
CLI & Python SDK for game developers
ohao is the SDK for MoGen3D — process videos into animation files (BVH / FBX) and retarget them onto your characters.
pip install ohaoRetargeting requires Blender (3.6+) installed locally.
# Log in once — opens browser, you paste your API key
ohao loginfrom ohao.mogen3d import MoGen3DClient, retarget
# No api_key needed — auto-reads from ~/.ohao/credentials.json
client = MoGen3DClient()
# Check sparks balance (each job costs 1 spark)
sparks = client.sparks()
print(f"{sparks.balance} sparks available")
# Claim daily free sparks
if sparks.can_claim:
client.claim_sparks()
# Process a video → download BVH
job = client.process("dance.mp4", wait=True)
bvh = job.download(format="bvh")
# Retarget onto your character (runs locally via Blender)
retarget(str(bvh), "MyCharacter.fbx")# Auth
ohao login # save API key locally (one-time)
ohao whoami # check account info
ohao logout # remove saved credentials
# Sparks
ohao mogen3d sparks # check balance
ohao mogen3d claim # claim daily free sparks
ohao mogen3d bundles # list purchasable bundles
# Process a video (costs 1 spark)
ohao mogen3d process dance.mp4 --format bvh -o dance.bvh
# Retarget onto a character (free, runs locally)
ohao mogen3d retarget dance.bvh MyCharacter.fbx --preset mixamoSparks are the credits that power processing jobs. 1 spark = 1 job. Retargeting is free (runs locally).
| Free | Pro | |
|---|---|---|
| Daily sparks | 1/day | 15/day (accumulates up to 100) |
| Exports | BVH | BVH + FBX |
| Daily job limit | 5 | 50 |
Need more? Purchase spark bundles:
| Bundle | Price |
|---|---|
| 30 sparks | $3.99 |
| 100 sparks | $9.99 |
| 1,000 sparks | $59.99 |
# Check available bundles
for bundle in client.bundles():
print(f"{bundle.label}: {bundle.price}")
# Purchase (opens Stripe checkout)
url = client.purchase_bundle("sparks_100")Sparks are refunded automatically if a job fails.
The SDK auto-detects your character's rig type and maps bones automatically.
| Rig Type | Detection | Characters |
|---|---|---|
| Mixamo | Hips bone (with optional prefix like mixamorig:) |
X Bot, Y Bot, any Mixamo character |
| UE5 Mannequin | pelvis bone |
Quinn, Manny, Quaternius models |
# Auto-detect (works for most characters)
retarget("dance.bvh", "XBot.fbx")
# Explicit preset
retarget("dance.bvh", "Quinn.gltf", preset="ue5")
# Custom Blender path
retarget("dance.bvh", "MyChar.fbx", blender_path="/path/to/blender")
# Open in Blender GUI to inspect
retarget("dance.bvh", "MyChar.fbx", background=False)| Input | Output |
|---|---|
Video: .mp4, .mov, .webm |
.bvh, .fbx (via cloud processing) |
Animation: .bvh, .fbx |
Retargeted .blend file (local) |
Character: .fbx, .glb, .gltf |
client = MoGen3DClient(api_key="mg_...", base_url="https://...")| Method | Description |
|---|---|
client.sparks() |
Get sparks balance and claim status |
client.claim_sparks() |
Claim daily sparks |
client.bundles() |
List purchasable spark bundles |
client.purchase_bundle(id) |
Start Stripe checkout for a bundle |
client.status() |
Account tier, usage, subscription info |
client.process(path, *, wait=False) |
Upload video, start processing (1 spark) |
client.list_jobs() |
List all jobs |
client.get_job(id) |
Get job by ID |
client.download(id, format="bvh") |
Download result file |
client.delete_job(id) |
Delete a job |
retarget(
bvh_path, # Path to BVH file
character_path, # Path to character (.fbx / .glb / .gltf)
*,
output_path=None, # Output .blend path (default: auto-named)
preset=None, # "mixamo", "ue5", or path to JSON
blender_path=None, # Blender executable (default: auto-detect)
background=True, # Run headless (default: True)
)See the examples/ directory for runnable scripts:
| Example | Description |
|---|---|
basic_retarget.py |
Minimal one-liner retarget |
batch_retarget.py |
Apply one BVH to a folder of characters |
retarget_with_preset.py |
Force a specific rig preset |
inspect_in_blender.py |
Open result in Blender GUI |
custom_blender_path.py |
Use a specific Blender install |
If your character uses a non-standard skeleton, create a JSON preset:
{
"name": "My Rig",
"bone_map": {
"Hips": "my_pelvis",
"Spine": "my_spine_01",
"Head": "my_head",
"LeftArm": "my_upper_arm_L",
"LeftForeArm": "my_lower_arm_L",
"RightArm": "my_upper_arm_R",
"RightForeArm": "my_lower_arm_R",
"LeftUpLeg": "my_thigh_L",
"LeftLeg": "my_shin_L",
"RightUpLeg": "my_thigh_R",
"RightLeg": "my_shin_R"
},
"root_bone": "Hips"
}Keys on the left are the BVH bone names. Values on the right are your character's bone names. Then pass it:
retarget("dance.bvh", "MyRig.fbx", preset="my_rig.json")ohao mogen3d retarget dance.bvh MyRig.fbx --preset my_rig.jsonThe recommended way to authenticate:
ohao loginThis opens your browser, you create/copy an API key, paste it in the terminal, and it's saved to ~/.ohao/credentials.json. All subsequent commands and MoGen3DClient() calls use it automatically — no API key in your code.
Alternatively, you can set an environment variable or pass it explicitly:
export OHAO_API_KEY=mg_your_key # env varclient = MoGen3DClient(api_key="mg_...") # explicit (not recommended)Priority order: explicit api_key= > OHAO_API_KEY env var > ~/.ohao/credentials.json
MIT
