폰 포털 릴스(Phone-portal reel)
개요
고정된 삼각대에서 촬영한 하나의 프레임으로 구성된 9초 9:16 제품 광고입니다. 세 개의 비트로 나뉩니다:
- 포털 드롭 (약 4.3초). 한 손이 폰을 잡고 있습니다. 다른 손이 폰을 스와이프하면, 스와이프할 때마다 제품 하나씩 화면 밖으로 떨어져 아래 선반 위에 비트에 맞춰 착지합니다. 히어로 제품은 마지막에, 음악이 멈춘 후 떨어집니다.
- 스톱모션 셔플 (약 2.7초). 하드 컷으로 손과 폰이 사라집니다. 제품들이 16분음표당 한 프레임씩, 4박자에 맞춰 전체 라인을 회전합니다.
- 로고 유지 (약 2초). 워드마크가 6~8프레임에 걸쳐 페이드 인되어 정지합니다. 음악만 재생되고 음성은 없습니다.
카메라 영상은 없습니다. 하나의 생성된 사진을 레이어(배경, 폰과 잡은 손, 스와이프하는 손)로 나누어 코드로 애니메이션 처리합니다. 제품은 실제 3D 모델이며, 폰 내부와 방 안에서 동일한 카메라로 렌더링되어 하나의 오브젝트로 유리면을 넘나듭니다.
기준: 실제 촬영처럼 보여야 합니다. 우리가 겪은 모든 실패는 누군가가 단일 프레임에서 발견한 연속성 오류였습니다. 최종 파일을 전체 크기로, 모든 접촉 순간에 확인하세요.
필요 사항
| 필요 항목 | 용도 |
|---|---|
OPENAI_API_KEY | 플레이트 및 마스터 생성용 gpt-image-2, 사진을 유지해야 하는 편집용 input_fidelity: high의 gpt-image-1.5 |
ELEVENLABS_API_KEY | 배경 음악(music_v2_5) 및 효과음 |
HyperFrames CLI (npx hyperframes), three.js r169 | 프레임 엔진 및 렌더링 |
ffmpeg; Python 3 with numpy opencv-python-headless pillow openai | 스크립트 실행 |
스크립트는 환경 변수에서 키를 읽거나, 작업 폴더 또는 상위 폴더의 .env 파일에서 읽습니다. 키를 절대 출력하지 않습니다. 각 실행 비용(OpenAI 달러(스크립트가 추정치 기록), ElevenLabs 크레딧)을 보고하세요.
누군가 삼각대에서 실제 손으로 폰을 스와이프하는 영상을 촬영할 수 있다면, 그 영상을 손 부분에 사용하세요. 이것이 가짜로 만들기 가장 어려운 부분입니다.
게이트: 각 단계에서 OK를 받아야 진행
- 브리프 및 비트 시트. 브랜드, 4~6개 제품(히어로 제품은 마지막, 배경과 보색 계열), 배경, 비트가 프레임의 정수 배가 되는 템포. 30fps에서 112.5BPM은 16프레임, 120BPM은 15프레임, 90BPM은 20프레임. 모든 착지를 음악 그리드(비트 또는 반비트)에 맞추고, 그 사이에 두지 마세요. 드롭 횟수는
references/build.md섹션 1을 참조하세요. - 룩. 플레이트, 마스터(손과 폰), 맞춤 카메라로 3D 제품의 첫 번째 렌더링, 엔드 카드를 3가지 폰트 조합으로 설정한 전체 시트.
- 모션 테스트. 한 번의 스와이프와 한 번의 드롭을 최종 품질로 렌더링하고 프레임별로 확인합니다. 대부분의 실패가 여기서 발견됩니다.
- **빌드, 사운드, 최종.
빌드
references/build.md를 따르세요. 모든 단계와 작동했던 숫자가 나와 있습니다. 순서대로:
- 플레이트(빈 배경)를 생성하고, 마스터(플레이트에 두 손과 빈 폰을 추가한 한 편집본)를 생성합니다. 마스터가 프레임입니다. 모든 클린 플레이트는 마스터에서 만들어집니다.
- 마스터에서 레이어를 자르고, 화면 모서리, 화면 하단 가장자리, 손가락 끝, 손목을 측정합니다.
- 3D 카메라를 선반 가장자리에 맞춥니다.
- 엔진을 빌드합니다.
example/studio/(참조 빌드: 차 브랜드, 5개 상자)를 복사하고 상수를 플레이트에 맞게 다시 측정합니다. 코드만 포함됩니다. 자신의 이미지, 폰트, 라벨 아트, three.js 파일을 가져오세요. 제품이 종이 상자가 아닌 경우(병, 항아리, 캔, 유리 제품 등)build.md의 "기타 제품"을 먼저 읽으세요. - 먼저 음악을 만들고 비트를 측정합니다. 그런 다음 착지를 그리드에 고정하고, 효과음을 추가하고, 믹싱합니다.
- 렌더링 후 아래 검사를 실행합니다.
환상을 깨뜨린 규칙들
| 현상 | 수정 방법 |
|---|---|
| 제품이 몇 프레임 늦게 폰 아래에 나타남 | 유리 양면에서 동일한 3D 오브젝트입니다. 각 스와이프를 착지 프레임에서 역으로 풀어냅니다. 즉, 제품의 최저점이 가장자리에 도달하는 프레임부터 스크롤 속도로 중력에 의해 떨어집니다. |
| 제품이 손 뒤로 떨어짐 | 화면 하단 가장자리 아래에서는 베젤과 손가락 앞에 그립니다. |
| 제품이 폰 아래에 몇 프레임 동안 매달려 있음 | 가장자리에서 중력이 적용됩니다. 페이지 글라이드를 계속 따라가지 않도록 합니다. |
| 스와이프가 사진 슬라이드처럼 보임 | 손목에서 튕기고, 팔뚝은 고정합니다. 손가락 끝이 페이지와 함께 움직이도록 손목 각도를 조정합니다. 두 스와이프가 같지 않아야 합니다. |
| 프레임이 정지 이미지처럼 보임 | 잡고 있는 폰이 1.5~2px 떠다니며 각 누름에 반응합니다. 벽은 절대 움직이지 않습니다. |
| 어두운 선이 폰을 가로질러 움직임 | 피드에 페이지 구분선이 없습니다. 고스팅을 낮게 유지합니다. |
| 손목에서 시계나 장신구가 미끄러짐 | 마스터에서 맨손목을 요청하세요. 들어온 경우, 모두 마스킹하고 scripts/blend-edit.py로 제거하세요. |
| 컷이 디졸브로 변함 | 모든 컷, 스왑, 정지를 전체 프레임에서 결정하고, 셔터 샘플 내부에서는 절대 결정하지 마세요. |
| 라벨이 사본 빗처럼 인쇄됨 | 제품이 떨어지는 동안 48개의 서브프레임을, 그 외에는 10개의 서브프레임을 사용하고, 0.38프레임 셔터를 사용합니다. |
| 생성 편집이 마스크 밖의 요소를 움직임 | 마스크된 편집은 존중되지 않습니다. 편집을 등록한 후 마스크 내부에서만 적용하세요. |
| 쿵 소리가 상자보다 먼저 남 | 각 테이크를 가장 큰 어택 4ms 전으로 자르고, 그 어택에 맞춥니다. |
전체 목록과 원인은 references/lessons.md에 있습니다.
보내기 전 확인
- 최종 파일의 모든 접촉 순간 전체 크기 자르기: 각 스와이프의 첫 프레임, 제품이 가장자리를 통과하는 순간, 각 착지, 컷, 팔이 프레임을 떠나는 순간.
python3 scripts/sync-sheet.py final.mp4 --audio sound/stems/sfx.wav: 각 히트가 지정된 프레임에 정확히 위치하는지 확인.bash scripts/check-final.sh final.mp4 1080x1920: -14 LUFS ±1 및 트루 피크 -1 dBTP 이하.
스크립트
| 스크립트 | 기능 |
|---|---|
scripts/openai-image.py OUT.png "prompt" [--edit IN.png --mask M.png --fidelity high] | 하나의 이미지를 생성하거나 편집하고, 토큰과 예상 비용을 기록합니다. |
scripts/blend-edit.py crop / blend | 한 영역의 마스크 편집을 준비한 후, 결과를 등록하고 마스크 내부에서만 적용합니다. |
scripts/elevenlabs.py spec.json OUTDIR | 스펙에서 음악 배경과 효과음을 생성하고, 캐시하며 사용된 크레딧을 기록합니다. |
scripts/beats.py bed.mp3 | 배경 음악의 템포, 비트 그리드, 첫 번째 다운비트를 찾습니다. |
scripts/sync-sheet.py VIDEO --audio sfx.wav 또는 --cues cues.json | 각 사운드 히트 주변의 5개 프레임을 한 시트에 표시합니다. |
bash scripts/check-final.sh VIDEO [WxH] | 크기, fps, 길이, 음량, 트루 피크를 확인합니다. |
각 스크립트를 --help와 함께 실행하면 옵션을 확인할 수 있습니다. example/README.md는 참조 빌드를 설명합니다.