跳到正文
cccskills
免费在 GitHub 公开

blender-motion-capture

Automate motion capture and tracking workflows in Blender with Python. Use when the user wants to import BVH or FBX mocap data, retarget motion to armatures, track camera or object motion from video, solve camera motion, clean up motion capture data, or script any tracking pipeline in Blender.

中文简介正在准备中。当前显示原文说明。

集成工具Blender
查看安装方法

包含的文件(2)

  • SKILL.md11.1 KB
  • _scores.json2.7 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Blender Motion Capture

Overview

Import, process, and retarget motion capture data in Blender using Python. Work with BVH/FBX mocap files, track camera and object motion from video footage, solve 3D camera paths, and clean up animation data. Checked against the Blender 5.2 Python API reference.

Blender 5.0 changed how animation data is stored: an Action now has layers, strips and slots, and F-Curves live in a channelbag (action.layers[0].strips[0].channelbag(slot).fcurves), not in action.fcurves. Code written for 4.x that touches action.fcurves fails on 5.x.

Instructions

1. Import BVH motion capture files

import bpy

bpy.ops.import_anim.bvh(
    filepath="/srv/mocap/walk_cycle.bvh",
    target='ARMATURE',
    global_scale=0.01,            # BVH files are usually in centimeters
    frame_start=1,
    use_fps_scale=False,
    update_scene_fps=True,        # match the scene fps to the file
    update_scene_duration=True,   # extend the scene frame range to the clip
    rotate_mode='QUATERNION',     # NATIVE keeps the file's Euler order, which breaks quaternion copies
    axis_forward='-Z', axis_up='Y'
)

armature = bpy.context.active_object
action = armature.animation_data.action
print(f"Imported: {armature.name}, Bones: {len(armature.data.bones)}, Frames: {tuple(action.frame_range)}")

2. Import FBX with animation

bpy.ops.import_scene.fbx(
    filepath="/srv/mocap/capture_take01.fbx",
    use_anim=True,
    ignore_leaf_bones=True,
    automatic_bone_orientation=True,
    primary_bone_axis='Y', secondary_bone_axis='X'
)

Newer Blender versions also ship a C++ importer, bpy.ops.wm.fbx_import(filepath=..., use_anim=True, ignore_leaf_bones=True), which has no bone-axis options. Both exist in 5.2; try the one that gives the right bone orientation for your rig.

3. Retarget motion between armatures

This copy-per-frame approach assumes both rigs share the same rest pose and bone roll. If they do not, or you need foot contact and offsets, constrain the target bones (Copy Rotation with mix_mode='REPLACE') and bake with bpy.ops.nla.bake(bake_types={'POSE'}, visual_keying=True, clear_constraints=True), or use an add-on such as Rokoko Studio Live or Auto-Rig Pro.

import bpy

def retarget_motion(source_armature, target_armature, bone_mapping):
    """Retarget animation using a bone name mapping: {target_bone: source_bone}"""
    source_action = source_armature.animation_data.action
    frame_start, frame_end = int(source_action.frame_range[0]), int(source_action.frame_range[1])

    if not target_armature.animation_data:
        target_armature.animation_data_create()
    new_action = bpy.data.actions.new(f"{source_action.name}_retarget")
    target_armature.animation_data.action = new_action   # keyframe_insert() creates the slot and channels

    for frame in range(frame_start, frame_end + 1):
        bpy.context.scene.frame_set(frame)
        for tgt_name, src_name in bone_mapping.items():
            src = source_armature.pose.bones.get(src_name)
            tgt = target_armature.pose.bones.get(tgt_name)
            if not src or not tgt:
                continue
            tgt.rotation_mode = 'QUATERNION'
            tgt.rotation_quaternion = (src.rotation_quaternion if src.rotation_mode == 'QUATERNION'
                                       else src.rotation_euler.to_quaternion())
            tgt.keyframe_insert(data_path="rotation_quaternion", frame=frame)
            # Copy location for root bone only
            if src_name == list(bone_mapping.values())[0]:
                tgt.location = src.location
                tgt.keyframe_insert(data_path="location", frame=frame)

# Example Mixamo → Rigify mapping
mapping = {
    "spine": "mixamorig:Hips", "spine.001": "mixamorig:Spine",
    "spine.004": "mixamorig:Neck", "spine.006": "mixamorig:Head",
    "upper_arm.L": "mixamorig:LeftArm", "forearm.L": "mixamorig:LeftForeArm",
    "upper_arm.R": "mixamorig:RightArm", "forearm.R": "mixamorig:RightForeArm",
    "thigh.L": "mixamorig:LeftUpLeg", "shin.L": "mixamorig:LeftLeg",
    "thigh.R": "mixamorig:RightUpLeg", "shin.R": "mixamorig:RightLeg",
}

4. Clean up motion capture data

