Commit Graph

10 Commits

Author SHA1 Message Date
3c013dcc88 유튜브 구간 탭에 붙여넣기 탭과 같은 분석→검토→생성 흐름 연결 (Task 6)
죽은 /yt/comments, /youtube 를 부르던 구식 화면(💬 구간 댓글 매칭 버튼, ytMatch,
window.ytCC)을 걷어내고 "편집 시작"이 /yt/analyze→SSE /yt/stream 을 돌게 했다.
검토 영역 위에 제목·출처 입력칸을 둬 분석 후에도 고칠 수 있게 하고, 생성
(/yt/build) 때 그 값을 보낸다 — bg_draft 가 title_*/channel 을 state 에서만
읽으므로 /yt/build 에도 그 세 필드를 추가해 state 를 덮어쓰게 했다(server/app.py,
브리프의 파일 목록엔 없었지만 이 요구사항 자체가 성립하려면 꼭 필요했다).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 12:05:19 +09:00
678d3f20e5 유튜브 구간 탭에 분석→추천→빌드 3단계 서버 흐름 추가, 옛 단일 엔드포인트 제거
붙여넣기 탭(Task 3)과 같은 구조로 /yt/analyze·/yt/stream/{aid}·/yt/build를
추가해 다운로드 전에 댓글 매칭 검토가 가능하게 한다. bg_analyze/bg_draft로
쪼개고 state["places"]/state["ranges_sec"]로 압축·원본 두 좌표계를 분리해
recommend.cuts_from_state에 넘겼다. 옛 /yt/comments·/youtube는 새 흐름이
대체하므로 삭제.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 11:48:08 +09:00
447e8808ff 붙여넣기 탭에 댓글 선택 화면 추가 (Task 4) + 서버 매니페스트 보정
병렬 세션에서 구현된 것을 검증 후 커밋. Task 3 리뷰가 짚은 (a)~(e) 전부 반영:
analyze manifest 에서 draft 스텝 제외(영원히 대기하던 것), comments start 이벤트,
build 스트림 manifest, 무음 제거 체크박스 숨김(항상 켜지므로), cuts_from_state
try/except(실패 시 cuts=None 으로 / 폴백 화면).

캡처 함정 3종(검색 해제·컷 펼침·selonly 해제)과 append/push 쌍 실행, 캡처 실패
n-- 까지 자동 탭과 동일하게 처리됨을 확인함.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 11:14:47 +09:00
85101867d5 붙여넣기 탭에 자동 탭과 같은 분석→추천→빌드 3단계 서버 흐름 추가
지금까지 붙여넣기 탭은 편집안 JSON을 받으면 바로 드래프트를 만들었는데,
자동 탭처럼 컷별 댓글 카드를 추천받아 검토한 뒤 만들 수 있도록
/paste/analyze(검증)·/paste/stream/{aid}(다운로드·무음·받아쓰기+h-lab
댓글 수집+추천)·/paste/build(보관한 상태로 드래프트만) 3종 엔드포인트를
추가했다. 추천에는 받아쓰기가 항상 필요해 analyze 단계는
remove_silence·asr_bottom을 강제로 켜고, build에서 asr_bottom을 끄면
받아쓰기 자막을 원래 JSON 자막으로 되돌려 압축 타임라인에 재매핑한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:46:15 +09:00
011c042778 자동 탭: 🔤 단어겹침 배지 표시 + AI 추천 실패 경고 문구 명확화
WHY 배지 맵에 word:"🔤" 를 더해 3순위(단어 겹침)로 배정된 카드가 화면에서
구분되게 했다(다른 곳엔 why 값을 쓰는 곳이 없어 auto.js 한 곳만 고치면 된다).
"AI 추천 실패 — 타임스탬프만으로 배정했습니다" 문구는 로그 영역에 묻혀
사용자가 못 보던 경고였다. 무엇이 실패했고(Gemini 응답 없음) 그래서 어떻게
됐는지(분:초·자막단어·좋아요로 대체)가 한 문장에서 드러나도록 고쳤다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 18:43:39 +09:00
4e479b50ce 추천 단계에 진행 표시 추가 (최대 450초 무반응 제거)
/auto/stream 은 하이라이트 5개를 순차로 돌며 각각 Gemini 를 부른다(timeout=90).
manifest 에 recommend 스텝이 없고 루프 안에 로그도 없어서, 마지막으로 보이는 게
"댓글 수집 done" 이고 그 뒤 최악 450초 동안 아무 이벤트도 안 나갔다.
사용자가 멈춘 줄 알고 새로고침하면 분석이 통째로 날아간다.

