본문으로 건너뛰기
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(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

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 / 1,000자

이 양식은 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의 스킬 모두 보기

이 스킬의 문제 신고