def decimate_fcurve(fcurve, factor=0.5):
    """Remove keyframes to reduce data while keeping shape."""
    points = fcurve.keyframe_points
    total = len(points)
    keep_every = max(1, int(1.0 / factor))
    remove_indices = [i for i in range(total) if i % keep_every != 0 and i != 0 and i != total - 1]
    for i in reversed(remove_indices):
        points.remove(points[i])

def action_fcurves(action, slot):
    """All F-Curves of one slot in a layered action (Blender 5.0+)."""
    for layer in action.layers:
        for strip in layer.strips:
            channelbag = strip.channelbag(slot)
            if channelbag:
                yield from channelbag.fcurves

armature = bpy.context.active_object
anim = armature.animation_data
for fcurve in action_fcurves(anim.action, anim.action_slot):
    decimate_fcurve(fcurve, factor=0.5)
    fcurve.update()

5. Video motion tracking and camera solve

The bpy.ops.clip.* operators need a Movie Clip Editor area, so they fail in --background mode. Open Blender with its UI, switch an area to the Movie Clip Editor, and either run the script from the Text Editor or wrap each call in with bpy.context.temp_override(area=clip_area, region=clip_region):.

# Load footage
clip = bpy.data.movieclips.load("/srv/footage/street_pan.mp4")
scene = bpy.context.scene
scene.active_clip = clip

# Configure tracking
tracking = clip.tracking
settings = tracking.settings
settings.default_pattern_size = 21
settings.default_search_size = 71
settings.default_motion_model = 'Affine'   # Loc, LocScale, LocRot, LocRotScale, Affine, Perspective

# Camera settings for solving
camera = tracking.camera
camera.sensor_width = 36.0
camera.focal_length = 50.0

# Create and follow markers (needs the clip editor context), drop bad tracks, then solve
bpy.ops.clip.detect_features(placement='FRAME', margin=16, threshold=0.5, min_distance=120)
bpy.ops.clip.track_markers(backwards=False, sequence=True)
bpy.ops.clip.clean_tracks(frames=10, error=3.0, action='DELETE_TRACK')

# Solve camera motion
bpy.ops.clip.solve_camera()
solve_error = tracking.reconstruction.average_error
print(f"Solve error: {solve_error:.4f} px ({'Good' if solve_error < 0.5 else 'Needs refinement'})")

# Set up scene from solved data
bpy.ops.clip.setup_tracking_scene()

6. Apply tracked motion to objects

obj = bpy.data.objects["Cube"]
constraint = obj.constraints.new(type='FOLLOW_TRACK')
constraint.clip = clip
constraint.track = tracking.tracks[0].name      # the track is referenced by name (a string)
constraint.use_3d_position = True
constraint.camera = scene.camera

# Bake constraint to keyframes
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.ops.nla.bake(
    frame_start=1, frame_end=clip.frame_duration,
    only_selected=True, visual_keying=True,
    clear_constraints=True, bake_types={'OBJECT'}
)

7. Export animation data

# Export as BVH
bpy.ops.export_anim.bvh(
    filepath="/tmp/output_mocap.bvh",
    frame_start=int(action.frame_range[0]),
    frame_end=int(action.frame_range[1]),
    rotate_mode='NATIVE',
    root_transform_only=False
)

# Export as FBX with baked animation
bpy.ops.export_scene.fbx(
    filepath="/tmp/output_anim.fbx",
    use_selection=True, bake_anim=True,
    bake_anim_use_all_bones=True, add_leaf_bones=False
)

Examples

Example 1: Batch scan mocap library

User request: "Import all BVH files from a folder, list bone counts and frame ranges"

import bpy, glob, os

for filepath in sorted(glob.glob("/srv/mocap/library/*.bvh")):
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete()
    bpy.ops.import_anim.bvh(filepath=filepath, target='ARMATURE', global_scale=0.01, frame_start=1)
    arm = bpy.context.active_object
    if arm and arm.animation_data:
        action = arm.animation_data.action
        duration = (action.frame_range[1] - action.frame_range[0]) / bpy.context.scene.render.fps
        print(f"{os.path.basename(filepath)}: {len(arm.data.bones)} bones, {duration:.1f}s")

Run: blender --background --python scan_mocap.py

Example 2: Apply mocap to character and render

User request: "Import a BVH file, apply it to my rigged character, and render a preview"

import bpy

bpy.ops.wm.open_mainfile(filepath="/srv/projects/hero_character.blend")
char_armature = bpy.data.objects["Armature"]

bpy.ops.import_anim.bvh(filepath="/srv/mocap/walk_cycle.bvh", target='ARMATURE', global_scale=0.01)
mocap_armature = bpy.context.active_object
mocap_action = mocap_armature.animation_data.action

# Transfer action (works when bone names match)
if not char_armature.animation_data:
    char_armature.animation_data_create()
