223 lines
10 KiB
Markdown
223 lines
10 KiB
Markdown
# ADO2 Hookit — 백엔드 개발자 핸드오프
|
|
|
|
> **무엇인가**: 사진 4장 + 5개 인터뷰 답변 → 8초 세로형(9:16) 후킹 숏폼을 자동 생성하는 파이프라인.
|
|
> "Intentional Unreal" 전략 — 실제 사진 기반에 AI 카메라 무브를 입혀 스크롤을 멈추게 하고, 디스클로저로 신뢰를 지킨다.
|
|
> ADO2 플랫폼의 **어텐션 트랙** 엔진 (`engine/higgsfield_shorts`).
|
|
|
|
이 문서는 PoC를 **운영 가능한 서비스**로 넘기기 위한 핸드오프입니다. 현 상태, 실행법, 데이터 계약, 그리고 운영화에 반드시 필요한 작업(❗)을 정리했습니다.
|
|
|
|
---
|
|
|
|
## 1. 아키텍처 — 3 엔진 오케스트레이션
|
|
|
|
```
|
|
인터뷰 답변(5개) + 사진(4장+)
|
|
│
|
|
▼
|
|
① spec_builder.py Claude(claude-opus-4-7) → VideoSpec(JSON) / ScriptResult(JSON)
|
|
│ · 구조화 출력(json_schema) + 프롬프트 캐싱 + 가드레일
|
|
▼
|
|
② higgsfield_client.py Higgsfield CLI shell-out → 완성형 8초 base.mp4 (오디오 포함)
|
|
│ · model=marketing_studio_video, mode=tv_spot, 9:16, 40cr
|
|
▼
|
|
③ remotion_render.py VideoSpec + base.mp4 → props.json → `npx remotion render` → final.mp4
|
|
│ · 자막/타이틀/셀링배지/엔드카드 오버레이 합성
|
|
▼
|
|
/outputs/<job>.mp4 + caption(업로드용 해시태그)
|
|
```
|
|
|
|
핵심 설계 원칙:
|
|
- **각 단계는 순수 함수**(입력 → path/객체 반환). 비동기 잡 큐로 바꾸기 쉬움.
|
|
- **데이터 주도 Remotion**: 컷/자막/타이밍을 props JSON으로 주입 → 콘텐츠가 바뀌어도 컴포넌트 불변.
|
|
- **dry_run 모드**: 크레딧 0으로 데모 클립 반환 (Higgsfield 호출 스킵). 개발·테스트용.
|
|
|
|
---
|
|
|
|
## 2. 디렉터리 구조
|
|
|
|
```
|
|
engine/higgsfield_shorts/
|
|
├── server/ # FastAPI 백엔드 (운영 대상 ★)
|
|
│ ├── app/
|
|
│ │ ├── main.py # 라우트: /api/health, /api/captions, /api/generate
|
|
│ │ ├── schemas.py # Pydantic 데이터 계약 (LLM·Remotion 공유)
|
|
│ │ └── pipeline/
|
|
│ │ ├── spec_builder.py # ① Claude → VideoSpec / ScriptResult
|
|
│ │ ├── higgsfield_client.py # ② Higgsfield CLI 래퍼
|
|
│ │ └── remotion_render.py # ③ Remotion 렌더 래퍼
|
|
│ ├── pyproject.toml # Python deps (fastapi, anthropic, pydantic…)
|
|
│ └── .env.example # ANTHROPIC_API_KEY
|
|
├── remotion/ # Remotion 영상 합성 프로젝트 (Node)
|
|
│ ├── src/
|
|
│ │ ├── Root.tsx # Composition 등록 (MumumShort)
|
|
│ │ ├── MumumShort.tsx # 메인 컴포지션 (props 기반)
|
|
│ │ ├── data/types.ts # ShortProps 타입 (= schemas.py VideoSpec와 1:1)
|
|
│ │ ├── data/mumum.ts # defaultProps (Studio 미리보기용 샘플)
|
|
│ │ └── components/ # HookTitle/Subtitle/SellingBadge/BrandLines/EndCard
|
|
│ ├── public/ # base 영상이 여기로 복사됨 (staticFile 해석)
|
|
│ └── package.json # remotion 4.0.468, react 19
|
|
├── webapp/ # 프론트엔드 (단일 HTML, Vercel 정적 배포)
|
|
│ ├── index.html # React(CDN) 단일 파일 — 4스텝 UI
|
|
│ ├── vercel.json
|
|
│ └── demo/mumum.mp4 # dry_run·데모용 완성 영상
|
|
├── _brief/03_energy-matching.md # 에너지 자동 매칭 결정표 (3 프로파일)
|
|
├── prompts/camera-vocabulary.md # 카메라 어휘 + 키프레임 기법
|
|
├── concepts/ # 5개 영상 컨셉 정의
|
|
└── docs/pipeline-integration.md # ADO2 본체 통합 노트
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 사전 요구사항 (개발 환경)
|
|
|
|
| 항목 | 버전/조건 | 비고 |
|
|
|---|---|---|
|
|
| Python | ≥ 3.12 | `uv` 권장 |
|
|
| Node.js | ≥ 22 | Remotion 4.x 요구 |
|
|
| ffmpeg / ffprobe | 설치 필요 | `remotion_render._probe_frames`가 ffprobe 사용 |
|
|
| Higgsfield CLI | `@higgsfield/cli@^0.1.40` | `higgsfield auth login` 으로 **디바이스 로그인 인증 선행** |
|
|
| ANTHROPIC_API_KEY | 필수 | `server/.env` 에 설정 (Claude 호출) |
|
|
|
|
> ⚠️ Higgsfield는 **API 키가 아니라 CLI 디바이스 로그인**으로 인증합니다(`~/.higgsfield/`).
|
|
> 서버는 `subprocess`로 CLI를 호출하므로, **서버 실행 계정이 로그인되어 있어야** 실제 생성이 동작합니다.
|
|
> 컨테이너/서버리스 환경에서는 이 인증 상태 주입이 별도 과제입니다(§7 참고).
|
|
|
|
---
|
|
|
|
## 4. 로컬 실행
|
|
|
|
```bash
|
|
# 0) 인증 (1회)
|
|
higgsfield auth login
|
|
|
|
# 1) Remotion 의존성 (1회)
|
|
cd remotion && npm install && cd ..
|
|
|
|
# 2) 서버 의존성 + 환경변수
|
|
cd server
|
|
cp .env.example .env # ANTHROPIC_API_KEY 채우기
|
|
uv sync # 또는: pip install -e .
|
|
|
|
# 3) 서버 기동
|
|
uv run uvicorn app.main:app --reload --port 8000
|
|
# → http://localhost:8000/ (웹앱)
|
|
# → http://localhost:8000/api/health
|
|
|
|
# (선택) Remotion 미리보기 스튜디오
|
|
cd ../remotion && npm run studio
|
|
```
|
|
|
|
프론트엔드만 따로 확인하려면 `webapp/`을 정적 서빙 (`python3 -m http.server`). `index.html`의 `API_BASE`를 백엔드 주소로 설정하면 실 호출, 비우면 데모 모드.
|
|
|
|
---
|
|
|
|
## 5. API 계약
|
|
|
|
### `GET /api/health`
|
|
```json
|
|
{ "ok": true }
|
|
```
|
|
|
|
### `POST /api/captions` — 자막 스크립트 4블록 생성 (JSON)
|
|
요청 (`GenerateRequest`):
|
|
```json
|
|
{
|
|
"kind": "place", // "place" | "product" | "message"
|
|
"biz_name": "Stay, 머뭄",
|
|
"addr": "전북 군산 …", // optional
|
|
"price": "1박 18만원", // optional
|
|
"selling": "프라이빗 독채, 넓은 정원, 깊은 욕조"
|
|
}
|
|
```
|
|
응답 (`ScriptResult`):
|
|
```json
|
|
{ "intro": "...", "selling": "...", "story": "...", "cta": "..." }
|
|
```
|
|
|
|
### `POST /api/generate` — 최종 영상 생성 (multipart/form-data)
|
|
필드: `photos[]`(파일, **4장 이상**), `kind`, `biz_name`, `selling`, `addr?`, `price?`, `dry_run?(bool)`
|
|
응답 (`GenerateResult`):
|
|
```json
|
|
{
|
|
"video_url": "/outputs/<job>.mp4",
|
|
"caption": "업로드용 캡션 + 해시태그",
|
|
"profile": "Still Cinema",
|
|
"cost_credits": 40.0,
|
|
"job_id": "ab12cd34"
|
|
}
|
|
```
|
|
|
|
데이터 계약 정의: `server/app/schemas.py` (VideoSpec / ScriptResult / GenerateRequest / GenerateResult).
|
|
Remotion 측 동일 계약: `remotion/src/data/types.ts` — **두 파일은 1:1로 동기화 유지 필수**.
|
|
|
|
---
|
|
|
|
## 6. 가드레일 (반드시 유지 — 비즈니스 규칙)
|
|
|
|
`spec_builder.py`의 시스템 프롬프트에 인코딩됨. 프롬프트 수정 시 절대 훼손 금지:
|
|
|
|
1. **식민지 유산·역사정치 용어 금지** — "적산가옥/일제/식민지/근대사" 등 → 미학·경험 어휘로 대체.
|
|
("적산가옥"은 어원상 부정적 함의 → 숙박 카피에서 영구 차단)
|
|
2. **거짓·과장 금지** — 사용자가 주지 않은 거리/효능/수치를 지어내지 않음.
|
|
3. **자막은 흰색 모노크롬** — 카피에 색 지시어 금지. 강조는 굵기·크기·그림자로.
|
|
4. **AI 디스클로저 고정** — 엔드카드에 "실제 사진 기반, AI 카메라 효과를 적용한 영상입니다."
|
|
|
|
---
|
|
|
|
## 7. 운영화(Production) 작업 — ❗ 백엔드 핵심 과제
|
|
|
|
현재는 **동작하는 PoC**입니다. 실 트래픽 전 다음을 처리해야 합니다:
|
|
|
|
1. **❗ 동기 → 비동기 잡 전환**
|
|
`/api/generate`가 Higgsfield 대기(최대 15분) + Remotion 렌더(수십 초)를 **한 요청 안에서 블로킹**함.
|
|
→ `POST /api/generate`는 `job_id` 즉시 반환, `GET /api/jobs/{id}` 폴링 or 웹소켓.
|
|
→ Celery/RQ/ARQ + Redis(이미 ADO2 스택에 있음) 권장.
|
|
|
|
2. **❗ Higgsfield 인증의 서버 이식**
|
|
CLI 디바이스 로그인(`~/.higgsfield/`)이 로컬 사용자에 묶여 있음. 컨테이너에서 동작하려면
|
|
인증 토큰/세션을 시크릿으로 주입하거나, Higgsfield **REST API 직접 호출**로 전환 검토
|
|
(현재는 CLI를 `subprocess`로 감싼 것 — `.env.example`의 `HIGGSFIELD_API_KEY`는 미사용 placeholder).
|
|
|
|
3. **❗ 스토리지** — `server/outputs/`, `remotion/public/`(잡별 base 복사)는 로컬 디스크.
|
|
→ S3(`S3_BUCKET_OUTPUTS`, `ap-northeast-2`) 업로드 + presigned URL 반환. 잡 종료 후 로컬 정리.
|
|
|
|
4. **멀티테넌트 / RLS** — ADO2 본체 규칙(모든 쿼리 `tenant_id` 기반). 잡·결과물에 tenant context 주입.
|
|
|
|
5. **비용 가드레일** — 생성 전 `higgsfield_client.cost()`로 크레딧 선확인, 월 예산(`HF_MONTHLY_BUDGET_USD`) 차단 로직.
|
|
|
|
6. **에러 처리** — 현재 각 단계 실패를 502로 surface. 재시도/부분 실패(예: Higgsfield 성공·Remotion 실패 시 base 보존) 정책 필요.
|
|
|
|
7. **동시성** — Remotion 렌더는 CPU/메모리 집약적. 렌더 워커 풀 분리 권장.
|
|
|
|
8. **CORS** — 현재 `allow_origins=["*"]`. 운영 도메인으로 제한.
|
|
|
|
9. **에너지 자동 매칭 자동화** — 현 PoC는 프로파일을 LLM이 텍스트로 선택. `_brief/03_energy-matching.md`의
|
|
결정표를 코드(`energy_matcher`)로 옮겨 결정론적 프로파일링 → Remotion 트랜지션/리듬 기본값 주입(Phase 2).
|
|
|
|
---
|
|
|
|
## 8. 비용 모델 (참고)
|
|
|
|
- 1 크레딧 ≈ $0.051(세포함) ≈ ₩76 (환율 1500 기준)
|
|
- 영상 1편 = **40cr = 약 ₩3,060** (marketing_studio_video tv_spot)
|
|
- 풀로디드(LLM 호출 포함) ≈ **₩3,160 / 편**
|
|
|
|
---
|
|
|
|
## 9. 배포 현황
|
|
|
|
- **프론트엔드(webapp)**: Vercel 정적 배포 — `https://ado2short.o2osolution.ai` (커스텀 도메인 DNS 연결 진행 중).
|
|
Vercel은 정적 호스팅이므로 **백엔드 미포함** → 데모 모드만 동작. 실 생성은 별도 백엔드 호스트 필요.
|
|
- **백엔드(server)**: 아직 배포처 없음. → §7 운영화 후 컨테이너 배포 대상.
|
|
|
|
---
|
|
|
|
## 10. 다음 액션 (백엔드 개발자 시작점)
|
|
|
|
1. 로컬 실행(§4) → `dry_run=true`로 `/api/generate` 한 번 통과시켜 파이프라인 감 잡기.
|
|
2. §7-1(비동기 잡) + §7-2(Higgsfield 인증 이식)이 **블로커**. 이 둘부터 설계.
|
|
3. `schemas.py` ↔ `remotion/src/data/types.ts` 동기화 규칙 확인 (계약 변경 시 양쪽).
|
|
4. 가드레일(§6)은 제품 신뢰의 핵심 — 프롬프트 리팩터 시 회귀 테스트 추가 권장.
|
|
|
|
문의: 크리에이티브/프롬프트 로직은 `_brief/`·`prompts/`·`concepts/` 참조.
|