순차 호출 자체는 유지한다 — 동시에 5발을 쏘면 429 가 난다(Step 3 도 같은 이유로
시차 재시도를 쓴다). 대신 보이게만 만든다:
- 세 갈래 manifest(paste / wpaste / else) 전부에 recommend 스텝 추가
- 루프 앞뒤로 step start/done(detail = 처리한 하이라이트 수)
- 하이라이트마다 "ID n 컷별 댓글 추천 중… (i/N, 컷 M개)" 로그 한 줄

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 14:09:41 +09:00
1e43530933 Gemini 추천 실패를 화면에 알린다 (조용히 삼키지 않음)
ai_pick_cuts 가 429·타임아웃·JSON 파싱 실패를 전부 {} 로 삼켜서,
build_highlight_cuts 는 여전히 타임스탬프만으로 채운 cuts 를 돌려주고
app.py 의 `if cuts:` 가 참이 되어 except 가 절대 타지 않았다.
스펙 §7이 요구한 "⚠ 추천 실패 → 기존 방식" 경고가 화면에 안 떴다.

- ai_pick_cuts: 실패는 None, 성공은 dict(빈 dict 포함).
  키가 없는 경우는 실패가 아니다 — 키 없이 쓰는 것도 정상 사용이라 {} 를 준다.
  실패로 치는 건 HTTP·타임아웃·응답 파싱·프롬프트 치환 오류뿐.
- 응답 파싱을 _rows_to_picks() 로 떼어내 '깨진 응답'(None)과
  '어울리는 게 없어 빈 배열'({})을 구분한다. _parse_ai() 계약은 그대로 둔다.
- build_highlight_cuts → (cuts, need, ai_failed) 3-튜플.
  통짜 모드는 Gemini 를 안 부르므로 ai_failed=False.
- build_cut_picks 는 ai_picks=None 이어도 안전(`ai_picks or {}`).
- app.py: ai_failed 면 warnings 에 "AI 추천 실패 — 타임스탬프만으로 배정" 한 줄.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 14:09:19 +09:00
c3556edb9d /auto/build가 card_cuts 폼 필드를 받아 파이프라인에 넘김
- auto_build 시그니처에 card_cuts 폼 필드 추가
- JSON 배열 문자열 파싱 (값 깨져도 빌드 계속)
- job dict에 저장 후 process_paste 호출에 전달
- bool 필터링 강화: JSON true/false가 정수로 둔갑하지 않도록

이유: JSON의 true/false가 Python bool로 파싱되는데, bool이 int의 서브클래스라
isinstance(v, int)를 통과해 컷 인덱스 1/0으로 대신 쓰이는 문제 해결.
capcut_agent/recommend.py 패턴과 일관성 있음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 12:23:18 +09:00
90ff2b174f /auto/analyze 결과에 컷별 추천(cuts[]) 추가
댓글 매칭 후 recommend.build_highlight_cuts()를 호출해 하이라이트별
cuts/need를 SSE result에 실어 보낸다. Gemini 호출이 블로킹이라
asyncio.to_thread로 스레드에서 돌리고, 실패해도 기존 matched/candidates로
화면이 폴백하도록 warnings에만 기록하고 드래프트 생성은 막지 않는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 12:12:35 +09:00
bf1b387d6d chore: git 저장소 초기화 (기존 코드 스냅샷)
컷별 댓글 추천 작업을 태스크 단위로 되돌릴 수 있게 버전관리를 시작한다.
.gitignore 로 영상·캐시(.downloads 2.7G, .comments 72M, .media 28M)와
비밀키(.gemini_key)를 제외했다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 11:36:05 +09:00