char_armature.animation_data.action = mocap_action
# Blender 5.0+: pick the slot explicitly if it was not matched by name
if char_armature.animation_data.action_slot is None:
    char_armature.animation_data.action_slot = mocap_action.slots[0]

# Remove temp armature, set frame range, add camera, render
bpy.data.objects.remove(mocap_armature)
scene = bpy.context.scene
scene.frame_start, scene.frame_end = int(mocap_action.frame_range[0]), int(mocap_action.frame_range[1])
scene.render.filepath = "/tmp/mocap_preview/frame_"
bpy.ops.render.render(animation=True)

Guidelines

  • BVH is simplest (plain text with hierarchy + motion). FBX supports richer data (blend shapes, multiple takes).
  • Scale matters: BVH files often use centimeters. Set global_scale=0.01 for cm-based files.
  • Bone name matching is critical for retargeting. Build a mapping dictionary for each source format.
  • For retargeting, copy rotations for all bones but only location for the root/hip bone.
  • Clean up imported mocap by decimating keyframes — raw mocap has every-frame keys, making editing difficult. On Blender 5.x reach F-Curves through the action's layers, strips and channelbag; action.fcurves no longer exists.
  • bpy.ops.clip.* operators depend on the Movie Clip Editor context; test them in a foreground session first.
  • Camera solve quality depends on marker count and distribution. Use 8+ well-distributed markers, keep error below 0.5px.
  • Use bpy.ops.nla.bake() to convert constraints to keyframes for export.
  • Always export with bake_anim=True in FBX to flatten NLA strips and constraints.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Scripts and configures production rendering in Autodesk 3ds Max with the V-Ray and Corona renderers: output size and files, render elements, denoising, light mix, batch and command-line rendering, and network rendering. Use when a user asks to set up a production render, render several cameras in one batch, render from the command line or on a render farm, add render passes for compositing, or cut render time for archviz and product shots.

中文简介正在准备中。当前显示原文说明。

TerminalSkills/skills1742026年10月22日 更新

Covers scripting Autodesk 3ds Max, the 3D modeling and rendering application, with MAXScript and Python (pymxs): scene manipulation, object creation, material assignment, camera and light setup, batch operations, and file I/O. Use when tasks involve automating repetitive 3ds Max workflows, batch processing scenes, running scripts headless with 3dsmaxbatch, creating custom tools, or scripting scene setup for archviz, product visualization, or VFX.

中文简介正在准备中。当前显示原文说明。

TerminalSkills/skills1742026年10月22日 更新

3proxy

免费

3proxy is a small open-source proxy server that runs HTTP/HTTPS, SOCKS4/5, SNI and TCP/UDP port-mapping proxies from one config file. Use when a user asks to set up an HTTP or SOCKS5 proxy, add proxy users and passwords, write 3proxy access rules, chain or rotate upstream (parent) proxies, limit bandwidth, connections or monthly traffic per user, run 3proxy in Docker, or fix a 3proxy.cfg that will not start.

中文简介正在准备中。当前显示原文说明。

TerminalSkills/skills1742026年10月22日 更新

Builds Agent2Agent (A2A) servers and clients, the open protocol (originally from Google, now under the Linux Foundation) that lets AI agents from different frameworks call each other. Use when the user wants to create an A2A-compliant agent, build an Agent Card, implement task management, connect agents across frameworks, set up agent discovery, handle streaming responses, implement push notifications, or orchestrate multi-agent workflows. Trigger words: a2a, agent to agent, agent2agent, a2a protocol, a2a server, a2a client, agent card, agent interoperability, agent collaboration, multi-agent, agent discovery, a2a sdk, a2a task.

中文简介正在准备中。当前显示原文说明。

TerminalSkills/skills1742026年10月22日 更新

Plans a controlled experiment (A/B test) so its result can be trusted: writes the hypothesis, picks one primary metric and the guardrails, computes sample size and run time, specifies how visitors are assigned and when exposure is logged, and reads out the result with a confidence interval. Use when someone says "set up an A/B test", "split test this page", "how many visitors do I need", "how long should the experiment run", "is this result significant", "can I stop the test early", or wants to test a headline, price, layout or onboarding change against the current version.

中文简介正在准备中。当前显示原文说明。

TerminalSkills/skills1742026年10月22日 更新

ably

免费

Ably is a hosted realtime messaging service: clients publish and subscribe to named channels over WebSockets, see who is present, replay message history, and resume after a dropped connection. Use when a user asks to "add realtime updates", "push live notifications to the browser", "show who is online", "add a chat room with typing indicators", "publish from a serverless function", or "authenticate Ably clients without exposing the API key". Covers the ably 2.x JavaScript SDK (Realtime and REST), JWT token authentication, presence, history and rewind, batch publishing, and the @ably/chat 1.x SDK.

中文简介正在准备中。当前显示原文说明。

TerminalSkills/skills1742026年10月22日 更新

查看 TerminalSkills 的全部技能

报告此技能的问题