저장소 워크스루 비디오
목표는 팀원이 저장소를 이해할 수 있는 비디오입니다: 저장소의 목적, 각 부분이 어떻게 연결되는지, 그리고 실제로 실행되는 모든 함수(현재 고장난 부분 포함)를 보여줍니다. 두 가지 작업이 혼합되어 있으며, 다음 순서로 진행되어야 합니다:
- 실제로 저장소를 테스트합니다. 비디오에 표시되는 모든 명령어는 실제로 실행되었고 그 출력을 읽었습니다.
- 스토리로 녹화합니다. 챕터는 시스템의 구조를 따르며, 각 챕터에는 내레이션이 있습니다.
성공하는 명령어만 보여주는 비디오는 팀을 오도합니다. 테스트 중 발견한 실패는 종종 비디오에서 가장 가치 있는 부분이므로, 별도의 마지막 챕터로 제공하세요.
출력 구성
저장소 외부의 폴더에서 작업합니다. 사용자가 폴더를 선택합니다. 선택하지 않으면 <repo-부모>/video/ 같은 형제 폴더를 사용하세요. macOS에서는 /video와 같은 디스크 루트 경로가 종종 읽기 전용입니다.
video/
├── <name>-walkthrough.mp4 # 전체 비디오: 챕터 + mov_text 자막 트랙
├── <name>-walkthrough.srt # 동일한 내레이션, 대본으로도 사용 가능
├── chapters/NN-slug.mp4 # 챕터당 하나의 파일
├── README.md # 시작 시간이 있는 챕터 인덱스, 재녹화 방법
├── src/ # engine.py, make_readme.py, script.py (+ 도우미)
├── work/ # 저장소의 임시 클론: 모든 명령어가 여기서 실행됨
└── build/ # 중간 파일 (세그먼트별 음성, 프레임, 클립)
사용자의 작업 복사본에서 데모 명령어를 실행하지 마세요. work/로 클론하세요(git clone <repo> work/<name>). 비디오가 의도적으로 문제를 일으키고(잘못된 매니페스트, 주입된 오류) git checkout . && git clean -fd로 초기화할 수 있습니다. 사용자의 체크아웃에 커밋되지 않은 변경 사항이 있으면 언급하고 건드리지 마세요.
단계 1: 도구 확인 및 누락된 항목 사용자에게 알리기
which vhs ffmpeg ffprobe jq; python3 -c "import PIL; print(PIL.__version__)"; say -v '?' | head -3
누락된 항목이 있으면 설치 이유와 함께 사용자에게 알린 후, 설치하세요(brew install vhs ffmpeg jq). Pillow의 경우 시스템 Python을 건드리지 마세요. 대신 uv를 통해 엔진을 실행하세요: uv run --no-project --with pillow python engine.py .... 셸 함수로 감싸세요(py() { uv run --no-project --with pillow python "$@"; }). 명령어를 담은 변수는 하나로 확장되지 않기 때문입니다. 저장소에 필요한 다른 것들(예: Docker 실행 중, 시뮬레이터 스택, 자격 증명)도 마찬가지입니다. 사용자에게 요청하고, 비밀을 절대 발명하지 마세요. 프리미엄 음성(시스템 설정 → 손쉬운 사용 → 말하기 콘텐츠, 예: "Ava (Premium)")이 기본 Samantha보다 훨씬 좋습니다. 제공하되, 필수로 요구하지는 마세요. VOICE=... engine.py --force로 나중에 음성을 다시 변경할 수 있습니다.
단계 2: 내레이션을 한 줄도 작성하기 전에 저장소를 이해하고 테스트하기
README, 문서 또는 ADR, CLI 진입점(모든 하위 명령어의 --help), 테스트 마커, Makefile 및 CI 구성을 읽으세요. 사용자가 실행할 수 있는 모든 기능의 인벤토리를 만드세요: 각 CLI 하위 명령어, 각 테스트 스위트, 각 통합, 코드가 방어하는 각 실패 모드.
그런 다음 work/에서 모두 실행하고, 다음을 기록하세요:
- 각 기능을 잘 보여주는 정확한 명령어와 짧은 출력(
jq,head,tail,cut -c1-160으로 파이프) - 실패하는 것과 그것이 실제 버그인지 아니면 단지 환경 문제인지(잘못된 기본 경로, 누락된 환경 변수). 환경 문제는 클론 내에서 또는 환경 변수로 수정하고, 그 수정을 비디오에서 볼 수 있게 만드세요. 팀도 같은 문제를 겪을 것이기 때문입니다.
- 각 안전 규칙을 의도적으로 위반하는 방법(픽스처, 복사본에
sed). 비디오가 규칙이 작동하는 것을 보여줄 수 있도록.
이 노트는 발견 사항 챕터가 됩니다. 번호가 매겨진 구체적인 항목 목록으로 유지하세요.
단계 3: 챕터 계획하기
폴더 목록이 아닌 시스템 자체의 파이프라인을 따르세요. 잘 작동했던 형태:
| # | 챕터 | 내용 |
|---|---|---|
| 00 | 환영 | 제목 카드, "무엇을 볼 것인지" 슬라이드 |
| 01 | 큰 그림 | 한 문장 목적, 상자와 화살표로 된 파이프라인, 저장소 레이아웃 터미널 장면 |
| 02 | 설정 | 설치, 목적별로 그룹화된 CLI, 빠른 테스트 스위트 |
| … | 파이프라인 단계별 챕터 | 실제 명령어, 규칙당 "의도적으로 깨뜨리기" 장면 |
| … | 라이브 / 통합 | 실제 백엔드 서비스, 엔드 투 엔드 |
| N-1 | 계약 / 인수인계 | 다른 팀이 의존하는 것 |
| N | 발견 사항 및 다음 단계 | 번호가 매겨진 발견 사항 목록, 그리고 다음에 할 일 |
챕터당 13분, 총 1525분을 목표로 하세요. 챕터는 하나의 아이디어입니다. 세그먼트는 하나의 화면과 하나의 내레이션입니다. 녹화 전에 이 개요(챕터 제목과 각각 한 줄)를 사용자에게 보여주세요.
단계 4: src/script.py 작성하기
번들된 스크립트를 비디오 폴더로 복사하세요:
mkdir -p video/src && cp <skill-dir>/scripts/{engine.py,make_readme.py,agent.jq} video/src/
cp <skill-dir>/scripts/script_template.py video/src/script.py
script.py는 모든 단어와 모든 명령어를 담고 있습니다. engine.py는 이를 비디오로 변환합니다. 전체 세그먼트 스키마, 슬라이드 레이아웃 및 내레이션 스타일에 대해서는 references/script-format.md를 읽으세요. scripts/script_template.py는 각 세그먼트 유형을 작동하는 예제와 함께 보여줍니다. 동일한 형태로 나머지 챕터를 만드세요(단계 3이 챕터 개요를 제공합니다).
가장 중요한 내레이션 규칙:
- 귀로 듣기에 적합하게 작성하세요: 짧은 문장, 마크다운 없음, 음성이 잘못 발음하는 약어는 철자로 표기하세요(
"M C P","C L I"). 또는script.py의SPOKEN에 추가하세요. - 시청자가 무엇을 볼지 말하세요("스킬을 보세요: 0개"). 음성과 화면이 일치해야 하므로, 명령어 출력(개수, 속도 계수)을 변경하면 문장도 수정하세요.
- 자막(터미널 장면의 하단 막대)은 요점을 한 줄로 나타내며,
code는 백틱으로 표시합니다.
단계 5: 드라이런 후 녹화
cd video/src # `py` = Python with Pillow (단계 1 참고)
py engine.py --dry # 모든 터미널 명령어를 일반 bash로 실행하고 출력을 출력합니다. 비디오 없음
py engine.py --dry --only 04 # 한 챕터
py engine.py --only 04 # 한 챕터 녹화 (빠른 피드백)
py engine.py # 누락되거나 변경된 모든 것을 처리한 후 전체 비디오 조합
py engine.py --only 07 --reuse-terms # VHS 클립 유지, 음성과 프레임만 다시 생성 (내레이션 수정)
py make_readme.py # 챕터 인덱스가 있는 README.md 작성
항상 먼저 드라이런하세요. 한 시간 대신 몇 분이면 되고, 오류가 나거나, 멈추거나, 너무 많이 출력하는 모든 명령어를 잡아냅니다. 전체 빌드 전에 한 챕터를 먼저 녹화하고 프레임을 확인하세요:
ffmpeg -v error -ss 20 -i chapters/04-*.mp4 -frames:v 1 build/check.png # PNG를 읽으세요
전체 빌드는 시간이 오래 걸립니다(21분 비디오의 경우 약 40분). 백그라운드에서 실행하고 완료 알림을 기다리세요. 폴링하지 마세요. 챕터는 스크립트의 해시로 캐시되므로, 다시 실행하면 변경된 부분만 다시 빌드됩니다.
단계 6: 확인 및 전달
ffprobe -v error -show_chapters -show_streams -of compact video/<name>-walkthrough.mp4 | head -40
다음을 확인하세요:
- 지속 시간
- 1920×1080 h264, aac, 그리고 mov_text 자막 스트림
- 챕터당 하나의 챕터 마커
- 몇몇 챕터의 샘플 프레임: 텍스트가 상자를 넘치지 않고, 자막이 두 줄 이내인지
그런 다음 사용자에게 MP4, chapters/ 폴더, SRT 및 README의 정확한 경로를 알려주세요. 여는 방법(open video/<name>-walkthrough.mp4; QuickTime 또는 VLC가 챕터 및 자막 메뉴를 표시함)과 발견 사항 목록을 추가하세요. 실행 중인 컨테이너나 서비스가 있으면 언급하고 중지 방법을 알려주세요.
이미 해결된 문제들 (엔진을 편집할 때 염두에 두세요)
- 샌드박스 셸: vhs, Docker,
uv캐시 및say는 종종 명령어 샌드박스 아래에서 실패합니다("Operation not permitted", Docker 소켓 오류). 이러한 명령어는 샌드박스 외부에서 실행해야 합니다.open도 차단되므로, 사용자에게 직접 실행할 명령어를 제공하세요. - VHS 프레임 드롭: 기본 50fps는 긴 장면에서 프레임을 드롭합니다. 엔진은
Set Framerate 15를 사용합니다. - VHS
Output은 파일 이름만 있어야 합니다.cwd를 출력 폴더로 설정하여vhs를 실행하세요. - VHS 문자열에는 이스케이프가 없습니다.
json.dumps인용은 PS1 이스케이프 시퀀스를 깨뜨립니다. 엔진에서q()를 사용하세요. 이 함수는 텍스트에 포함되지 않은",', 또는`구분자를 선택합니다. Wait가 프롬프트와 일치하지 않으면 중단됩니다. 엔진은$로 끝나는 PS1을 설정하고WaitPattern /[>$]$/를 사용합니다.$또는>로 끝나는 마지막 줄을 출력하는 명령어는 wait를 조기에 종료할 수 있으므로pause를 추가하세요.- 오래 실행되는 장면 (AI 에이전트, 파이프라인 실행): 세그먼트에
"speedup": True를 설정하세요. 엔진은 클립을 대략 내레이션 길이로 가속화하고 헤더에sped up ×N.N을 찍습니다. 가속화되었다고 말하세요. - 슬라이드의 텍스트 오버플로:
wrap()은 고정 폰트로 코드 스팬을 측정합니다. 상자 본문을 짧게 유지하고, 긴 경로는 두 줄로 나누세요. - 대기 루프:
pgrep -f <pattern>루프는 자기 자신과 일치합니다. 대신 PID나 파일을 기다리세요. - Before-훅 (챕터의
"before": [...])은 상태를 준비합니다: DB 컨테이너 재설정, 파이프라인 트리거, 오류 주입. 실행 취소(재설정, 주입 제거)를 같은 챕터에 넣어, 한 챕터의 재빌드가 플랫폼을 망가뜨리지 않도록 하세요. - 데모에 필요한 비밀은 클론의 git-ignored 파일(예:
dev-vault.env)에 넣으세요. 화면에 값을 절대 표시하지 말고, 커밋하지 마세요.
AI 에이전트 작업 보여주기 (선택 사항)
저장소가 에이전트를 빌드하거나 구성하는 경우, 가장 강력한 장면은 에이전트가 실제로 주입된 실패를 진단하는 것입니다. 헤드리스로 실행하고 stream-json 출력을 사용하며, 번들된 agent.jq(도구 호출당 한 줄, 그다음 답변)로 스트림을 포맷하세요:
claude -p "<질문>" --output-format stream-json --verbose | jq -rj -f /path/to/video/src/agent.jq
해당 세그먼트를 "speedup": True로 표시하고, 같은 챕터에서 오류를 재설정하세요.