Sticky Director — AI 영화 감독 플레이북
이 저장소는 로컬 애니메이션 및 무성 영화 엔진입니다. 리깅된 검은 실루엣 캐릭터(회색 후드 착용)가 사진(예: Google Flow 이미지) 앞에서 음악, 앰비언트 사운드, 카메라 움직임, 자막과 함께 연기합니다. MCP 도구(.mcp.json에 sticky-studio → node mcp-server.js 등록) 또는 CLI(node cli.js …)를 통해 감독할 수 있습니다. 두 방식 모두 server.js를 자동으로 시작하며, 캔버스 작업은 스튜디오를 엽니다(디스플레이가 없으면 헤드리스 Chromium 사용).
절대 파일 경로를 항상 사용하세요. 아래 모든 ID는 검증됩니다. 알 수 없는 값은
warnings로 반환되며 적용되지 않으므로 경고를 반드시 읽어보세요.
Antigravity에서 실행:
sticky-studioMCP 도구를 사용할 수 없으면 저장소 루트에서 CLI를 사용하세요. 모든 MCP 도구에는 CLI 대응 항목이 있습니다(아래 표).node cli.js snapshot <t> <abs.png>는 비전으로 열 수 있는 PNG를 생성합니다. 모든 명령은 스튜디오 서버를 자동으로 시작합니다.
도구 (MCP) ↔ CLI
| MCP 도구 | CLI | 기능 |
|---|---|---|
sticky_status | node cli.js status | 모드, 종횡비, 길이, BPM/비트 수, 연결된 탭, 장면 목록 |
sticky_get_project | node cli.js get-project [out.json] | 전체 프로젝트를 평면 에이전트 형식으로 반환 (장면, fxMarkers, mediaCards, audio.beats/strongBeats, 배경 + lightProfile) |
sticky_load_audio | node cli.js load-audio <path> --mode silent | 음악/음성 로드 → {duration, bpm, beats[], strongBeats[]} |
sticky_import_photos | node cli.js import-photos <p1> <p2> … [--auto-build] | 사진 등록 → [{bgId, name, path, width, height, lightProfile}] |
sticky_apply_template | node cli.js template <id> [--no-photos] | 오디오와 사진에 맞춰진 무성 영화 스토리보드 로드 |
sticky_set_project | node cli.js set-project <file.json | '{…}'> | 전체 또는 부분 스토리보드 푸시 (전송한 키만 적용) |
sticky_update_scene | node cli.js update-scene <index|id> '{…}' | 하나의 장면 패치 |
sticky_split_scene | node cli.js split <timeSec> [--no-snap] | 특정 시간에 분할, 가장 가까운 비트 (±0.35초)로 스냅 |
sticky_add_fx | node cli.js add-fx <type> <timeSec> [--duration s] | 카메라 펀치 / SFX / card |
sticky_render_frame | node cli.js snapshot <timeSec> [out.png] | 정확한 프레임을 PNG로 (MCP는 이미지로도 반환) |
sticky_export_mp4 | node cli.js export | 실시간 렌더링 → exports/sticky_video_*.mp4 (60fps H.264 + AAC) |
get_status, get_project, set_project, update_scene은 스튜디오 탭이 열려 있지 않아도 작동합니다. projects/live_state.json을 읽고 쓰며, 스튜디오는 연결 시 해당 파일을 로드합니다.
참조 ID
감정 (10개)
| id | 용도 |
|---|---|
neutral | 기본, 평온 |
happy | 따뜻함, 안도, 작은 승리 |
tired | 새벽 3시, 번아웃, 탈진 |
crying | 슬픔, 무너짐 (silentMouth: quiver와 함께 사용) |
angry | 좌절 |
shocked | 공포, 깨달음 |
skeptical | 의심, 곁눈질 |
confused | "?" 순간 |
excited | 흥분 (별눈) |
deadpan | 공허함, 무감각 |
제스처 (18개) — gesture
| id | 설명 | 최적 뷰 |
|---|---|---|
pocket | 손을 후드 주머니에 (차분한 기본) | any |
idle | 이완된 팔 (걸을 때 흔들림) | any |
talking | 오디오 반응형 손 비트 (음성) | front |
explain | 양손을 펼침 | front |
point_screen | 옆으로 가리킴 (미디어 카드) | front |
point_viewer | 카메라를 가리킴 | front / 3/4 |
crossed | 팔짱 | front |
facepalm | 손으로 얼굴 가림 | front |
hands_head | 머리에 손을 얹음 (공포) | front |
shrug | 어깨 으쓱, 손바닥 위로 | front |
wave | 손 흔듦 | front |
typing | 책상에 앉아 타이핑 (책상 + 의자 자동 그림) | auto 3/4–side |
slouch_lonely | 깊게 구부림, 머리 숙임, 느린 깊은 호흡 | front / 3/4 |
heavy_sigh | 4.5초 주기: 들숨 → 멈춤 → 축 처짐 (자동 호흡 효과음) | front / 3/4 |
check_phone_dark | 빛나는 전화기를 듦; 얼굴과 후드에 푸른 빛 원뿔 | front / 3/4 |
sit_curb_hug_knees | 바닥에 앉아 무릎을 껴안고 머리 숙임 | auto 3/4 |
look_back_horizon | 서서 전망을 응시, 후드에 바람 | back / 3/4 |
pull_hood_up | 동작: 뒤로 손을 뻗어 후드를 올림 (~장면 시작 후 2.3초) | front |
신체 및 포즈 키
| 키 | 값 |
|---|---|
pose | rig (관절형, 기본) · v1 스프라이트: front, bust, side, back |
view | front, threeQuarter, side, back |
hoodUp | true / false (모든 뷰에 후드 그림; 뒤 뷰는 기본적으로 올림) |
walkSpeed | 0 대기 · 0.1–1.0 걷기 · 1.1–2.5 조깅 → 전력 질주 |
walkDir | left, right |
walkInPlace | true (러닝머신) / false (프레임 가로질러 이동, 화면 반대편으로 나타남) |
wind | 0..1 (옷자락, 끈, 후드) |
silentMouth | closed (기본) · sigh · quiver (울음/불안) |
handLeft, handRight | auto, relaxed, open_palm, pointing, fist, holding_prop, in_pocket |
prop | none, phone, mug, mic, controller, book |
spineLean, headTilt, headNod | 각도 (≈ −25…25; headNod + = 아래를 봄) |
ikPins | { rightHand|leftHand|rightFoot|leftFoot|head: {x, y} } (리그 단위, 원점 = 발 사이 바닥, +x = 바라보는 방향, 위는 음수 y; 머리는 y ≈ −300, 손은 y ≈ −130 근처). {}로 초기화 |
x, y, scale, flipX | 위치 0..1 (x 0.5 = 중앙; y ≈ 0.55 = 하단 1/3 지점), 크기 (1 = 기본), 반전 |
motion | breathe (무성 영화 기본), talk_bounce, walk, shake (떨림), float, none |
emotion | 위 표 참조 |
배경 — background
내장: paper_sketch, cozy_night, rainy_window, streetlight (심야 가로등), classroom (일몰 책상), dark_spotlight, rooftop_dusk, green_screen.
사진: sticky_import_photos가 반환한 bgId를 사용하거나, background에 절대 사진 경로를 바로 넣으세요 (자동으로 가져옴).
사진 카메라 및 깊이
| 키 | 값 |
|---|---|
kenBurns | none, push_in, pull_out, drift_left, drift_right, breathing (사진 100%, 캐릭터 30% 이동 → 시차 효과) |
foreground | none, bokeh, rain_streaks, window_reflection |
camera | static, zoom_in, zoom_out, pan_right, handheld (kenBurns 위에 적용) |
atmosphere | dust (음악 비트에 따라 빛남), rain, none |
dutchScene / spotlightScene | 장면 전체 기울어진 지평선 / 배경 60% 어둡게 |
라이트 매치 (사진 조화) — lightMatch
true = 권장 (tint 0.35, rim 0.55, exposure 0.5) · false = 끔 · 숫자 0..1 = 전체 강도 · 또는 { tint, rim, exposure, side } (side = auto (사진에서) | left | right | back (역광, 양쪽 가장자리).
모든 사진 장면에 true를 사용하세요. 일몰과 역광 지평선에는 rim을 높이고(0.7–0.9), look_back_horizon에는 side: "back"을 사용하세요.
전환 (장면이 들어오는 방식) — transitionType, transitionDur (0–2초)
cut · dissolve (두 샷이 실시간으로 렌더링되어 혼합) · fade_black (시간 경과, 외로움) · fade_white (회상, 깨달음, 희망). dissolve 또는 fade_black이 있는 0번 장면은 검은색에서 페이드인됩니다. fadeOutEnd: true는 영화 끝을 검은색으로 페이드아웃합니다.
앰비언트 배경음 (연속, 장면별) — ambientBed, ambientVol 0..1
| id | 분위기 |
|---|---|
none | — |
rain_window | 부드러운 빗소리 + 먼 천둥 (발자국도 젖은 소리) |
night_wind | 외로운 자정 바람 |
vinyl_crackle | 따뜻한 로파이 잡음 |
clock_ticking | 60 BPM 반향성 째깍 소리: 새벽 3시, 불면증, 공허함 |
heartbeat | 깊고 막힌 심장 박동: 불안, 공포 |
crowd_muffle | 저역 통과 웅성거림: 붐비는 방 안의 외로움 |
FX 마커 — sticky_add_fx / fxMarkers: [{type, timeSec, …}]
- 카메라 펀치:
snap_zoom(1.0→1.25× 스프링처럼 얼굴 줌인),dutch_tilt,shake,spotlight(+duration,intensity0..3,dir±1 for dutch) - SFX / 효과음 (10개):
whoosh,pop,vine_boom,record_scratch,shutter,typing,footstep_wet,heavy_sigh_breath,phone_vibrate,door_close_echo(+volume) - 장면은
transitionSfx(컷에서 재생되는 SFX)와foley: true(자동 발자국 + 한숨 호흡; 무성 모드에서 기본 켜짐)를 설정할 수 있습니다. - 미디어 카드:
type: "card"+card: {kind: image\|meme\|post\|note, text, imagePath, side: auto\|left\|right, hold, size}
프로젝트 수준 키 (sticky_set_project)
| 키 | 값 |
|---|---|
mode | silent (음악만, 입술 싱크 없음) · voiceover |
aspectRatio | 16:9 · 16:9-letterbox (2.35:1 시네마 바) · 9:16 (Shorts / Reels / TikTok, 720×1280) |
fadeOutEnd | true 또는 초 |
masterAmbientVol | 0..1 |
captionStyle | cinematic (무성 영화 세리프), pop, karaoke, classic, off, 또는 {mode, highlight, position: bottom|middle|top, chunk, uppercase, size} |
snapToBeats | 기본 true: 컷이 가장 가까운 비트로 스냅 |
scenes | 평면 장면 객체. 타이밍: 모든 장면에 start/end를 주거나, 아예 주지 않고 duration / weight 사용 (음악에 분산) |
fxMarkers | 위 참조 |
mediaCards | [{sceneIndex | timeSec, kind, text, imagePath, appear, hold, side}] |
템플릿 — sticky_apply_template
loneliness_3am (어둠 속 전화 → 후드 쓴 빗속 산책 → 길가에 무릎 껴안음 → 새벽 지평선) · social_anxiety (구석에 웅크림 + 군중 웅성거림 → 심장 박동 공포 → 바람 속 밖으로 나가기 → 안도의 한숨) · burnout (책상에서 타이핑 → 빈 응시 + 시계 → 검은색 페이드 → 빗속 산책) · discipline (피곤한 기상 → 후드 올리기 → 1.2배 조깅 → 2.0배 일출 속 전력 질주).
연출 워크플로우
- 보고 듣기. 사용자의 사진을 비전으로 살펴보고(이미지 파일 읽기) 감정 호를 결정합니다 (예: 고립 → 한계점 → 해방 → 희망).
sticky_load_audio {path, mode: "silent"}로 음악을 로드하고duration,bpm,strongBeats(최적의 컷 포인트)를 기록합니다. - 사진 가져오기 및 매핑.
sticky_import_photos {paths: [...]}를 스토리 순서대로 실행합니다. 각lightProfile(tonewarm/cool,brightness,lightFrom)을 사용하여 비트를 선택합니다. 어둡고 차가운 방은check_phone_dark/slouch_lonely+clock_ticking에 적합합니다. 비 오는 거리는 후드pocket산책 +rain_window+rain_streaks에 적합합니다. 일몰과 스카이라인은look_back_horizon(뒷모습,lightMatch {rim: 0.8, side: "back"}) +night_wind에 적합합니다. - 스토리보드 구성. 한 번의
sticky_set_project호출로:mode: "silent",captionStyle: "cinematic",fadeOutEnd: true, 사진당 하나의 장면. 각 장면에background(경로 또는 bgId),gesture,emotion,view,hoodUp,kenBurns,lightMatch: true,ambientBed,transitionType(첫 장면fade_black, 주로dissolve1.0–1.5초, 시간 점프fade_black, 희망 전환fade_white), 짧은 시적subtitle(≤ 8단어, 또는 빈칸),weight를 설정합니다. 몇 가지fxMarkers를 추가합니다(phone_vibrate,door_close_echo, 감정적 정점에snap_zoom). 결과의warnings를 확인하세요. - 시각적 검사.
sticky_render_frame을 2–3개의 주요 시점(첫 장면의 페이드 후 ~1.5초, 중간, 클라이맥스)에서 실행합니다. 캐릭터가 프레임 안에 완전히 있고 바닥에 닿았는지(y,scale,x조정), 림과 틴트가 사진과 일치하는지(lightMatch조정), 자막이 읽기 쉽고 가려지지 않았는지, 얼굴이 카드로 가려지지 않았는지 확인합니다.sticky_update_scene으로 수정하고 다시 렌더링합니다. - 내보내기. 사용자가 준비되면
sticky_export_mp4로 내보냅니다. 렌더링 시간은 영화 길이 + 인코딩 시간 정도입니다.mp4Path를 보고합니다.
무언 감정 단편 영화 취향 가이드
- 더 적고 긴 샷(4–8초).
strongBeats에서 컷.heavy_sigh와slouch_lonely는 최소 한 주기(≥ 4.5초) 동안 숨 쉬게 둡니다. hoodUp: true= 위축 / 비 / 불안; 후드 내림 = 개방감, 안도.walkSpeed는 우울한 산책에 0.4–0.6, 단호한 조깅에 1.2, 클라이막스 전력 질주에만 2.0+ 사용.- 감정과 입 움직임을 짝지음:
crying+quiver,tired+sigh. 무성 모드에서는talking을 사용하지 마세요. - 장면당 하나의 앰비언트 배경음을 0.4–0.8 볼륨으로 사용. 컷에서 배경음을 변경하여 새로운 장소를 표시.
9:16에서는x≈ 0.5,scale0.9–1.1 유지. 자막과 카드는 자동으로 재배치됩니다.
예제 스토리보드
{
"mode": "silent", "aspectRatio": "16:9-letterbox", "captionStyle": "cinematic", "fadeOutEnd": true,
"scenes": [
{ "title": "3 AM", "background": "/abs/photos/bedroom.jpg", "gesture": "check_phone_dark", "emotion": "tired",
"kenBurns": "push_in", "lightMatch": true, "ambientBed": "clock_ticking", "transitionType": "fade_black", "transitionDur": 1.2, "subtitle": "3:07 AM." },
{ "title": "Rain Walk", "background": "/abs/photos/street.jpg", "gesture": "pocket", "view": "threeQuarter", "hoodUp": true,
"walkSpeed": 0.55, "walkInPlace": false, "x": 0.25, "foreground": "rain_streaks", "ambientBed": "rain_window",
"lightMatch": true, "transitionType": "dissolve", "transitionDur": 1.2, "weight": 1.2 },
{ "title": "Dawn", "background": "/abs/photos/sunset.jpg", "gesture": "look_back_horizon", "view": "back", "wind": 0.6,
"lightMatch": { "rim": 0.8, "side": "back" }, "kenBurns": "pull_out", "ambientBed": "night_wind",
"transitionType": "fade_white", "subtitle": "But the sun still came up." }
],
"fxMarkers": [ { "type": "phone_vibrate", "timeSec": 0.8 } ]
}