63 lines
4.4 KiB
Markdown
63 lines
4.4 KiB
Markdown
# 숏폼 큐 — Opal 연동 작업 큐/결과 저장 설계
|
|
|
|
2026-08-03. 유튜브 URL을 h-lab에 등록하면, 구글 Opal "숏폼 생성기" 앱(무료, Gemini Pro 영상분석)을 실행 엔진으로 삼아 결과를 DB에 구조화 저장하고 조회하는 기능.
|
|
|
|
## 배경·제약
|
|
|
|
- Opal은 외부 API가 없다. 실행은 (A) 클로드가 브라우저 자동화로 대행하거나 (B) 사용자가 수동 실행 후 결과를 붙여넣는다. 두 경로 모두 동일한 저장 API로 수렴한다.
|
|
- Gemini API 직접 호출은 Pro가 유료(2026-04부터 무료 티어 제외)라 배제. 단, 실행 엔진 교체가 쉽도록 h-lab은 "결과 텍스트를 받아 파싱·저장"만 담당한다.
|
|
- Opal 출력 형식(프롬프트 v13.x): 구간(ID 1~5)별로 `N=====` 구분자 + ```json 블록(capcut2 붙여넣기용) + 📌 타이틀 후보 5선 + ⏱️ 컷 길이 검산표.
|
|
|
|
## 구성요소
|
|
|
|
### 1. 백엔드 — `domain/shortform/` (DDD 컨벤션)
|
|
|
|
**엔티티**
|
|
- `ShortformJob` (테이블 `shortform_job`): id, youtubeUrl, videoId(URL에서 추출), title(nullable, 결과 JSON의 title_main 첫 값 또는 null), status(PENDING/DONE/FAILED), rawOutput(TEXT, 파싱 실패 대비 원문 보존), createdAt, completedAt
|
|
- `ShortformClip` (테이블 `shortform_clip`): id, job FK, clipNo(1~5), capcutJson(TEXT), titleCandidates(TEXT), durationTable(TEXT), titleTop/titleMain(파싱값, nullable)
|
|
|
|
**API** (`ApiResponse<T>` 래핑, `/api/shortform/...`, web/ 스타일 경로)
|
|
- `POST /api/shortform/jobs` {youtubeUrl} → 큐 등록(PENDING). 중복 URL 등록 시 기존 작업 반환
|
|
- `GET /api/shortform/jobs` → 목록(최신순)
|
|
- `GET /api/shortform/jobs/{id}` → 상세(클립 포함)
|
|
- `POST /api/shortform/jobs/{id}/result` {rawText} → 파싱·저장, status 갱신
|
|
- `POST /api/shortform/import` {youtubeUrl, rawText} → 등록+결과 저장 한 번에 (수동 실행 후 붙여넣기용)
|
|
- `DELETE /api/shortform/jobs/{id}`
|
|
|
|
**파서** (`ShortformOutputParser`)
|
|
- `N=====` 형태 구분자로 섹션 분리 → 섹션마다 ```json 코드블록, "타이틀 후보" 블록, "검산표" 블록 추출
|
|
- JSON 파싱 성공 시 titleTop/titleMain 추출. 어떤 단계든 실패하면 해당 클립은 원문 조각만 저장하고 job은 DONE 유지(rawOutput이 항상 원본 보존) — 파싱 실패로 데이터를 잃지 않는다
|
|
- 클립이 0개 추출되면 FAILED + rawOutput 보존
|
|
|
|
### 2. 프론트 — `/shortform` 페이지 (Thymeleaf, layout/base)
|
|
|
|
- 사이드바에 "숏폼" 메뉴 추가 (`currentPage=shortform`)
|
|
- 상단: URL 입력 폼(등록) + "결과 붙여넣기" 토글(URL+원문 textarea → import API)
|
|
- 목록: 작업 카드(썸네일 `img.youtube.com/vi/{videoId}/mqdefault.jpg`, 상태 뱃지, 등록시각)
|
|
- 상세(카드 펼침 또는 별도 영역): 클립 1~5 카드 — 타이틀(top/main), 타이틀 후보 5선, 검산표, **capcut2 JSON 복사 버튼**(클립보드 API)
|
|
|
|
### 3. 스킬 — `.claude/skills/shortform-queue/SKILL.md`
|
|
|
|
트리거: `/shortform-queue`, "숏폼 큐 돌려줘" 류 요청.
|
|
절차(오늘 세션에서 검증된 노하우를 명문화):
|
|
1. `GET /api/shortform/jobs`에서 PENDING 목록 조회 (h-lab은 localhost:8088)
|
|
2. 크롬 자동화로 opal.google → 숏폼 생성기 앱(edit URL 고정) 열기
|
|
3. YouTube Video 노드 클릭 → URL 입력 → Apply → Preview의 Start
|
|
4. 완료 폴링(전체 4~5분, Step 3 각 ~90초). 앱 UI는 접근성 트리에 안 잡히므로 스크린샷 + `iframe#opal-app` contentDocument에 JS 주입(shadow DOM 관통)으로 상태 확인
|
|
5. Output 전문 추출(JS, `"cuts"` 포함 최대 텍스트) → `POST /api/shortform/jobs/{id}/result`
|
|
6. 노드 에러 시 1회 재실행, 재실패면 FAILED 보고 후 다음 작업 진행. 큐 소진까지 반복, 요약 보고
|
|
주의사항: Opal 프롬프트 끝 중복 칩 이슈(2026-08-03 해결) 같은 앱 구조 변경 감지 시 사용자에게 보고.
|
|
|
|
## 순서·범위
|
|
|
|
1. 백엔드(엔티티→파서→API) — 파서는 오늘 실행에서 얻은 실제 Output 샘플로 단위 테스트
|
|
2. 프론트 페이지
|
|
3. 스킬 파일
|
|
빌드·커밋은 변경 단위별. 실제 Opal 실행 검증은 스킬 완성 후 사용자 요청 시.
|
|
|
|
## 하지 않는 것 (YAGNI)
|
|
|
|
- Gemini API 직접 호출(비용) — 파서/저장 구조만 호환되게 유지
|
|
- n8n 연동, 스케줄 자동 실행(Opal이 로그인 세션 필요, 무인 실행 불가)
|
|
- capcut2 앱으로의 직접 전송(현행 수동 붙여넣기 유지)
|