Communitygithub.com

thativanng/reels-maker

코드로 영화, 릴(Reel), 애니메이션을 제작하고 렌더링합니다. 하나의 HTML 페이지가 window.seek(t)로 모든 프레임을 주문 제작하며, 헤드리스 브라우저가 2배 해상도로 각 프레임을 렌더링하여 MP4(사운드 포함)로 출력합니다.

reels-maker란 무엇인가요?

film-engine(thativanng/reels-maker)은 코드를 기반으로 영화, 릴, 애니메이션을 제작하고 렌더링하는 AI 에이전트 스킬입니다. 핵심 아이디어는 하나의 HTML 페이지가 `window.seek(t)` 함수를 통해 시간 `t`에 해당하는 프레임을 항상 일관되게 그리도록 하고, 헤드리스 브라우저가 30fps로 각 프레임을 2배 해상도로 캡처하여 ffmpeg로 MP4 비디오를 만드는 것입니다. 클로드 코드, 커서, 코덱스와 같은 AI 코딩 에이전트에서 사용할 수 있으며, '비디오를 만들어 줘', '이 페이지를 동영상으로 바꿔줘' 같은 요청에 응답합니다. 9:16, 4:5, 1:1, 16:9 등 다양한 종횡비를 지원하고, 스타일 팩(예: voxel-walk)이나 starter.html 템플릿을 기반으로 제작합니다. 모든 프레임이 결정론적이어서 재렌더링 시 결과가 일치하며(약간의 GPU 노이즈 제외), film-audit 스킬과 연동되어 완성 전에 품질 검사를 통과해야 합니다. 오디오는 Python 스크립트로 큐를 생성하고, 최종 믹싱 시 -14 LUFS 음량 표준, 리미터, 색상 태그 없는 H.264 인코딩을 적용합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/thativanng/reels-maker/tree/HEAD/skills/film-engine

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

film-engine: 코드로 그리는 영화, 한 프레임씩

키트 위치: 이 스킬의 모든 명령은 reels-maker 폴더(github.com/thativanng/reels-maker 의 클론으로, template/ 와 tools/ 를 포함)에서 실행하세요. 프로젝트에 이 폴더가 없으면 먼저 해당 레포지토리의 SETUP.md를 따라 설정하세요.

한 문단으로 보는 아이디어

여기서 영화는 하나의 HTML 페이지이며, 규칙은 단 하나입니다: window.seek(t) 는 시간 t에 해당하는 프레임을 항상 정확히 그려야 하며, t 외에는 아무것도 사용하지 않습니다. 화면 속 어떤 것도 실제 시계를 읽어서는 안 됩니다. 그런 다음 렌더러가 30fps로 t를 진행하며 각 프레임을 2배 해상도로 스크린샷하고 ffmpeg로 전달합니다. 페이지가 결정론적이기 때문에, 재렌더링 시 결과가 일치하며(평균적으로 약간의 레벨 차이 이내, GPU 노이즈로 인해 단일 픽셀이 최대 60레벨까지 변동 가능), 17.3초에서의 정지 이미지는 비디오에서 보여줄 프레임과 동일하며, 모든 검사(film-audit)는 영화를 재생하지 않고도 어떤 순간이든 확인할 수 있습니다.

