| name | autorig-tha4-eyes |
| description | AUTORIG 리그에 THA4 자연 감은눈을 비파괴로 베이크 주입하고, 웹캠 눈 트래킹을 버튜버 표준으로 끌어올린다. ★THA4 리그는 바이너리(뜬눈디테일 L·R 전부 ParamEyeLOpen에 묶임·open은 0.97~1.0서만) → 양눈 링크+1.0 SNAP 필수, 눈 개폐는 drift-track baseline+넓은 plateau(고정 데드존·머리각도보정 폐기). 010(루비) R&D로 배포수준 검증된 character-agnostic 파이프라인 — scripts/inject_tha4_eyes.py(4단 알파필터+뜬눈숨김키프레임) + 공유 드라이브 템플릿(scripts/templates/mini_cubism_drive.html). 디버깅은 추측 금지·HUD 숫자 실측. 트리거 — "THA4 눈", "자연스러운 깜빡임", "눈 표현력", "눈 사라짐/한쪽 눈 소멸", "눈 잔상/앞머리 딸려옴", "윙크 안 됨", "고개 들면/돌리면 눈 감김", "바로 감김", "눈 트래킹 표준", "tha4 eyes", "eye blink ghost". 배포본 불가침 — 항상 rig_v0_project_tha4eyes 변종에. |
AUTORIG THA4 표현력 눈 (감은눈 주입 + 트래킹 표준)
리그 깜빡임은 원래 2상태 텍스처 스왑(open eye_white/iris ↔ eye_*_blink.png)이라 별개작화 스냅이고, 원본 blink는 ParamEyeLOpen=0.27에서도 안 닫히는 경우가 있다(동공 노출). THA4 감은눈을 주입하면 더 깨끗하게 닫히고, 메시에 얹혀 머리턴·물리 자동 추종한다. 010(루비) 배포수준 검증.
비협상 (Non-Negotiables)
- 주인님이라 부른다. 시각 판정은 주인님 전담 — Claude가 PASS 선언 금지([[show-results-open-png]]).
open으로 띄우고 사실만 보고.
- 배포본 불가침: 항상
rig_v0_project_tha4eyes 비파괴 변종에 주입. 원본·Vercel 배포 static은 건드리지 않는다.
- 검증은 성역: 강제 파라미터 실렌더(capture_pose)로 자산 무죄/유죄를 가린 뒤 트래킹을 만진다. 라이브 증상≠자산 결함.
1. 선행: THA4 프레임 생성 (Colab)
THA4 헤드리스 추론으로 crypko-512 표정 프레임 → Real-ESRGAN 애니6B 4×→2048 SR. 프레이밍이 생명 — eye_white 앵커 + 작동배율(008 SCALE 0.1638·EYE_CRYPKO 262,152)로 정렬해야 입·눈이 열린다([[expression-control-sota-tha4]] PoC, frame_*_crypko.py). 산출 = grid 폴더(m0_b0.png 뜬눈·m0_b2.png 감은눈).
2. 주입 (character-agnostic 스크립트)
python3 scripts/inject_tha4_eyes.py \
--src experiments/autorig-character-<id>/rig_v0_project \
--dst experiments/autorig-character-<id>/rig_v0_project_tha4eyes \
--grid experiments/autorig-character-<id>/tha4_expr_poc/grid_sr
- 변종 없으면 자동 복사 생성.
--framing-json affine_rig_to_crypko.json으로 scale·eye_crypko 자동(없으면 인자).
--character-spec characters/<id>.yaml을 지정하면 tha4_eye: 섹션의 diff_threshold/eye_white_margin/darkgate/front_hair_part_names로 필터를 오버라이드할 수 있다. run_autorig_pipeline.py --tha4-grid-dir 사용 시에는 자동 전달된다.
- 4단 알파필터(전부 파트/기하 기반, 색 무관 = 모델 무관): footprint × 눈꺼풀변화영역(open↔closed diff, eye_white bbox 공간제한) × darkgate(어두운 속눈썹만, 밝은 윗주름 투명) × front_hair 파트영역 제외(머리 침범 방지 — 색 게이트는 머리색 바뀌면 깨져서 폐기, 파트영역이 정답).
- 뜬눈 숨김 키프레임 자동 주입: 루비처럼 파트명이
R_eye_white(≠eye_L_ 접두사)면 런타임 crossfade(eyeOpenDetailOpacity) 대상에서 빠져 감아도 안 숨겨짐 → blink 위 잔상. ParamEyeLOpen 숨김 키프레임(0.97→1.0 페이드인)으로 blink와 짝지어 제거. 멱등.
3. 검증 (실렌더 A/B — 주인님 판정)
python3 scripts/capture_pose.py --project .../rig_v0_project_tha4eyes --out /tmp/ck \
--poses '[{"name":"open","parameters":{"ParamEyeLOpen":1.0,"ParamEyeROpen":1.0}},{"name":"closed","parameters":{"ParamEyeLOpen":0.27,"ParamEyeROpen":0.27}}]'
눈 영역 확대 몽타주로 잔상/머리/주름 확인. 강제 0.27만 보지 말 것 — 중간값(0.5·0.7) 스윕도(라이브 전환 재현). 자산 깨끗하면 트래킹으로.
4. ★THA4 리그 = 바이너리 (트래킹 만지기 전 반드시 이해)
character.json의 part_opacity_keyframes를 보면 (capture_pose로 실렌더 확인):
- 뜬눈 디테일(L·R 둘 다 — L/R_eye_white·iris·upper_lash)이 전부
ParamEyeLOpen 하나에 묶임. blink 텍스처만 좌우 분리(eye_L_blink←ParamEyeLOpen, eye_R_blink←ParamEyeROpen).
- 뜬눈은 ParamEyeLOpen 0.97~1.0서만 보인다 (0.87도 이미 "감김" 렌더 —
[{value:0.27,op:0},{value:0.97,op:0},{value:1.0,op:1}]).
- ⇒ 두 파라미터가 벌어지면 한 눈이 뜬눈·blink 모두 숨겨져 소멸. 중간값(0.5~0.9)은 전부 감김 렌더.
불변식 (어기면 소멸/감김): ① ParamEyeLOpen == ParamEyeROpen (단일 링크값을 둘에). ② 뜰 땐 1.0까지 SNAP(중간값 금지). 아카네(008, 연속 메시 리그)는 per-eye 독립·1-eyeBlink 중간값 OK지만 THA4선 독. "아카네 잘됐는데 루비 안 됨"의 정체 = 트래킹 아닌 리그 구조차. → [[tha4-eyes-rig-requires-linked-1.0]].
5. 웹캠 눈 트래킹 표준 (공유 템플릿, 전 모델 자동)
scripts/templates/mini_cubism_drive.html convert()에 박혀 모든 모델 자동(per-model 아님). 마커 grep:
EYE-DRIFT-TRACK-001 + 넓은 plateau: eyeBlink "open" 레벨은 사람·카메라·고개각마다 다르고 드리프트한다(010 주인님 실측: 정면 0.37·고개듦 0.54, pitch엔 안 잡힘=0°). 고정 절대값(옛 0.25~0.48) 금지. → baseline이 ① 더 뜨면 빠르게 내림(0.05) ② 조금 위(<0.28)=pose 드리프트면 추종(0.04) ③ 확 튐(≥0.28)=깜빡임이면 고정/무시. 데드존 = baseline+0.28(뜸≤) ~ +0.45(감김≥). margin을 넉넉히 둬 추종 lag 없이도 고개듦이 처음부터 plateau 안(=바로 안 감김). openBoth를 두 파라미터에 동일 적용(THA4 불변식).
EYE-SMOOTH-001: 시간축 EMA(감김 k0.45·뜸 k0.3). raw 1프레임 스냅 완화.
EYE-WINK-HOTKEY-001: 윙크=핫키 Q/W. THA4선 독립 윙크 불가(뜬눈디테일이 ParamEyeLOpen 공유) → Q/W는 양눈 깜빡으로 강등.
- 폐기됨:
EYE-DEADZONE(고정값)·EYE-LINK(max, 코너서 멀쩡한 눈까지 감김)·HEAD-ANGLE-COMP/GAZE-COMP/PITCH-FORESHORTEN(고개 들어도 head_pitch=0°라 죽은코드)·트러스트게이트·워치독. 전부 "고정 절대 임계가 세션마다 어긋난 걸" 메우려던 증상패치였고, drift-track 하나로 대체.
- HUD
?panel=1: eyeBlink raw L/R·보정후·baseline·데드존(뜸≤·감김≥)·EyeOpen 최종. /drive 기본은 OBS 초록 크로마키(패널 숨김).
드라이브: python3 scripts/run_mini_cubism_webcam_drive.py --project .../rig_v0_project_tha4eyes --port <p> --no-open → open http://127.0.0.1:<p>/drive?panel=1. 템플릿은 매 요청 새로 읽혀 하드새로고침만으로 반영(빌드 불요). 배포 반영은 build_player_webapp.py 재빌드+재배포.
6. ★측정 우선 (이 세션이 5턴 날린 이유)
눈 트래킹 계수를 추측으로 바꾸지 말 것 — HUD 숫자를 읽고 고친다. 010 디버깅이 길어진 유일한 원인 = 실측 없이 margin/계수를 감으로 돌림. 올바른 루프:
- 주인님께 증상 순간 HUD 5줄(특히
eyeBlink raw·baseline·데드존·pitch°) 받기. 고개 든 채 멈춰 읽으면 sustained라 안정.
- THA4 자산 무죄는 capture_pose로 가린다(ParamEyeLOpen 1.0/0.87/0.5 스윕 → 1.0만 뜸 확인).
- 계수 후보는 node로 수치 시뮬(remapDeadzone 재현)해 실측값 통과 확인 후 적용.
- pitch 같은 신호는 실제로 잡히는지 HUD로 먼저 확인(고개 들어도 0°면 그 축은 죽은코드).
7. 디버깅 레퍼런스 (010서 산 교훈)
| 증상 | 원인 | 수정 |
|---|
| 한쪽 눈 소멸 | L/R 파라미터 벌어짐(per-eye 독립) | 양눈 링크(단일값 둘에) — THA4 불변식 |
| 고개 들면 감김/평상 반쯤감김 | open 레벨이 데드존 위(고정 절대값) | drift-track + 넓은 plateau(margin +0.28) |
| 고개 들 때 바로 감김 | 추종 baseline lag | plateau를 넉넉히(추종 없이도 즉시 커버) |
| 윗눈 잔상(속눈썹) | 뜬눈 파츠 crossfade 제외(R_ 접두사) | 뜬눈 숨김 키프레임(스크립트 자동) |
| 밝은 아치 잔상 | blink 윗주름 반투명 | 알파=눈꺼풀변화영역×darkgate |
| 앞머리 딸려옴 | THA4 머리 미세이동이 diff에 잡힘 | eye_white bbox 제한 + front_hair 제외 |
| 입·눈 안 열림 | 프레이밍 작음/비율 | eye_white 앵커+작동배율 |
| 감은눈에 머리색 얼룩(어두운 머리) | THA4가 머리를 리그에 없는 위치로 재작화 → diff 발화·darkgate 통과·파트영역 제외 무력(오염픽셀 hair 커버 0% 실측, URO 2026-07-09) | lid_component_gate(꺼풀=가로≥세로 성분만, 색 무관) — 스크립트 내장. 임계 상향은 기각(꺼풀 42% 손실) |
관련 메모리 [[tha4-eyes-rig-requires-linked-1.0]]·[[expression-control-sota-tha4]]·[[expression-tha4-only-no-mixing]]·[[visual-verify-real-render]]·[[citation-authority-overclaim]].