Communitygithub.com

MBehtemam/montagent-skills – 컷아웃 캐릭터 애니메이션

Montagent에서 파츠 리그로 제작된 마스코트와 인형의 컷아웃 캐릭터 애니메이션: 포즈, 제스처, 비즈메 기반 입술 동기화, 깜빡임. Montagent 영상에 움직이거나 말하는 캐릭터가 있을 때 사용합니다.

montagent-skills – 컷아웃 캐릭터 애니메이션란 무엇인가요?

이 스킬은 Montagent 환경 내에서 컷아웃 스타일의 캐릭터를 애니메이션하는 방법을 제공합니다. 캐릭터는 몸통, 머리, 두 조각의 팔, 그리고 머리 캔버스 위에 그려진 입 모양과 깜빡임을 위한 페이스 오버레이로 구성된 파츠 리그로 만들어집니다. 주요 제약 조건은 Montagent에 부모-자식 관계나 이미지 변경 기능이 없다는 점으로, bake_rig.py 스크립트가 각 프레임에서 모든 파츠의 위치와 회전을 계산하고 각 입 모양과 깜빡임을 독립적인 요소로 출력하여 해결합니다. 사용자는 리그 사양을 정의하는 JSON 형식의 스펙 파일을 제공하고, 스크립트를 실행하여 최종 프로젝트를 생성합니다. 스킬에는 캐릭터 배치, 등장 동작, 다양한 제스처(손 흔들기, 가리키기 등), 비즈메 기반 입술 동기화, 깜빡임 패턴에 대한 구체적인 레시피가 포함되어 있으며, 각 단계마다 montagent-craft를 사용한 시각적 확인을 강조합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MBehtemam/montagent-skills/tree/HEAD/skills/montagent-character

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

컷아웃 캐릭터 애니메이션하기

파츠 리그로 제작된 캐릭터를 위한 레시피: 몸통, 머리, 두 조각의 팔, 그리고 머리 캔버스 위에 그려진 페이스 오버레이(입 모양과 깜빡임)로 구성됩니다. 이 레시피들은 montagent의 루프 중 빌드 단계에 들어갑니다. 아직 montagent를 로드하지 않았다면 먼저 로드하세요. 캐릭터가 대사를 말하는 쇼트 영상의 경우, 계획을 세우기 전에 캐릭터 쇼트 구조를 여세요.

리그가 제공해야 하는 것

무엇보다 먼저 리그의 설명을 읽으세요. 각 파츠에 대해 다음이 필요합니다: 이미지, 크기, 피벗(파츠가 회전하는 관절 지점, 원본 그림에서의 점), 부모, 그리고 파츠가 그려지는 순서(뒤에서 앞으로). 또한 음성의 비즈메 ID를 입 모양에 매핑하는 테이블이 필요합니다. 각 파츠의 이미지는 피벗이 캔버스의 정확한 중심이 되도록 패딩되어야 합니다. 페이스 오버레이는 머리의 캔버스와 피벗을 공유합니다.

브리핑이 파츠나 피벗 없이 단일 그림만 제공하는 경우, 맹목적으로 리그를 자를 수 없습니다. 사용자에게 알리고 미리 잘린 리그를 요청하세요.

리그 굽기(Bake)

Montagent에는 부모-자식 관계가 없으며, 요소는 이미지를 변경할 수 없습니다. 따라서 캐릭터는 '구워집니다(baked)': 번들 스크립트가 각 그려진 프레임에서 모든 파츠의 화면상 위치와 회전을 부모로부터 계산하고, 각 입 모양과 깜빡임을 자체적인 요소로 작성하여 머리의 변환과 함께 해당 기간 동안 표시합니다. 직접 작성하지 마세요.

python3 scripts/bake_rig.py <project> <rig> <spec>은 파츠당 하나의 트랙이 추가된 프로젝트를 출력합니다. --help를 실행하여 스펙(캐릭터가 서 있는 위치, 명명된 포즈, 그 사이의 움직임, 흔들기, 점프, 음성 및 비즈메 파일, 깜빡임)을 확인하세요. 스펙을 변경할 때마다 다시 실행하세요. 이 스크립트는 자신이 작성한 트랙만 교체합니다. 스펙을 프로젝트 옆에 보관하세요: 이것이 캐릭터의 진정한 소스입니다.

보고서를 읽으세요. 병합된 각 입 기간, 모든 그려진 프레임에서 자식과 부모 사이의 가장 큰 간격, 그리고 주목해야 할 순간들(각 움직임의 도착과 각 관절의 극단 각도)을 나열합니다. 위치는 정수 픽셀이므로 약 1.5px까지의 간격은 반올림으로 인한 것이며 둥근 관절에 의해 숨겨집니다. 더 큰 간격은 리그의 피벗이 잘못되었음을 의미합니다.

