docs: 스펙 범위를 구간 탭 + 붙여넣기 탭으로 확장

댓글 매칭이 일어나는 모든 곳에 같은 추천·배치를 적용한다. 붙여넣기 탭은
자막이 JSON 안에 있어 파이프라인·추천 엔진을 안 건드리고 화면만 붙이면 되므로
같은 스펙에 담는다. 카드 패널 렌더러가 세 갈래로 갈라지는 걸 막기 위해
renderCutPanel 하나로 모으는 것도 포함.

파일 탭은 제외 — 로컬 파일이라 원본 영상 시각을 몰라 분:초 매칭이 불가하다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
hehihoho3@gmail.com 2026-08-04 16:19:22 +09:00
parent 4abf41ebcb
commit 2d37d42893

View File

@ -1,9 +1,24 @@
# 유튜브 구간 탭 — 2단계 분할 + 구간별 댓글 추천 (설계)
# 컷별 댓글 추천을 남은 두 탭에 — 구간 탭(2단계 분할) + 붙여넣기 탭 (설계)
작성일: 2026-08-04
관련 코드: `capcut_agent/pipeline.py`, `capcut_agent/recommend.py`, `server/app.py`, `server/static/auto.js`, `server/static/index.html`
선행 스펙: `2026-08-04-컷별-댓글-추천-design.md` (자동 탭. 추천 엔진 `recommend.py`가 여기서 나왔다)
## 0. 목표 한 줄
**댓글 매칭이 일어나는 모든 곳에서 같은 추천·배치가 돌게 한다.**
| 탭 | 상태 | 이 스펙에서 |
|---|---|---|
| 🤖 자동 | ✅ 완료(선행 스펙) | 손대지 않음 |
| ▶ 유튜브 구간 | 분:초만 봄 | **2단계로 쪼개고** Whisper 자막으로 추천 — §2~§12 |
| 📋 붙여넣기 | 댓글 매칭 UI 자체가 없음 | **매칭 화면 추가** — §13 |
| 📁 파일 | 로컬 파일이라 유튜브 URL이 없음 | 제외 — §14 |
두 탭의 난이도가 크게 다르다. 구간 탭은 파이프라인을 쪼개는 구조 변경이고,
붙여넣기 탭은 **파이프라인·추천 엔진을 하나도 안 건드린다**(이미 컷 자막이 있고
`process_paste``card_cuts`를 받는다). 그래서 한 스펙에 같이 담는다.
## 1. 배경
▶ 유튜브 구간 탭의 `💬 구간 댓글 매칭`**댓글 본문의 분:초만** 본다. 실측(2026-08-04):
@ -194,28 +209,79 @@ Gemini 내용 매칭 경로**로 간다. 타임스탬프 우선·중복 금지
**어떤 경우에도 드래프트 생성을 막지 않는다**(다운로드 실패 제외 — 그건 영상이 없다).
## 13. 하지 않는 것
## 13. 📋 붙여넣기 탭
- **📋 붙여넣기 탭** — 별도 스펙. 구간 탭에서 만든 재사용 부품 위에 얹는 게 순서다.
- **📁 파일 탭 흐름 변경** — 내부만 쪼개고 겉보기는 그대로.
구간 탭과 달리 **2단계로 쪼갤 필요가 없다.** 자막이 붙여넣은 JSON 안에 이미 있어서
영상을 받기 전에 추천이 끝난다. 그래서 지금 구간 탭이 쓰던 방식 — `💬 댓글 매칭`
버튼으로 먼저 고르고 `편집 시작` — 을 그대로 쓴다.
**파이프라인과 추천 엔진은 한 줄도 안 건드린다:**
- 컷마다 `bottom` 자막이 있다 → `build_highlight_cuts()`가 그대로 걸려 Gemini 내용 매칭이 돈다
- `process_paste(..., card_cuts=…)`는 선행 작업에서 이미 받는다
**새로 만드는 것:**
| 위치 | 변경 |
|---|---|
| `POST /paste/comments` (신규) | 폼 `data`(붙여넣은 JSON) → `parse_paste``fetch_comments(url)``build_highlight_cuts``{cuts, need, comments, candidates, warnings}` |
| `POST /paste` | `cards`(PNG 다수)·`card_cuts` 폼 필드 추가. 저장 로직은 기존 `/youtube`의 것을 그대로 옮긴다 |
| `index.html` | 붙여넣기 탭에 `💬 댓글 매칭` 버튼 + 결과 영역 |
| `auto.js` | `window.pasteCC = {active, capture}` 다리 추가 (기존 `window.ytCC`와 같은 모양) |
**주의**: 붙여넣기 탭의 `무음 제거`·`받아쓰기 자동 생성` 옵션을 켜면 타임라인이 줄거나
자막이 바뀐다. 추천은 붙여넣은 JSON의 `bottom` 기준으로 하되, 배치 장수는 자동 탭과
똑같이 `_cards_by_cut`이 압축 후 길이로 캡하고 버린 장수를 로그에 남긴다. 별도 처리 없음.
## 13-1. 렌더러를 하나로 모은다
지금 카드 패널을 그리는 코드가 자동 탭(`onResult`)과 구간 탭(`ytMatch`) 두 군데에
갈라져 있다. 여기에 붙여넣기 탭까지 더하면 세 갈래가 되어 한 곳만 고치는 실수가 난다.
**`renderCutPanel(panelId, data, opts)` 하나로 모은다** — 컷/구간별 섹션, ⭐🤖➕ 배지,
검색창, ` 채우기` 섹션, 선택 상한을 전부 담당한다. 세 탭이 `panelId`만 달리해서 부른다
(`hl.id` / `"yt"` / `"paste"`). 라벨 접두사(`컷` vs `구간`)는 `opts`로 넘긴다.
이건 이번 작업에 필요해서 하는 정리이지, 무관한 리팩터링이 아니다.
## 14. 하지 않는 것
- **📁 파일 탭** — 로컬 파일이라 댓글을 가져올 유튜브 URL이 없다. URL 칸을 따로 받으면
자막 기반 추천(🤖)은 가능하지만, 로컬 파일의 시각이 원본 영상 시각과 달라
**분:초 매칭(⭐)은 원리적으로 불가**하다. 사용자가 제외를 선택했다.
- **📁 파일 탭 흐름 변경** — `process_bg_template` 내부만 쪼개고 겉보기는 그대로.
- **유튜브 자동자막** — Whisper 받아쓰기를 쓰기로 했으므로 불필요.
- **🤖 자동 탭** — 손대지 않는다.
- **🤖 자동 탭** — 렌더러 통합(§13-1) 외에는 동작을 바꾸지 않는다.
- **다운로드 캐시 추가** — 파이프라인을 쪼개면 재다운로드가 없어지므로 필요 없다.
- **구간별 제목·출처 개별 지정** — 구간을 이어붙여 영상 하나를 만드는 것이므로 제목도 하나다.
- **붙여넣기 탭 2단계 분할** — 자막이 JSON에 있어 쪼갤 이유가 없다.
## 14. 검증
## 15. 검증
자동 테스트 스위트가 없다(CLAUDE.md). 다음으로 확인한다.
1. `is_time_based()` / 구간별 `_whole_picks` 중복 방지 — 인라인 assert
2. 구간 자막 추출(압축 좌표 범위 → 캡션 이어붙이기) — 인라인 assert
3. `quotas` 외부 주입 시 `build_highlight_cuts` 동작 — 인라인 assert
4. 📁 파일 탭 회귀: 분할 전후 SSE 이벤트 순서·내용이 같은가 (실제 파일 1건)
5. 구간 2개짜리 실제 영상 1건 → 검토 화면에 구간별 섹션·자동 선택이 뜨는가
6. 생성된 `draft_content.json`에서 카드 시간이 **각 구간의 압축 타임라인 범위 안**인가
7. 표시한 `need` 장수 = 실제 배치된 카드 수 (버려지는 카드 0)
8. Gemini 키를 비워 폴백이 도는가
**순수 함수 (인라인 assert, 네트워크·서버 없이)**
1. `is_time_based()` — 자막이 전부 비면 참, 하나라도 차 있으면 거짓. 컷 1개 통짜도 참
2. 구간별 `_whole_picks` — 구간 간 댓글 중복 배정이 없는가
3. 구간 자막 추출 — 압축 좌표 범위에 걸친 캡션만 이어붙이는가, 500자에서 자르는가
4. `quotas` 외부 주입 시 `build_highlight_cuts` 동작 (안 넘기면 기존과 동일)
## 15. 열린 질문
**회귀 (실행 확인)**
5. 📁 파일 탭: 분할 전후 SSE 이벤트 순서·내용이 같은가 (실제 파일 1건). `state` 이벤트가 밖으로 새지 않는가
6. 🤖 자동 탭: 렌더러 통합 후 컷별 섹션·배지·검색·캡처가 그대로인가
**구간 탭 (실사용)**
7. 구간 2개짜리 실제 영상 1건 → 검토 화면에 구간별 섹션·자동 선택이 뜨는가
8. `draft_content.json`에서 카드 시간이 **각 구간의 압축 타임라인 범위 안**인가
9. 표시한 `need` 장수 = 실제 배치된 카드 수 (버려지는 카드 0)
**붙여넣기 탭 (실사용)**
10. `💬 댓글 매칭` → 컷별 섹션·추천이 뜨는가
11. 카드가 해당 컷 위에 깔리는가
12. 댓글을 하나도 안 고르고 `편집 시작`해도 기존처럼 생성되는가 (하위호환)
**공통**
13. Gemini 키를 비워 세 탭 모두 폴백이 도는가
## 16. 열린 질문
없음. 미결이 생기면 여기에 적고 구현 전에 사용자에게 묻는다.