feat: 숏폼 큐 스킬 - 기본 모드 1단계로 전환 + 캡컷 에이전트 연동
"숏폼 돌려줘"가 이제 1단계 앱으로 돌아간다. 풀버전은 "풀버전으로 돌려줘"로 명시할 때만 쓴다. 작업 저장이 DONE 되면 캡컷 에이전트(127.0.0.1:8001)의 자동 탭 구간 JSON 방식으로 유튜브 URL과 candidates JSON을 넣고 영상 생성을 시작만 시킨다. 완료를 기다리지 않고 바로 다음 작업의 Opal 실행으로 넘어간다. 서버가 analysis_id별로 독립 처리해 동시 실행이 가능하고, 작업마다 새 탭을 써서 앞 실행의 화면 상태가 덮이지 않게 한다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9c9bc9afdb
commit
be56ff39df
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: shortform-queue
|
name: shortform-queue
|
||||||
description: h-lab 숏폼 큐의 대기 작업을 구글 Opal "숏폼 생성기"로 실행하고 결과를 DB에 저장. "숏폼 큐 돌려줘", "/shortform-queue", "숏폼 돌려줘", "1단계만 돌려줘" 요청 시 사용.
|
description: h-lab 숏폼 큐의 대기 작업을 구글 Opal "숏폼 생성기"로 실행하고, 결과를 DB에 저장한 뒤 캡컷 에이전트(127.0.0.1:8001)로 영상 생성까지 넘긴다. "숏폼 돌려줘", "숏폼 큐 돌려줘", "/shortform-queue", "숏폼 1단계", "풀버전으로 돌려줘" 요청 시 사용.
|
||||||
---
|
---
|
||||||
|
|
||||||
# 숏폼 큐 실행 (Opal 브라우저 대행)
|
# 숏폼 큐 실행 (Opal 브라우저 대행)
|
||||||
@ -13,8 +13,8 @@ h-lab 서버가 꺼져 있으면 먼저 `.\gradlew.bat bootRun`(JAVA_HOME=D:\Dev
|
|||||||
|
|
||||||
| 요청 | 앱 | URL | 출력 형식 |
|
| 요청 | 앱 | URL | 출력 형식 |
|
||||||
|------|-----|-----|----------|
|
|------|-----|-----|----------|
|
||||||
| "숏폼 큐 돌려줘" (기본) | 숏폼 생성기 (풀버전) | `https://opal.google/edit/1w3mThvSpI3_skt4p4OAN3-M6-tnqz0HN` | `N=====` 구간 5개 + cuts JSON |
|
| **"숏폼 돌려줘", "숏폼 큐 돌려줘" (기본)** | 숏폼 생성기 1단계 | `https://opal.google/edit/1Z9zXUiBAjKKOJ08zXxAmE9Neliq86SEw` | `{"candidates":[...]}` JSON 하나 |
|
||||||
| "1단계만 돌려줘", "숏폼 1단계" | 숏폼 생성기 1단계 | `https://opal.google/edit/1Z9zXUiBAjKKOJ08zXxAmE9Neliq86SEw` | `{"candidates":[...]}` JSON 하나 |
|
| "풀버전으로 돌려줘", "전체 돌려줘" | 숏폼 생성기 (풀버전) | `https://opal.google/edit/1w3mThvSpI3_skt4p4OAN3-M6-tnqz0HN` | `N=====` 구간 5개 + cuts JSON |
|
||||||
|
|
||||||
사용자가 Opal URL을 직접 주면 그 URL 우선. 파서(ShortformOutputParser)는 두 형식 모두 인식한다(88179bb) — 어느 모드든 저장하면 DONE + 클립 5개.
|
사용자가 Opal URL을 직접 주면 그 URL 우선. 파서(ShortformOutputParser)는 두 형식 모두 인식한다(88179bb) — 어느 모드든 저장하면 DONE + 클립 5개.
|
||||||
|
|
||||||
@ -27,21 +27,39 @@ h-lab 서버가 꺼져 있으면 먼저 `.\gradlew.bat bootRun`(JAVA_HOME=D:\Dev
|
|||||||
b. Preview 패널의 새로고침(리셋) 아이콘 → **Start** 클릭.
|
b. Preview 패널의 새로고침(리셋) 아이콘 → **Start** 클릭.
|
||||||
c. **완료 폴링** 및 **추출**: 모드별 절차(아래) 참조.
|
c. **완료 폴링** 및 **추출**: 모드별 절차(아래) 참조.
|
||||||
e. **저장**: 브라우저 fetch는 HTTPS→HTTP라 차단됨 — 추출 텍스트를 파일로 옮겨 셸에서 `POST http://localhost:8088/api/shortform/jobs/{id}/result` body `{"rawText": "<Output 원문>", "step1Text": "<Step 1 원문>"}`. PowerShell은 UTF-8 바이트로 전송(`[Text.Encoding]::UTF8.GetBytes`), 응답 한글이 깨져 보이는 건 PS 5.1 표시 문제이므로 검증은 curl로. 응답의 clips가 5개 미만이면 원문과 함께 보고.
|
e. **저장**: 브라우저 fetch는 HTTPS→HTTP라 차단됨 — 추출 텍스트를 파일로 옮겨 셸에서 `POST http://localhost:8088/api/shortform/jobs/{id}/result` body `{"rawText": "<Output 원문>", "step1Text": "<Step 1 원문>"}`. PowerShell은 UTF-8 바이트로 전송(`[Text.Encoding]::UTF8.GetBytes`), 응답 한글이 깨져 보이는 건 PS 5.1 표시 문제이므로 검증은 curl로. 응답의 clips가 5개 미만이면 원문과 함께 보고.
|
||||||
|
f. **capcut 에이전트 넘기기**: 저장이 DONE이면 아래 "capcut 에이전트 연동" 절차로 영상 생성을 **시작만** 하고, 완료를 기다리지 않고 즉시 다음 작업의 Opal 실행으로 넘어간다.
|
||||||
4. **에러 처리**: 특정 Step 노드가 빨간 표시로 실패하면 Preview 리셋 → Start로 1회 재실행. 재실패 시 해당 작업은 건너뛰고 사유를 보고(저장하지 않음 — PENDING 유지). 프롬프트 노드 끝에 중복 YouTube Video 칩이 생겼는지 확인(2026-08-03에 이 원인으로 ID 3이 항상 실패했음).
|
4. **에러 처리**: 특정 Step 노드가 빨간 표시로 실패하면 Preview 리셋 → Start로 1회 재실행. 재실패 시 해당 작업은 건너뛰고 사유를 보고(저장하지 않음 — PENDING 유지). 프롬프트 노드 끝에 중복 YouTube Video 칩이 생겼는지 확인(2026-08-03에 이 원인으로 ID 3이 항상 실패했음).
|
||||||
5. **보고**: 처리한 작업 수, 성공/실패 목록, h-lab `/shortform` 링크로 요약.
|
5. **보고**: 처리한 작업 수, 성공/실패 목록, capcut으로 넘긴 작업과 진행 중인 탭 수, h-lab `/shortform` 링크로 요약.
|
||||||
|
|
||||||
## 풀버전 모드 (기본)
|
## 풀버전 모드
|
||||||
|
|
||||||
- **완료 폴링**: 40~60초 간격 스크린샷. "Thinking... Step N" 진행 표시가 사라지고 Output(1===== 형식)이 렌더링되면 완료. 전체 4~5분 소요(Step 3 다섯 개가 각 ~90초 병렬).
|
- **완료 폴링**: 40~60초 간격 스크린샷. "Thinking... Step N" 진행 표시가 사라지고 Output(1===== 형식)이 렌더링되면 완료. 전체 4~5분 소요(Step 3 다섯 개가 각 ~90초 병렬).
|
||||||
- **Output 추출**: 앱 UI는 접근성 트리에 안 잡힌다. javascript_tool로 `document.getElementById('opal-app').contentDocument`에서 shadow DOM을 재귀 관통해 `"cuts"`를 포함한 **가장 긴** innerText를 찾는다. 텍스트가 크면 window 변수에 저장 후 900자 단위로 나눠 회수한다.
|
- **Output 추출**: 앱 UI는 접근성 트리에 안 잡힌다. javascript_tool로 `document.getElementById('opal-app').contentDocument`에서 shadow DOM을 재귀 관통해 `"cuts"`를 포함한 **가장 긴** innerText를 찾는다. 텍스트가 크면 window 변수에 저장 후 900자 단위로 나눠 회수한다.
|
||||||
- **Step 1 결과 추출**: Console 탭에서 "Step 1: 하이라이트 후보 구간 추출" 항목을 UI 클릭으로 펼친 뒤(lazy 렌더라 JS로 details.open만 하면 내용이 안 붙을 수 있음 — 안 되면 화면 좌표 클릭), shadow DOM 관통으로 `"candidates"`를 포함한 **가장 짧은** innerText(Model Response 부분)를 회수한다.
|
- **Step 1 결과 추출**: Console 탭에서 "Step 1: 하이라이트 후보 구간 추출" 항목을 UI 클릭으로 펼친 뒤(lazy 렌더라 JS로 details.open만 하면 내용이 안 붙을 수 있음 — 안 되면 화면 좌표 클릭), shadow DOM 관통으로 `"candidates"`를 포함한 **가장 짧은** innerText(Model Response 부분)를 회수한다.
|
||||||
|
|
||||||
## 1단계 모드
|
## 1단계 모드 (기본)
|
||||||
|
|
||||||
- 노드 3개뿐: YouTube Video → Step 1(하이라이트 후보 5개) → Generate HTML. 전체 **~1분**이면 끝난다(10초 간격 폴링, "Thinking... Step 1: N%"가 사라지고 candidates JSON이 렌더링되면 완료).
|
- 노드 3개뿐: YouTube Video → Step 1(하이라이트 후보 5개) → Generate HTML. 전체 **~1분**이면 끝난다(10초 간격 폴링, "Thinking... Step 1: N%"가 사라지고 candidates JSON이 렌더링되면 완료).
|
||||||
- **추출**: shadow DOM 관통으로 `"candidates"`를 포함한 **가장 긴** innerText 하나만 회수(~2KB, 통짜 회수 가능). Console 추출 불필요 — Output 자체가 Step 1 결과다.
|
- **추출**: shadow DOM 관통으로 `"candidates"`를 포함한 **가장 긴** innerText 하나만 회수(~2KB, 통짜 회수 가능). Console 추출 불필요 — Output 자체가 Step 1 결과다.
|
||||||
- **저장**: rawText와 step1Text에 **같은 텍스트**를 넣는다.
|
- **저장**: rawText와 step1Text에 **같은 텍스트**를 넣는다.
|
||||||
|
|
||||||
|
## capcut 에이전트 연동 (저장 직후 · 시작만)
|
||||||
|
|
||||||
|
작업 저장이 DONE 되면 그 작업의 영상 생성을 캡컷 에이전트에 바로 넘긴다. **완료를 기다리지 않는다** — 시작된 것만 확인하고 다음 작업의 Opal 실행으로 넘어간다. 여러 작업이 동시에 돌아도 서버는 `analysis_id`별로 독립 처리하므로(`server/app.py`의 `ANALYSES` 딕셔너리, 전역 락 없음) 충돌하지 않는다.
|
||||||
|
|
||||||
|
1. **생존 확인**: `GET http://127.0.0.1:8001` — 200이 아니면 이 단계 전체를 건너뛰고 "캡컷 에이전트 꺼져 있어 넘기지 않음"으로 보고한다(작업 상태는 DONE 유지).
|
||||||
|
2. **작업마다 새 탭**을 연다(`http://127.0.0.1:8001`). 한 탭에서 두 번 실행하면 `analyze()`가 이전 실행의 화면 상태(`A`/`P`/`AUTO_AID`)를 초기화해 먼저 돌던 작업의 진행 화면이 깨진다.
|
||||||
|
3. 탭에서 순서대로:
|
||||||
|
- `#tab-auto` 클릭 (🤖 자동 탭)
|
||||||
|
- 방식에서 **📐 구간 JSON** 선택 — `input[name="amode"][value="wpaste"]`
|
||||||
|
- `#autoUrl` ← 작업의 `youtubeUrl` (구간 JSON에는 URL이 없어 필수)
|
||||||
|
- `#apaste` ← 저장에 쓴 candidates JSON 원문 그대로
|
||||||
|
- `#autoAutoRun`(끝까지 진행)이 **체크되어 있는지 확인**, 아니면 체크한다. 이게 켜져야 버튼이 "댓글 매칭 시작 → 영상까지 자동"이 되고 검토 화면에서 안 멈춘다.
|
||||||
|
- `#autoRmsilence`(무음 제거)는 **사용자가 둔 상태 그대로 두고 건드리지 않는다**.
|
||||||
|
- `#autoGo` 클릭
|
||||||
|
4. **시작 확인**: 버튼이 "분석 중…"으로 바뀌고 진행 로그가 붙는지 스크린샷으로 확인한다. `alert`가 뜨면(URL 없음·JSON 없음) 입력이 빠진 것이므로 채우고 다시 클릭.
|
||||||
|
5. **실행 중인 탭은 닫지 않는다** — 진행이 SSE(`/auto/stream/{aid}`)로 흐르므로 탭을 닫으면 중단된다. 작업 종료 보고 시 "탭 N개에서 영상 생성 진행 중"이라고 남기고 사용자가 닫도록 둔다.
|
||||||
|
|
||||||
## 주의
|
## 주의
|
||||||
|
|
||||||
- Opal은 무료 실험 서비스 — 일일 사용량 제한이 있으니 큐가 많으면 사용자에게 몇 개까지 돌릴지 확인.
|
- Opal은 무료 실험 서비스 — 일일 사용량 제한이 있으니 큐가 많으면 사용자에게 몇 개까지 돌릴지 확인.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user