validate는 캐릭터가 유지하는 각 포즈에 대해 R-EASE-INERT를 보고하고, 입과 깜빡임 트랙의 간격 사이에 N-TRACK-GAP을 보고합니다. 둘 다 예상된 것입니다(발견 가이드 참조).

구운 결과는 다음과 같습니다: 각 파츠는 피벗을 중심으로 배치되고, 움직이는 곳에만 키프레임이 있으며, 각 입 또는 깜빡임 요소는 해당 기간 동안 머리의 변환을 복사합니다.

{
  "frame": {"width": 640, "height": 360}, "fps": 30, "background": "#2E3440", "duration": 2000, "output": "out/baked.mp4",
  "tracks": [
    {"name": "set", "layer": 0, "elements": [
      {"id": "set", "type": "image", "start": 0, "end": 2000, "source": "media/still.png", "x": 0, "y": 0, "origin": "top-left", "width": 640, "height": 360, "fit": "literal"}
    ]},
    {"name": "puppet-torso", "layer": 10, "elements": [
      {"id": "puppet-torso", "type": "image", "start": 0, "end": 2000, "source": "rig/parts/torso.png", "x": 320, "y": 330, "origin": "center", "fit": "literal", "width": 80, "height": 280}
    ]},
    {"name": "puppet-head", "layer": 12, "elements": [
      {"id": "puppet-head", "type": "image", "start": 0, "end": 2000, "source": "rig/parts/head.png", "x": 320, "y": 190, "origin": "center", "fit": "literal", "width": 90, "height": 160, "rotation": [{"t": 0, "v": 0}, {"t": 500, "v": 6.0, "ease": "linear"}, {"t": 1000, "v": 0.0, "ease": "linear"}]}
    ]},
    {"name": "puppet-mouth", "layer": 13, "elements": [
      {"id": "puppet-mouth-0", "type": "image", "start": 400, "end": 700, "source": "rig/parts/mouth_open.png", "x": 320, "y": 190, "origin": "center", "fit": "literal", "width": 24, "height": 60, "rotation": [{"t": 400, "v": 4.8}, {"t": 500, "v": 6.0, "ease": "linear"}, {"t": 666, "v": 4.0, "ease": "linear"}]}
    ]}
  ]
}

레시피

모든 레시피는 정답이 아닌 시작 범위를 제공합니다. 각 레시피는 확인 단계로 끝납니다: montagent-craft를 로드한 다음, 해당 단계에 명시된 대로 확인한 후 진행하세요.

각도는 그려진 기본 포즈에서의 회전이며, 각각 부모를 기준으로 하고, 화면에서 시계 방향으로 양수입니다. 따라서 시청자 기준 오른쪽 팔은 음수 각도로 올라가고, 왼쪽 팔은 양수 각도로 올라갑니다.

세트에 세우기

  • 배경: origin이 top-left인 전체 프레임 세트 이미지를 (0, 0)에, 프레임 크기로, 가장 낮은 레이어에 배치합니다. origin을 명시적으로 설정하세요.
  • 바닥에 발: 리그의 루트(발에서 피벗하는 몸통)는 바닥이 벽의 그림자 선과 만나는 곳, 또는 그보다 약간 앞에 위치합니다. 높이 1080의 세트에서 바닥의 상단 가장자리는 보통 아래에서 80–85% 지점이므로, 발을 그보다 5–10% 아래에 두세요.
  • 크기: 캐릭터는 프레임 높이의 55–75%이며, 스펙의 스케일(프레임 픽셀 / 그림 픽셀)로 설정됩니다. 패딩된 그림이 아닌 보이는 캐릭터를 측정하세요: 그림 높이에 스케일을 곱하면 실제보다 커집니다.
  • 배치: 단독으로 서 있지 않다면, 소품이나 카드 반대쪽으로 중앙에서 벗어나 1/3 지점에 배치합니다.
  • 확인: 안정적인 순간에 frame을 보고 발이 바닥에 닿아 있는지(떠 있거나 파묻히지 않았는지), 머리가 프레임 상단에서 최소 5% 이상 떨어져 있는지 확인하세요.

등장: 깡충 뛰어 들어오기

  • 점프: 2–3회, 각 300–450ms, 점점 낮아집니다: 첫 번째 점프는 캐릭터 높이의 8–12%, 마지막 점프는 4–6%입니다. 수평 이동은 동일한 구간을 ease-out으로 덮으므로 마지막 점프는 부드럽게 착지합니다.
  • 포즈: 점프하는 동안 팔을 내립니다. 그려진 프레임에 착지하고, 첫 번째 제스처 전에 150–300ms 동안 유지합니다.
  • 타이밍: 음성이 시작되기 전에 끝나야 하며, 최소 200ms의 여유가 있어야 합니다.
  • 확인: 등장 구간에 대해 frame --from --to --keyframes를 실행합니다. 각 착지 지점에서 발이 바닥에 닿는지, 어떤 파츠도 몸통보다 뒤처지거나 앞서 튀지 않는지 확인하세요.