과정 (단계를 건너뛰지 마세요)

  1. 먼저 브리핑과 룩을 확정하세요. reel-intake는 서명된 브리핑과 스토리보드(형식, 길이, 사운드, 절대 등장하지 않아야 할 것)로 마무리됩니다. reel-style은 선택된 룩으로 마무리됩니다. 이 스킬의 빌드 단계를 열기 전에 두 가지가 모두 준비되어 있어야 합니다.
  2. 스토리보드. reel-intake가 작성합니다 (시간 · 화면에 표시될 텍스트 · 사운드 및 자막 · 이유; references/brief.md), 그리고 빌드 전에 사람이 서명합니다. 배너가 있는 스타일은 배너 열을 추가합니다.
  3. 테스트 스트립. 선택된 룩으로 처음 약 10초를 빌드하고(걷기 스타일 영화는 한 챕터를 보여주기 위해 15~30초가 필요할 수 있음), 정지 이미지를 캡처하여 승인을 받으세요. 서명되지 않은 룩으로 전체 빌드하는 것은 낭비입니다.
  4. 전체 영화를 빌드하세요 (스타일 팩이 장면을 빌드하는 방법을 알려줍니다).
  5. 게이트 (film-audit): 40fps 충돌 검사, 픽셀 프로브, 그리고 독립 감사자. 이 과정 전까지는 아무것도 사람에게 보여주지 마세요.
  6. 렌더링: node tools/render.mjs --page reels/<name>/page.html --out reels/<name>/out/film-silent.mp4 (2배 프레임, lanczos로 축소, 컬러 태그 없음).
  7. 오디오: python3 template/audio.py out/film.wav (영화와 동일한 시계를 따르는 큐 목록).
  8. 마무리: zsh tools/mux.sh out/film-silent.mp4 out/film.wav out/film.mp4. 이 명령은 −14 LUFS, 리미터, 태그 없는 H.264 파일 및 영화와 같은 비율의 전화 미리보기(짧은 변 720px)를 생성합니다.
  9. 커버: node tools/cover.mjs --page reels/<name>/page.html --out reels/<name>/out/cover.jpg. 커버 모드가 있는 페이지(스타터의 ?cover, 설정의 cover)는 디자인된 정지 이미지를 그리고, 다른 페이지는 T= 시점의 프레임을 제공합니다. 영화 자체 비율로 저장되며 2MB 미만으로 유지되고, 9:16 영화의 경우 중앙 3:4 크롭(인스타그램 그리드용, 보고됨)도 함께 제공됩니다. LinkedIn은 게시 시에만 커버를 설정할 수 있습니다: 게시 후에는 게시글 텍스트만 수정 가능합니다(LinkedIn 도움말, "공유된 게시물 편집", https://www.linkedin.com/help/linkedin/answer/a522811). LinkedIn의 썸네일 사양(JPG 또는 PNG, 비디오와 동일한 비율, 최대 2MB)은 검색 요약에 인용된 LinkedIn 도움말에서 가져온 것입니다. 페이지 자체는 로드되지 않으므로, 확인되지 않은 정보로 취급하세요.
  10. 먼저 전화 미리보기를 보내고, 그다음 전체 파일과 커버를 보내세요.

페이지 규약

  • window.seek(T): 프레임 T를 그립니다. 이것이 애니메이션을 처리하는 유일한 곳입니다.
  • window.ready: 폰트, 텍스처 및 첫 번째 프레임이 로드된 후 해결되는 프로미스입니다.
  • window.DUR: 영화의 길이(초)입니다.
  • window.FILM = { w, h, format, safe }: 프레임 크기와 안전 영역(픽셀 단위). 모든 도구가 이 값을 기준으로 창 크기를 조정하므로, 페이지가 자체 포맷을 소유합니다.
  • 선택 사항: window.cover() 는 프레임 대신 커버를 그리고, FILM.coverAt 은 커버가 해당하는 시간을 지정합니다 (tools/cover.mjs는 둘 다 사용합니다; 없으면 T= 시점의 프레임을 캡처합니다).
  • window.collide(T) 및 window._dbg: film-audit을 위한 훅 (해당 스킬 참조).
  • 도구들은 키트 폴더를 http로 서빙합니다 (ES 모듈은 file:// 에서 로드되지 않음). 브라우저에서 페이지를 실시간으로 보려면 npm run serve 를 실행하고 http://127.0.0.1:8765/template/starter.html 을 여세요.

포맷, 스타터 및 다른 언어

  • template/formats.json 은 네 가지 크기(9:16 1080×1920 · 4:5 1080×1350 · 1:1 1080×1080 · 16:9 1920×1080), 플랫폼→포맷 매핑, 각 플랫폼의 안전 영역과 출처를 포함합니다. 브리핑의 포맷 라인이 이 중에서 선택합니다.
  • 모든 릴은 자체 폴더 reels/<name>/ 에 저장됩니다 (gitignore됨): 브리핑, 스토리보드, page.html (스타터 또는 film.html의 복사본), reel.json 또는 career.json, out/. 페이지는 키트 루트에서 폰트와 formats.json을 로드하므로, 복사본이 거기서 작동합니다. 도구를 해당 위치로 지정하세요: PAGE=reels/<name>/page.html.
  • template/starter.html + template/reel.json 은 voxel walk를 제외한 모든 룩의 골격입니다. 단어와 타이밍은 설정 파일에 있으며, ?fmt= 또는 설정에 따라 크기가 조정되고, 모든 단어는 플랫폼의 안전 영역 내에 유지됩니다. ?guides 는 체크 전용으로 덮힌 영역을 빨간색으로 표시합니다. 절대 켠 상태로 렌더링하지 마세요. 이것은 골격일 뿐, 룩이 아닙니다: reel-style이 토큰과 레이아웃을 다시 작성합니다.
  • template/film.html (복셀 템플릿) 은 4:5 전용이며, 안전 영역(safe 는 0)을 사용하지 않습니다: 배너와 자막이 의도적으로 가장자리 근처에 위치하므로 safe 프로브는 항상 통과하고 감사자의 눈이 검사 역할을 합니다. 카메라는 4:5에 맞춰져 있습니다. 다른 비율을 사용하려면 카메라를 다시 설정하고 모든 게이트를 다시 실행해야 합니다.
  • 중국어, 일본어, 한국어: 스타터는 렌더링 시 Google Fonts에서 Noto Sans TC를 로드하고(설정에서 사용하는 문자만), CJK 텍스트를 라틴 문자 크기의 약 0.72배로 렌더링합니다(CJK 문자는 전체 em 너비). 줄바꿈이 필요한 곳에 \n 을 작성하세요: 중국어는 어떤 두 문자 사이에서도 줄바꿈이 가능하므로, 긴 줄에는 선택한 줄바꿈이 필요합니다. template/reel.zh.json 은 작업 예제입니다. 다른 스크립트는 스택에 자체 폰트가 필요합니다.

시계 및 타이밍

  • 하나의 영화 시계가 장면, 카메라, 배너, 자막 및 사운드를 구동합니다. 나중에 모든 타이밍을 다시 조정하지 않고 비트를 삽입하려면 리맵을 사용하세요: 장면 시계는 삽입 지점에서 멈추고 오버레이는 실제 시계를 유지합니다:
    const INS = [[24.0, 5.0, 'detail']];   // 장면 시간 24.0에서 5초 분량의 'detail' 비트를 재생
    function remap(T) { let sh = 0; for (const [a, len, id] of INS) { if (T < a + sh) return { t: T - sh, ins: null }; if (T < a + sh + len) return { t: a, ins: id, u: T - sh - a, len }; sh += len; } return { t: T - sh, ins: null }; }
    
    오디오 스크립트도 동일한 테이블이 필요합니다: 장면 시간에 삽입된 길이를 더하는 RT(t) 를 작성하고, 모든 큐를 RT(t) 에 배치하세요. 그렇지 않으면 삽입 이후의 모든 큐가 밀려납니다. (템플릿에는 삽입이 없으므로 audio.py에도 필요하지 않습니다.)
  • 이징: 카메라 움직임에는 eio, 물체가 들어올 때는 eo, 걷기 및 운전에는 trap (사다리꼴 속도)을 사용하여 움직이는 물체가 끝에서 "딱" 끊기지 않도록 하세요.
  • 카메라 키는 절대 위치 A(pos, target) 또는 캐릭터의 바닥 지점을 기준으로 한 F(offset, targetOffset) 입니다. 키 사이를 eio로 블렌딩하세요. 중요한 비트에서는 고정하고, 항상 움직이는 샷은 불안정해 보입니다.

오버레이 (DOM에, 캔버스 위에)

  • 배너: 연도, 회사, 역할 필(role pill), 그리고 현재 연도에 점이 숨쉬는 타임라인. 배너는 새 장면이 화면에 나타날 때 변경됩니다(세트가 올라오고, 의상이 바뀌고, 주인공이 도착했을 때). 코드가 장면을 구축하기 시작할 때가 아닙니다. 매 변경 시점 전후 ±1초에서 프레임 시트로 확인하세요.
  • 자막: 비트당 한 줄의 스토리, 핵심 구문은 굵은 악센트. text-wrap: balance를 사용하세요. 독자에게 초당 약 3단어를 제공하고, 빠른 카메라 움직임이 그 뒤의 피사체를 드러내기 전에 자막을 페이드 아웃하세요.
  • 말풍선: 캐릭터를 따라다니며, 머리 포인트를 투영하고 말풍선을 프레임 안쪽 최소 24px 이상 유지하세요.
  • 엔드 카드: 이름, 태그라인 하나, 잘하는 것, 인용구 하나. 뒤의 장면은 흐려집니다.

오디오

  • 큐는 영화 시계에 맞춰, 해당 순간 옆에 기록됩니다(걸음 수당 스텝 소리, 사물이 나타날 때 차임, 착지할 때 쿵 소리).
  • 전환에 윙(whoosh) 소리를 사용하지 마세요. 싸구려 느낌입니다. 대신 차임, 틱, 부드러운 충격음을 사용하세요.
  • template/audio.py 의 기본 배경음은 사인파로 생성되므로 어디서든 무료로 사용할 수 있습니다. 누군가 AI 생성 트랙을 가져온 경우 라이선스를 확인하세요: 일부 모델의 가중치는 비상업적 용도만 허용합니다.
  • 음량: −14 LUFS로 2패스 loudnorm (측정 후 선형 적용), 그 다음 리미터. 1패스는 초과할 수 있습니다.

우리가 며칠을 소비하게 만든 렌더링 사실들 (자세한 내용은 references/gotchas.md)

  • 2배 해상도로 렌더링하고 축소하세요. EffectComposer가 캔버스 안티앨리어싱을 제거하므로 1x 렌더링은 모든 곳에서 계단 현상이 발생합니다.
  • MP4에 색상 태그를 넣지 마세요. JPEG 파이프가 전체 범위로 태그하여 일부 플레이어에서 색상이 변할 수 있습니다. 필터에 setparams=...=unknown 을 사용하세요.
  • 하나의 평면에 있는 두 개의 얼굴이 깜빡입니다 (z-파이팅). 앞쪽 얼굴에 깊이 오프셋을 주세요.
  • 폰트는 캔버스 텍스트를 그리기 전에 로드되어야 합니다 (document.fonts.load). 그렇지 않으면 조용히 기본 폰트로 대체됩니다.
  • 헤드리스 Chromium에서 GPU를 켜세요 (macOS에서는 --use-angle=metal). GPU가 없으면 렌더링 속도가 약 10배 느려집니다.

모든 단계에서 프롬프트 없이 작업하기

사용자는 키트의 허용 규칙에 한 번 동의했습니다 (SETUP.md 4단계). 그 규칙 내에서 작업하세요. 그렇지 않으면 매번 승인을 요청받게 됩니다:

  • 파일 쓰기 및 변경은 Write 및 Edit 도구를 사용하세요: 페이지, reel.json, 브리핑, 스토리보드, AUDIT.md. Python이나 쉘 스크립트, heredoc, sed -i로 생성하지 마세요. 각각은 승인 프롬프트입니다.
  • 측정은 키트의 도구를 사용하세요 (stills, probe, sheet, collide, render, cover). 일회성 python3 -c 스니펫을 사용하지 마세요.
  • mkdir, 루프, 체인은 필요 없습니다: 모든 도구는 자체 출력 폴더를 생성하고, 한 번의 호출로 시간 목록을 받습니다 (stills.mjs … 1.5,6,12).
  • 릴의 자체 스크립트 (사운드 스크립트, 헬퍼)는 reels/<name>/ 에 저장되며 python3 reels/<name>/audio.py 또는 node reels/<name>/x.mjs 로 실행되며, 이는 규칙에 포함됩니다.

명령어

각 도구를 하나의 평문 명령어로 실행하세요 (플래그, VAR=… 앞에 붙이지 않음, 루프 없음, && 체인 없음). 그러면 사용자의 허용 규칙(node tools/*)이 이를 포함하여 모든 단계를 승인하라고 요구하지 않습니다. 환경 변수는 여전히 스크립트에서 작동합니다.

npm run doctor                                  # 이 머신을 먼저 확인
npm run demo                                    # 12초 데모: out/demo/
node tools/stills.mjs "2,8.5,15"                # 2배 스틸 → out/stills (복셀 템플릿)
node tools/stills.mjs --page template/starter.html --format 16:9 1.6        # 다른 비율의 스타터
node tools/stills.mjs --page template/starter.html --cfg reel.zh.json 1.6   # 다른 설정 (여기서는 중국어)
node tools/stills.mjs --dsf 1 --out out/chk 2,8.5                           # 시트용 빠른 1x 프레임
python3 tools/sheet.py out/chk/sheet.jpg 6 300 out/chk/t*.jpg
node tools/render.mjs --page reels/<name>/page.html --out reels/<name>/out/film-silent.mp4
python3 template/audio.py out/film.wav
zsh tools/mux.sh out/film-silent.mp4 out/film.wav out/film.mp4

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

thativanng/reels-maker

The gates every code-rendered film passes before anyone sees it. A 40 fps collision pass (no mover touches a solid or another mover), pixel probes (nothing sits over or behind a face, a head, a subtitle or the frame edge), then an independent auditor (a fresh agent) who reads frame sheets at ≥2 fps and signs off. The builder never signs off their own film. Use it before sending ANY render, after every fix round, and whenever someone says "check the film", "audit this", "is it ready", or "why does this frame look wrong".

thativanng/reels-maker

The interview before any video is built. It reads what the person already gave (source text, CV, links, brand files), then asks the rest in a few short rounds of numbered questions with a recommended answer marked, always including the format (platform, reel or video, ratio, layout, length, sound). It ends in a one-screen brief that splits "you said" from "I assumed", plus a storyboard, and builds nothing until the person says yes. Use it whenever someone asks for a reel, a video, an explainer, a career film, an animation or a "make a video about X", before film-engine or any style pack, and again when a request changes its purpose, platform or audience mid-way.

thativanng/reels-maker

Picks the look of a reel or film before it is built. It shows three genuinely different looks as stills of the same opening frame with the same words, so the person judges the look and not the content. It keeps a log of every look ever shown, so no look comes back unless asked for, and it locks one look on purpose for a series. Use it after reel-intake's brief is signed and before any test strip, whenever someone says "what should it look like", "give me options", "make it look different from last time", "it looks cheap", or starts a new reel or a new series.

thativanng/reels-maker

The voxel career-film style. A blocky 3D version of the person walks, without ever vanishing, through one scene per role. Their outfit changes as they walk, each scene rises out of the floor ahead of them, and a dark banner tracks year, company and role. Use it when someone wants their career, a journey or a "how I got here" told as a short 3D film for LinkedIn or a portfolio, says "make my career film", "turn my CV into a video", "voxel film", or wants a new chapter added to an existing one. It runs on film-engine (render, audio, finish) and must pass film-audit before anything is sent.

관련 스킬