diff --git a/.claude/skills/shortform-queue/SKILL.md b/.claude/skills/shortform-queue/SKILL.md index 27aa337..c217666 100644 --- a/.claude/skills/shortform-queue/SKILL.md +++ b/.claude/skills/shortform-queue/SKILL.md @@ -26,6 +26,7 @@ h-lab 서버가 꺼져 있으면 먼저 `.\gradlew.bat bootRun`(JAVA_HOME=D:\Dev a. 캔버스의 **YouTube Video 노드 클릭** → 우측 패널 URL 입력창을 비우고(전체선택 ctrl+a 후 덮어쓰기) 작업의 youtubeUrl 입력 → **Apply** (썸네일이 해당 영상으로 바뀌는지 확인). b. Preview 패널의 새로고침(리셋) 아이콘 → **Start** 클릭. c. **완료 폴링** 및 **추출**: 모드별 절차(아래) 참조. + d. **JSON 검증·보정** (1단계 모드에서 저장 전 필수): 추출 텍스트를 `ConvertFrom-Json`으로 파싱해본다. 실패하면 스킬 폴더의 `fix-opal-json.ps1`로 보정하고 다시 검증한다 — 통과하면 보정본으로 저장·전달하고, 여전히 깨지면 저장하지 말고(PENDING 유지) 원문과 파싱 오류를 보고한다. 보정 후 candidates가 5개인지도 확인. (풀버전은 `N=====` 구간 5개라 통짜 파싱 대상이 아님 — 저장 후 응답 clips 개수로 확인한다.) e. **저장**: 브라우저 fetch는 HTTPS→HTTP라 차단됨 — 추출 텍스트를 파일로 옮겨 셸에서 `POST http://localhost:8088/api/shortform/jobs/{id}/result` body `{"rawText": "", "step1Text": ""}`. 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이 항상 실패했음). @@ -51,9 +52,9 @@ h-lab 서버가 꺼져 있으면 먼저 `.\gradlew.bat bootRun`(JAVA_HOME=D:\Dev 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 원문 그대로 + - 방식 선택 — 1단계 모드(기본)는 **📐 구간 JSON** `input[name="amode"][value="wpaste"]`, 풀버전은 **📋 오팔 JSON** `value="paste"` + - `#autoUrl` ← 작업의 `youtubeUrl` (구간 JSON에는 URL이 없어 필수. 오팔 JSON 모드에서는 선택) + - `#apaste` ← 저장에 쓴 원문 그대로 (1단계=candidates JSON, 풀버전=Output 통짜) - `#autoAutoRun`(끝까지 진행)이 **체크되어 있는지 확인**, 아니면 체크한다. 이게 켜져야 버튼이 "댓글 매칭 시작 → 영상까지 자동"이 되고 검토 화면에서 안 멈춘다. - `#autoRmsilence`(무음 제거)는 **사용자가 둔 상태 그대로 두고 건드리지 않는다**. - `#autoGo` 클릭 diff --git a/.claude/skills/shortform-queue/fix-opal-json.ps1 b/.claude/skills/shortform-queue/fix-opal-json.ps1 new file mode 100644 index 0000000..7111f5a --- /dev/null +++ b/.claude/skills/shortform-queue/fix-opal-json.ps1 @@ -0,0 +1,25 @@ +# Opal 출력 JSON 보정 — 문자열 값 안의 미이스케이프 따옴표를 \" 로 바꾼다. +# +# Opal이 title_top 같은 값에 따옴표를 그대로 뱉는 일이 있다(예: "title_top": ""나 진짜 방장하기 싫어..."""). +# 그대로 저장하면 ShortformOutputParser의 Jackson readTree가 던져서 status=FAILED, clips=0이 되고, +# 캡컷 에이전트의 구간 JSON 붙여넣기도 같이 막힌다. +# +# 한 줄에 필드 하나씩 나오는 Opal 출력 형태를 전제로, `"key": "value"` 꼴 줄의 +# value 안쪽 따옴표만 이스케이프한다. 이미 정상인 JSON에는 아무 변화가 없다. +# +# 사용: +# $fixed = & .\fix-opal-json.ps1 -Text $raw +param([Parameter(Mandatory = $true)][AllowEmptyString()][string]$Text) + +$lines = $Text -split "`r`n|`n|`r" +$out = foreach ($ln in $lines) { + if ($ln -match '^(\s*"[A-Za-z0-9_]+"\s*:\s*)"(.*)"(\s*,?)\s*$') { + $pre = $Matches[1]; $val = $Matches[2]; $tail = $Matches[3] + $val = [regex]::Replace($val, '(?