제스처

제스처는 명명된 포즈와, 그 포즈로 들어가고 나오는 움직임입니다. 각 움직임에 리드인 시간(스펙의 in)을 주어 포즈가 출발할 때까지 유지되도록 합니다.

  • 팔 내리기: 팔을 벌린 기본 포즈에서 각 위팔을 몸쪽으로 40–55° 돌리고, 아래팔을 5–15° 더 돌립니다.
  • 손 흔들기: 위팔을 기본에서 40–50° 옆으로 올리고, 아래팔을 25–35° 더 올립니다. 아래팔을 팔꿈치에서 15–20°씩 양방향으로 흔들며, 주기는 350–450ms, 최소 2회 완전한 흔들기(800ms 이상)를 수행합니다. 더 높이 올리면 손이 흔들림의 안쪽 극단에서 머리 뒤로 갑니다: 머리가 팔 위에 그려집니다.
  • 무언가 가리키기: 위팔을 대상 방향으로 거의 수평(팔을 내린 상태에서 10–25° 위)으로 하고, 아래팔은 직선에서 20° 이내로 하여 손이 대상의 가까운 가장자리를 가리키도록 합니다. 그 대상을 지칭하는 단어보다 1–3프레임 먼저 도착합니다.
  • 환호: 두 위팔을 40–50° 올리고, 아래팔을 20–30° 더 올립니다. 더 구부리면 오버슈트의 정점에서 손이 머리 뒤로 숨겨집니다.
  • 움직임: 250–400ms 동안 들어옵니다. 오버슈트 베지어 [0.34, 1.56, 0.64, 1]로 도착하고, ease-in-out으로 기본 포즈로 돌아갑니다. 후속 동작을 위해 위팔이 도착한 후 2–4프레임 뒤에 아래팔만 지정하는 두 번째 움직임을 추가합니다.
  • 절대 멈추지 않음: 강세가 있는 단어에서 머리를 2–5° 기울이며, 짧은 흔들림 또는 250–400ms 동안 왔다 갔다 하는 움직임으로 표현합니다. 1.5초 이상 아무것도 움직이지 않고 포즈를 유지하는 캐릭터는 정지 이미지처럼 보입니다.
  • 확인: 각 제스처에 대해 베이크 보고서에 해당 관절의 극단으로 나열된 순간에 frame --at을 실행합니다. 손이 머리와 프레임 가장자리에서 떨어져 있고, 소리 없이도 포즈가 해당 제스처로 읽히는지 확인하세요. 그런 다음 가장 높이 올린 포즈에서 어깨와 팔꿈치에 대해 실제 스케일로 frame --crop을 실행하고, 간격이나 느슨한 파츠가 있는지 확인하세요.

비즈메 기반 입술 동기화

베이크는 음성의 비즈메 파일로부터 입을 작성합니다. 각 비즈메 ID는 리그의 테이블을 통해 입에 매핑되고, 침묵은 오버레이 없이 쉬고 있는 부리 또는 입술입니다. 스펙에서 음성 요소와 비즈메 파일을 지정하세요. 그러면 입은 해당 요소의 시작 및 소스 범위를 따르므로, 음성을 이동하고 다시 베이크하면 동기화가 유지됩니다.

  • 가장 짧은 모양: 2프레임. 베이크는 더 짧은 모양을 이전 모양으로 병합하고 각 병합을 보고합니다. 6초 대사에서 12개의 병합은 정상입니다.
  • 리드: 0ms. 렌더링을 볼 때 입이 늦게 느껴지면 1프레임(30fps에서 33ms)만 리드하고, 그 이상은 하지 마세요.
  • 타이밍: 음성 파일을 프로브하세요. 길이가 비즈메 파일의 명시된 지속 시간과 일치하지 않으면 프로브를 신뢰하세요.
  • 확인: 세 단어의 중간에서 query --at을 실행하고 각각 하나의 입 요소가 켜져 있는지 확인하세요. 그런 다음 가장 긴 멈춤의 중간과 대사가 끝난 후에 query --at을 실행하고 어떤 입 요소도 켜져 있지 않은지 확인하세요.

깜빡임

  • 길이: 3프레임(30fps에서 100ms), 최대 4프레임.
  • 리듬: 2–4초마다, 불규칙적으로, 절대 박자에 맞추지 마세요. 큰 움직임이 도착한 직후에 한 번, 대사의 멈춤 중에 한 번 넣으세요. 8초마다 최소 2번.
  • 피해야 할 것: 제스처 도착과 같은 프레임에 깜빡임이 있으면 도착이 가려집니다.
  • 확인: 한 번의 깜빡임 중간 프레임에서 frame --at을 실행하고, 감긴 눈이 머리 위에 정확히 위치하고 머리의 기울기를 따르는지 확인하세요.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

관련 스킬