영상 → 숙지용 마크다운
Claude Code · codex · goose 공용. 런타임별 변형본을 두지 않는다 — 이 스킬은 셸 명령(ffmpeg)과 이미지 판독만 쓰므로 세 런타임에서 절차가 동일하다. 원본은
codex-personal-skills저장소의skills/video-to-md/이며, 각 런타임 스킬 디렉터리로 복사해 쓴다. 스킬 실행 중에 자신이나 다른 스킬 사본을 수정하지 않는다.
이 스킬이 푸는 문제
에이전트는 영상을 재생할 수 없다. 프레임 이미지로 변환해야 읽을 수 있는데, 프레임 판독은 비싸다(720p 한 장 ≈ 1.5k 토큰). 그래서 아무 프레임이나 많이 뽑는 방식은 실패한다. 비용은 폭발하는데 정작 중요한 순간은 놓친다.
핵심은 구조를 먼저 파악하고 그 구조에 맞춰 표본을 뽑는 것이다. 어디가 변화 구간이고 어디가 반복 구간인지 알면, 판독할 프레임 수를 몇 배로 줄이면서 내용은 더 정확하게 잡을 수 있다.
산출물의 독자는 영상을 못 보는 다른 에이전트다. "영상에 대한 감상"이 아니라 영상을 대체할 수 있는 사실 기록을 써야 한다. 화면에 뜬 숫자·필드명·버튼 이름을 그대로 옮기는 것이 요약보다 훨씬 가치 있다.
실행 전제 — 먼저 확인한다
이 스킬은 셸에서 ffmpeg/ffprobe를 실행할 수 있어야 동작한다. 프레임 추출이 전부 여기에 의존하기 때문이다.
command -v ffprobe ffmpeg || echo "MISSING"
- 둘 다 있음 → 아래 절차를 그대로 수행한다.
- 없는데 패키지 매니저를 쓸 수 있음 → 설치는 사용자 환경을 바꾸는 일이므로 먼저 물어보고 진행한다(macOS
brew install ffmpeg, Debian/Ubuntuapt install ffmpeg, Windowswinget install Gyan.FFmpeg). - 셸 자체가 없는 환경(파일 실행이 불가능한 채팅 전용 환경 등) → 이 스킬은 수행할 수 없다. 추측으로 영상 내용을 지어내지 말고, "이 환경에서는 영상을 프레임으로 변환할 수 없어 분석이 불가능하다"고 명확히 말한다. 사용자가 프레임 이미지를 직접 올려준다면 4단계(판독)부터 §산출물 구조까지는 그대로 적용할 수 있다.
오디오 전사 도구(whisper 계열)는 선택 사항이다. 없으면 §1의 지침대로 "음성 미확보"로 처리한다.
절차
0. 열기 전에 접근 규칙부터 확인
프로젝트에 파일 열람 규칙이 있으면 영상을 열기 전에 먼저 확인한다. macOS에서 Finder 태그로 접근을 통제하는 프로젝트가 흔하다:
xattr -p com.apple.metadata:_kMDItemUserTags "<video>" 2>&1
mdls -name kMDItemUserTags "<video>"
AGENTS.md / CLAUDE.md에 규칙이 있으면 그것을 따른다. 판별이 실패하면 열지 말고 그 사실을 기록한다. 이미 열어버린 뒤에 확인하면 규칙 위반이므로 순서가 중요하다.
1. 메타데이터 — 특히 오디오 유무
ffprobe -v error -show_format -show_streams "<video>"
확인할 것: 재생시간, 해상도, fps, 오디오 스트림 존재 여부.
오디오 유무는 이후 전략을 완전히 바꾸므로 가장 먼저 확정한다.
- 오디오 없음 → 화면 텍스트가 유일한 정보원이다. 프레임 판독에 전부 투자한다.
- 오디오 있음 → 말이 핵심 정보일 가능성이 높다. 전사를 먼저 시도한다:
전사 도구가 없으면 없다고 명시하고 프레임만으로 분석한 뒤, 문서의 "미확인" 항목에 "음성 내용 미확보"를 남긴다. 음성을 못 들었으면서 들은 것처럼 쓰지 않는다.ffmpeg -i "<video>" -vn -ac 1 -ar 16000 audio.wav # whisper / mlx_whisper / faster-whisper 등 설치된 도구로 전사
2. 구조 파악 — 장면 전환 지도
ffmpeg -hide_banner -i "<video>" -vf "select='gt(scene,0.06)',showinfo" \
-vsync vfr -f null - 2>&1 | grep -o 'pts_time:[0-9.]*'
이 출력이 알려주는 것:
- 전환이 몰린 구간 = 화면·주제가 바뀌는 곳. 반드시 판독한다.
- 전환이 없는 긴 구간 = 정적 화면 또는 같은 작업의 반복. 표본 몇 장이면 충분하다. 이 구간의 길이 자체가 중요한 발견인 경우가 많다(예: 4분 영상 중 2분이 단순 반복 입력 = 업무 비효율의 정량 근거).
임계값은 0.06이 화면녹화에 무난하다. 실사 영상은 0.3~0.4로 올린다.
3. 프레임 추출 — 파일명에 타임스탬프를 넣는다
번들 스크립트를 쓰면 위 1~3단계가 한 번에 끝난다. 이 SKILL.md와 같은 디렉터리의 scripts/vidframes.sh 를 실행한다:
# 설치 위치에 의존하지 않고 스킬 디렉터리를 찾는다 (Claude Code / codex / goose 공통)
for d in ~/.claude/skills ~/.codex/skills ~/.config/goose/skills \
./.agents/skills ./.claude/skills ./.goose/skills; do
[ -f "$d/video-to-md/scripts/vidframes.sh" ] && SK="$d/video-to-md" && break
done
bash "${SK:?스크립트 없음 — 아래 -ss 루프를 직접 쓴다}/scripts/vidframes.sh" "<video>" <outdir> [interval]
스크립트를 못 찾으면 아래 3단계의 -ss 루프를 직접 쓴다. 스크립트는 편의 도구일 뿐이고, 절차 자체는 ffmpeg 명령만으로 완결된다.
직접 할 경우 반드시 -ss로 시각을 지정해 파일명에 시각을 박는다:
for t in $(seq 2 5 262); do
ffmpeg -v error -ss $t -i "<video>" -frames:v 1 -q:v 2 "<outdir>/$(printf %03d $t)s.jpg" -y
done
fps=1/5 필터나 mpdecimate 중복제거는 편해 보이지만 출력 파일명이 시각과 대응하지 않는다. 타임라인을 쓸 수 없게 되어 결국 다시 뽑게 된다. 판독한 내용을 시각에 묶으려면 처음부터 -ss 루프로 간다.
간격 선정 (판독 비용과 직결):
| 영상 길이 | 기본 간격 | 대략 프레임 수 |
|---|---|---|
| ~3분 | 3초 | ~65 |
| 3~7분 | 5초 | 40~80 |
| 7~15분 | 10초 | 40~90 |
| 15~30분 | 20초 | 45~90 |
| 30~60분 | 40초 | 45~90 |
| 60분+ | 60초 + 장면전환 보강 | 60~ |
목표는 40~90장이다. 이보다 적으면 조작 단계를 통째로 놓치고, 많으면 비용만 늘고 정확도는 안 오른다. 번들 스크립트가 이 표대로 자동 선택한다.
균등 간격으로 뼈대를 잡고, 2단계에서 찾은 전환 시점 근처만 추가로 뽑아 보강한다.
4. 순서대로 판독
프레임을 시간 순으로 읽는다. 뒤에서 앞으로 가거나 건너뛰면 인과관계를 놓친다.
각 프레임에서 뽑을 것:
- 화면 이름 / 탭 / 창 제목
- 필드명과 입력된 값 (값이 핵심이다)
- 버튼·메뉴·드롭다운 선택지
- 상태바, 번호, 날짜, 사용자명
- 직전 프레임 대비 무엇이 바뀌었는지
뽑은 프레임은 전부 읽는다. 토큰을 아끼려고 "앞뒤가 비슷해 보이니 건너뛰자"고 하면, 건너뛴 그 한 장에 결정적 장면이 들어 있는 경우가 많다. 실제 사례: 5초 간격으로 뽑아놓고 172초와 182초만 읽고 177초를 건너뛰었는데, 그 한 장에 "단가를 수기로 입력 중"인 화면이 있었다. 건너뛴 탓에 "단가는 자동 반영된다"는 틀린 서술이 문서에 들어갔다. 간격을 넓게 잡을지언정, 뽑은 것은 읽는다. 부득이 건너뛰면 어느 구간을 안 봤는지 기록한다.
글씨가 작아 안 읽히면 잘라서 확대한다. 이건 자주 필요하다:
ffmpeg -v error -ss <t> -i "<video>" -frames:v 1 \
-vf "crop=<w>:<h>:<x>:<y>,scale=<w*3>:<h*3>:flags=lanczos" -q:v 2 zoom.jpg -y
작은 숫자, 상태바, 메뉴 목록, 화면 안에 떠 있는 사진/캡처는 거의 항상 확대해야 읽힌다. 흐릿하다고 넘기지 말고 확대해서 확인한다 — 거기에 문서의 핵심 데이터가 있는 경우가 많다.
4.5 공백 추적 루프 — 설명되지 않는 변화를 쫓는다
순서대로 읽다 보면 앞 프레임과 뒤 프레임 사이에 뭔가 일어났는데 그게 뭔지 모르겠는 지점이 생긴다. 8행이던 표가 7행이 되어 있다, 비어 있던 단가 열이 채워져 있다, 값이 바뀌었는데 바꾸는 장면이 없다.
그 구간만 다시 뽑아서 본다. 균등 샘플링이 구조적으로 놓치는 것을 메우는 방법은 이것뿐이다.
이건 한 번 훑고 끝나는 단계가 아니라 루프다. 새로 뽑은 프레임이 또 다른 공백을 만들면 그것도 후보에 넣는다. 실제로 한 단계 더 들어가야 결론이 뒤집히는 경우가 있다:
172s·182s 판독 → "단가가 어떻게 채워졌지?" → 177s 추출
→ 1행만 편집 중 → "나머지 6행은?" → 179.5s 추출
→ 1~6행 완료·7행 편집 중 → "행별 수기 입력" 확정
177초에서 멈췄다면 "1행부터 채우기 시작"까지만 알고, 전파 버튼을 썼을 가능성이 남는다. 179.5초가 있어야 확정된다.
무엇이 트리거인가
"읽은 내용에 설명 안 되는 차이가 있는 구간"이다. "장면전환이 몰린 구간"이 아니다.
이 둘은 자주 어긋난다. 실측 사례 하나를 그대로 적어둔다 — 4분 22초 화면녹화에서 이 루프로 정정한 사실 3건은 전부 장면전환이 0개인 구간에서 나왔고, 반대로 전환이 몰린 구간(초당 3~4회 검출)을 이분해서 얻은 새 사실은 0건이었다.
이유는 구조적이다:
- 전환 검출이 잡는 건 탭 전환·창 열림처럼 화면이 통째로 바뀌고 몇 초씩 지속되는 변화다. 그건 균등 샘플링이 이미 잡는다. 거기에 프레임을 더 쓰는 건 대체로 중복이다.
- 정작 놓치는 건 그리드 한 열이 채워지거나 행 하나가 사라지는 변화다. 픽셀 변화가 작아 전환 검출에 안 걸리고, 표본 간격 사이에 끝난다. 전환 밀도를 트리거로 쓰면 이런 건 영원히 못 잡는다.
그래서 장면전환 목록은 3단계에서 구조를 파악하는 용도로만 쓰고, 이 루프의 트리거로는 쓰지 않는다.
루프 운영
- 판독하면서 설명 안 되는 변화를 목록에 쌓는다. 각 항목에 "이게 풀리면 문서의 어떤 서술이 바뀌는가"를 함께 적는다.
- 그 영향이 큰 것부터 구간을 이분한다:
ffmpeg -v error -ss <중간시각> -i "<video>" -frames:v 1 -q:v 2 gap.jpg -y - 새로 읽은 프레임이 만든 공백도 같은 기준으로 목록에 넣는다.
- 예산이 남아 있고 목록에 "문서를 바꿀 수 있는" 항목이 남아 있으면 2로 돌아간다.
언제 멈추는가
화면녹화는 무한히 잘게 쪼갤 수 있다. 깊이 제한만으로는 부족하고, 두 가지 기준을 함께 쓴다.
① 문서 영향 판정 — 이게 주 기준이다. "이 공백을 풀면 내가 쓸 문장이 달라지는가?"
- 달라진다 → 쫓는다. 특히 단정해서 쓸 값이 걸린 공백은 반드시 쫓는다. "이 값은 자동 계산되었다"고 쓰려면 그 사이에 사용자가 버튼을 눌렀는지 확인해야 한다. 확인 없이 쓰면 문서가 틀리고, 독자는 영상을 못 보므로 검증할 방법이 없다.
- 안 달라진다 → 버린다. 마우스 이동 경로, 0.3초 떴다 사라진 툴팁, 이미 확립된 패턴의 반복(행별 입력이 확인된 뒤 "3행은 언제 채워졌나")은 쫓지 않는다.
② 총 예산 — 발산 방지용이다. 추가 판독은 1차 표본의 20% 이내로 잡는다(53장이면 10장 남짓). 깊이가 아니라 총량으로 거는 이유는, 한 공백이 깊게 들어가야 풀리는 경우와 여러 공백이 얕게 풀리는 경우 중 어느 쪽이 나을지 미리 알 수 없기 때문이다.
못 푼 것은 반드시 남긴다. 예산이 끝나거나 이분해도 안 잡히면 "미확인"에 좁혀진 구간과 함께 적는다 — "27.0~27.4초 사이에 발생, 그 안은 확인 불가". 어디까지 좁혔는지가 정보이고, 예산이 모자랐다는 사실도 정보다. 조용히 지우면 독자는 그 공백의 존재조차 모른다.
5. 교차 검증
이게 이 스킬에서 가장 중요한 단계다. 판독한 숫자들 사이의 관계를 실제로 계산해 맞는지 확인한다.
- 합계가 항목 합과 맞는가
- 단가 × 수량 = 금액인가
- A 화면의 값이 B 화면의 같은 항목과 일치하는가
- 화면 밖 자료(첨부 이미지, 다른 탭)의 값과 입력값이 일치하는가
효과가 두 가지다. 첫째, 오독을 잡는다(저해상도에서 8/B, 0/O, 1/l은 자주 헷갈린다). 둘째, 불일치 자체가 발견이 된다. 예를 들어 원본 자료의 수량과 실제 입력값이 다르면, 그 영상은 실제 업무 처리가 아니라 시연일 가능성이 크다 — 이런 판단은 문서 신뢰도를 크게 좌우하므로 반드시 명시한다.
6. 문서 작성
영상 파일과 같은 이름의 .md 를 같은 폴더에 만든다 (ERP사용예시1.avi → ERP사용예시1.md). 사용자가 다른 경로를 지정하면 그걸 따른다.
산출물 구조
아래는 뼈대다. 영상 유형에 맞게 가감하되, 굵게 표시한 것은 빼지 않는다 — 독자가 영상을 못 보는 상황에서 이것들이 없으면 문서를 신뢰할 수 없다.
# <파일명> — 영상 내용 분석
> 이 문서는 영상을 직접 볼 수 없는 에이전트가 <파일명>의 내용을 숙지하기 위한 대체 자료다.
## 1. 파일 메타 ← **오디오 유무를 반드시 포함**
## 2. 한 줄 요약 ← **전체를 한 문장으로**
## 3. 등장 요소 ← 시스템/조직/인물/화면 등 고유명사
## 4. 타임라인 ← **시각 + 화면 + 무슨 일이 일어났는지**
## 5. 화면(장면)별 상세 ← 필드 구조, 선택지, 실제 값
## 6. 데이터 ← 표로 옮긴 수치. 검증식도 함께
## 7. 흐름 / 프로세스 ← 단계 간 인과관계
## 8. 도메인 지식 ← 이 영상을 이해하는 데 필요한 배경
## 9. 시사점 ← 관찰된 사실에 근거한 것만
## 10. 확인 상태 구분 ← **확인된 사실 / 추정 / 미확인**
유형별 강조점
- 업무 시스템 화면녹화: 5·6·7번이 핵심. 필드명·선택지·자동계산 동작·번호 체계를 그대로 옮긴다. 사용자가 어디서 시간을 많이 쓰는지(2단계의 정적 구간)를 정량으로 기록한다.
- 회의·발표 녹화: 오디오 전사가 본체. 프레임은 슬라이드·화면공유 캡처용 보조.
- 튜토리얼·데모: 4·7번 중심. 재현 가능한 단계 순서로 쓴다.
- 실사 영상: 3·4번 중심. 장면 전환 임계값을 높여 표본을 잡는다.
판독 정확도 원칙
문서의 가치는 정확도에서 나온다. 영상을 못 보는 독자는 이 문서를 검증할 방법이 없으므로, 틀린 단정은 요약이 부실한 것보다 훨씬 해롭다.
확인된 사실 / 추정 / 미확인을 반드시 분리한다.
- 확인된 사실: 화면에서 직접 읽었고, 가능하면 교차 검증까지 통과한 것
- 추정: 근거는 있으나 화면이 단정하지 않은 것. 근거를 함께 적는다
- 미확인: 영상에 없거나, 잘렸거나, 판독 실패한 것. 비워두지 말고 없다고 적는다
특히 이런 것들은 미확인으로 명시한다: 오디오 미전사, 잘린 이미지의 나머지 부분, 클릭했지만 결과만 보이고 과정이 안 보인 팝업, 표본 간격 사이에 지나간 조작.
추측으로 빈칸을 메우지 않는다. "아마 저장했을 것"은 쓰지 않고 "저장 버튼 클릭 직전 프레임과 저장 후 프레임만 확인됨"이라고 쓴다.
흔한 실패
- 프레임을 너무 많이 뽑는다 — 구조 파악 없이 1초 간격으로 뽑으면 비용만 나가고 정확도는 안 오른다. 2단계를 건너뛰지 않는다.
- 파일명에 시각이 없다 — 타임라인을 못 쓴다.
-ss루프로 간다. - 작은 글씨를 넘긴다 — 상태바·번호·메뉴에 핵심 정보가 있다. 확대해서 읽는다.
- 화면 안의 화면을 무시한다 — 채팅창에 붙은 사진, 열려 있는 다른 앱, 미리보기 창이 영상의 입력 출처인 경우가 많다.
- 요약만 쓰고 값을 안 옮긴다 — 독자에게 필요한 건 "수주를 등록했다"가 아니라 "수주번호 SOZ20260700195, 7행, 합계 10,665,268원"이다.
- 접근 규칙 확인을 나중에 한다 — 여는 순간 이미 늦다. 0단계를 먼저 한다.
- 표본 사이에서 일어난 일을 추론으로 메운다 — "값이 채워졌으니 자동 계산됐겠지"가 가장 흔한 오류다. 4.5단계로 실제로 확인하거나, 확인 못 했다고 적는다.