| name | screenshot-markup |
| description | 강의자료/책 원고에 들어가는 스크린샷에 박스·화살표·번호 배지·하이라이트·블러·캡션을
자동으로 입혀 마크업된 이미지(JPEG/PNG)를 만들고, 원문(MD/HTML/PPTX/DOCX)에 다시 삽입한다.
사용 시점:
(1) "스크린샷 마크업", "screenshot markup" 언급 시
(2) 사용자가 스크린샷 파일 경로 + "이 부분에 빨간 박스 / 번호 / 캡션" 식의 지시를 줄 때
(3) "박스 표시", "캡션 달아줘", "이미지 마크업" 등 키워드 등장 시
(4) 일괄 처리(batch) 요청이 manifest와 함께 들어올 때
|
| trigger_keywords | ["스크린샷 마크업","스크린샷 박스","캡션 달아줘","screenshot markup","mark up screenshot","박스 표시","번호 배지"] |
Screenshot Markup Skill
원본 스크린샷에 코드로 마크업(박스/화살표/번호/하이라이트/블러/캡션)을 그려
마크업된 JPEG 와 (선택) 본문 자동 삽입 까지 해 주는 스킬.
핵심 규약
- 출력 기본은 JPEG (
.marked.jpg, white-flatten). 본 저장소(원자력연구원-handson)의 .sections/build_handson.py 가 data:image/jpeg;base64,… 만 처리하므로 HTML embedder는 비-JPEG 타깃을 거부한다.
- 좌표는 픽셀 정수 또는
"75%" 같은 퍼센트 문자열. 원점 top-left.
- LLM-제안 좌표는 항상 preview-then-confirm 흐름.
--yes 만 prompt 생략.
흐름 — Claude Code 에서 이 스킬을 호출했을 때
- 입력 확인. 사용자가 (a) 이미지 경로, (b) 자연어 지시 또는 spec JSON 경로를 줬는지 본다. 없으면 묻는다 ("어느 스크린샷에 어떤 표시를 할까요?").
- 단일 vs 일괄 결정. 단일 이미지면
render / locate, 디렉터리·manifest면 batch 를 쓴다.
- 명령 실행. 아래 표 참조. 모든 명령은
python -m screenshot_markup ... 로 호출.
- 검증. 출력 JPEG 의 픽셀 크기·존재·exit code 를 확인한다. 실패시 사용자에게 보고.
- 선택: 본문 삽입. 사용자가 원하면
embed 로 MD/HTML/PPTX/DOCX 에 자동 삽입.
명령 치트시트
| 무엇을 | 명령 |
|---|
| 손으로 쓴 spec 으로 렌더 | python -m screenshot_markup render <img> --spec <spec.json> --out <out.jpg> --yes |
| 자연어 지시로 렌더 (LLM) | python -m screenshot_markup render <img> --instruction "우상단 로그인 버튼에 빨간 박스" --out <out.jpg> |
| 위치만 찾기 | python -m screenshot_markup locate <img> --target "로그인 버튼" (LLM-grid + preview) |
| 클릭으로 위치 지정 | python -m screenshot_markup locate <img> --click 412,287 |
| macOS Preview 보면서 클릭 | python -m screenshot_markup locate <img> --click-pick |
| 이미 마크업된 이미지에 op 추가 | python -m screenshot_markup edit <marked.jpg> --add-op '{"type":"caption","anchor":"bottom","text":"수정"}' |
| 일괄 처리 | python -m screenshot_markup batch manifest.yaml --out-dir out/ |
| MD 본문에 삽입 | python -m screenshot_markup embed md <marked.jpg> --doc README.md --anchor markup:foo |
| HTML(원자료연 빌드) 에 삽입 | python -m screenshot_markup embed html <marked.jpg> --doc .sections/section_s1.html --asset s1_image2.jpg |
| PPTX 슬라이드에 삽입 | python -m screenshot_markup embed pptx <marked.jpg> --doc deck.pptx --notes-id step3 |
| 스킬 재설치 | python -m screenshot_markup install-skill --force |
Exit codes (자동화 분기용)
| Code | 의미 |
|---|
| 0 | 성공 |
| 1 | 일반 실패 |
| 2 | 배치에서 needs_review/ 항목 존재 (저신뢰 결과) |
| 3 | CostExceededError — --max-cost 초과 |
| 4 | MimeMismatchError — HTML embedder 가 비-JPEG 거부 |
| 5 | FontMissingError — 한국어 폰트 없음 |
| 6 | SkillAlreadyInstalledError — 이미 설치됨 (—force 로 덮어쓰기) |
Spec 형식 (요약)
{
"schema_version": "1.0",
"image": "examples/s1_image2.original.jpg",
"output": "examples/s1_image2.marked.jpg",
"ops": [
{"type":"box", "xy":[22,20,470,92], "color":"#ff3b30", "thickness":5, "corner_radius":10},
{"type":"badge", "anchor":[40,38], "number":1, "color":"#ff3b30", "size":44},
{"type":"arrow", "from":[780,100], "to":[970,180], "color":"#ff9500", "head":18},
{"type":"highlight", "xy":[560,70,530,420], "color":"#ffeb3b", "opacity":0.18},
{"type":"blur", "xy":[100,100,200,80], "radius":12},
{"type":"caption", "anchor":"bottom", "text":"코어 메시지", "font_size":26, "fg":"#ffffff", "bg":"#000000cc"}
]
}
각 op는 id, z (그리기 순서) 를 옵션으로 가질 수 있다. 좌표는 int 또는 "50%" 문자열.
실제 사례 (원자력연구원-handson)
- 입력:
handson_assets/jpg/s1_image2.jpg (1100×554, 슬라이드 캡처)
- 결과: 제목 박스 + ① 배지 + 균형 저울에 향한 화살표 + 우측 코드 영역 하이라이트 + 하단 캡션
- spec:
tools/screenshot_markup/examples/s1_image2.spec.json
- 재생산:
bash tools/screenshot_markup/examples/run.sh
트러블슈팅
| 증상 | 원인 / 해결 |
|---|
| 한국어가 □□□ 로 나옴 | default_font() 가 후보 폰트를 찾지 못함. brew install font-noto-sans-cjk-kr 또는 SCREENSHOT_MARKUP_FONT=/path/to/font.ttf |
| Batch 가 exit 2 로 끝남 | 일부 항목 confidence < 0.85 → <out_dir>/needs_review/ 에 .preview.jpg 확인 후 spec 보정 |
| HTML embedder 에서 exit 4 | 타깃이 .jpg 가 아님. JPEG 로 재인코딩 또는 --format jpeg 로 렌더 |
| LLM 비용 초과 | --max-cost 5.0 식으로 제한, 또는 LM Studio 백엔드로 전환: SCREENSHOT_MARKUP_BACKEND=lmstudio |
절대 하지 말 것
.sections/build_handson.py 수정 — zero-diff 유지가 acceptance 조건.
embed pptx 를 slide index 로 호출 (NotSupportedError). 반드시 notes_id 와 슬라이드 노트에 <!-- markup-id: X --> annotation 사용.
- 사용자 확인 없이
--auto-accept-all 로 batch 실행 (preview-before-commit 원칙).