피드·인물 수집에서 새로 담긴 영상이 업로드 24시간(골든타임) 이내면
텔레그램으로 알림을 발송한다. 신규 insert만 대상이라 같은 영상이
두 번 울리지 않고, 경쟁(RIVAL) 채널 영상은 알림에서 제외한다.
기존 TelegramNotifier(hlab.notify.telegram) 재사용 — 미설정 시 no-op.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
피드 수집 필터를 쇼츠/롱폼 구분에서 최소 길이(초) 기준으로 교체.
기본 600초(10분) — FEED_MIN_DURATION_SEC 로 조정 가능.
화면 조회에도 같은 하한을 적용해 이미 담긴 10분 미만 영상도
소스·경쟁 탭에서 바로 사라진다. 길이 필터 라벨(공식클립 10~15분)도 정리.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
인물 추적은 65초 컷으로 쇼츠를 걸렀지만 유튜브 쇼츠가 최대 3분까지
허용되면서 1~3분짜리 쇼츠가 통과해 인물 탭에 들어왔다.
수집(PersonPicks)과 조회(feedByPerson) 모두 180초 컷으로 올려
이미 담긴 1~3분 영상도 탭에서 사라지게 했다.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
결과가 잘못 나왔을 때 지금은 작업을 통째로 삭제하고 URL을 다시 등록해야 했다.
등록 이력도 같이 날아간다.
큐 스킬이 status=PENDING 인 작업만 집어가므로, 결과만 비우고 PENDING 으로
되돌리면 그대로 재실행 대상이 된다.
- POST /api/shortform/jobs/{id}/reset — rawOutput·step1Output·clips·title·
completedAt 을 비우고 PENDING 으로. youtubeUrl·videoId·등록시각은 유지한다.
- 화면: PENDING 이 아닌 카드에만 되돌리기 버튼(확인창 포함). 결과가 삭제되므로
무엇이 지워지고 무엇이 남는지 문구에 명시했다.
- FAILED 재시도에 특히 필요했다 — 파싱 실패한 작업을 되살릴 방법이 아예 없었다.
fix: Mockito self-attach 실패로 목 기반 테스트 6건이 깨지던 문제
내 변경과 무관하게 환경에서 깨져 있었다(변경을 치운 깨끗한 트리에서도 동일 실패).
Mockito 가 JVM 에 self-attach 를 시도하다 실패하면 "Could not initialize plugin:
MockMaker" 로 DashboardServiceTest·YoutubeCommentServiceTest 가 전부 죽는다.
JDK 21+ 는 self-attach 를 경고하고 이후 버전에서 막으므로, 권장 방식대로
mockitoAgent 설정을 만들어 -javaagent 로 명시 지정했다. 116건 전부 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
썸네일·제목을 누르면 YouTube 새 탭으로 나가던 걸 레이어 팝업 재생으로 바꿨다.
쇼츠는 세로(9:16), 롱폼은 가로(16:9)로 비율을 맞추고, 팝업 안에 숏폼 큐 등록과
YouTube 열기를 함께 뒀다. Escape·배경 클릭으로 닫히고 닫을 때 재생이 멈춘다.
임베드를 막아둔 채널이 많다는 걸 실측했다 — 소재 원본 9건 중 4건이 차단이고
채널 단위로 갈린다(짠한형 전부 차단, 뜬뜬·스프 전부 가능). 그대로 두면 절반이
"동영상을 재생할 수 없음" 화면을 보게 되므로:
- 수집할 때 videos.list 에 status 파트를 붙여 embeddable 을 저장한다(쿼터 동일).
- 차단된 영상은 팝업 대신 바로 YouTube 새 탭으로 연다.
- 차단 영상 썸네일에 외부링크 아이콘을 띄워 눌렀을 때 나가는 걸 예고한다.
- embeddable 이 null(미수집)이면 일단 재생을 시도한다 — 팝업 안에 YouTube 링크가
있어 막혀도 빠져나갈 수 있다.
브라우저에서 확인: 재생 가능 영상은 팝업에서 실제 재생됐고(썸네일·제목 클릭 모두),
차단 채널 카드에만 외부링크 아이콘이 붙었다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
발굴한 롱폼을 숏폼 큐로 넘기는 동선이 없어 URL을 손으로 옮겨야 했다.
채널 등록·롱폼 수집·정보 표시는 이미 소재 피드에 있으므로 페이지를 새로
만들지 않고 카드에 버튼만 붙였다.
- 소재 원본/인물 탭 카드의 주 버튼을 '숏폼 큐로'로 바꿨다. 경쟁 쇼츠는 이미
잘린 결과물이라 큐 대상이 아니라 원본 보기만 남긴다.
- 피드를 열 때 큐 목록을 함께 받아 이미 담긴 영상은 '큐에 있음'으로 표시하고
숏폼 큐로 링크한다. 등록 API가 videoId 기준 멱등이라 중복 클릭도 안전하다.
- 기존 재가공 스튜디오 진입은 아이콘 버튼으로 남겼다.
- 큐 목록 조회가 실패해도 피드 자체는 정상 동작한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
JobDetail에 rawOutput 노출, 카드 펼침 상단에 전체 복사·영상 URL 복사 툴바 추가.
capcut2가 구분선·타이틀 후보 섞인 통짜 텍스트에서 JSON 5개를 알아서 뽑고
타이틀은 자체 선택 화면에서 고르므로 원문 그대로 복사한다.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
초안 없는 댓글을 한 번에 처리한다. 서버에서 통짜로 돌리지 않고 화면에서 한 건씩
순차 호출한다 — 실측 건당 26~32초라 26건이면 13분짜리 요청이 되어 프록시에서
끊기기 때문이다. 순차 방식이면 진행률이 보이고, 중단해도 앞서 만든 초안은 남는다.
- 진행 바 + 남은 건수, 중단 버튼(진행 중인 1건은 마저 끝냄)
- 완성되는 대로 카드에 반영되어 기다리는 동안에도 읽을 수 있다
- 실패한 건은 건너뛰고 개수만 보고한다(다시 눌러 재시도)
- 확인창에 예상 소요 시간을 알려준다 — 13분짜리 작업을 모르고 시작하지 않게
- 버튼에 남은 건수를 표시하고, 할 게 없으면 비활성화
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
내 영상에 달린 댓글 중 내가 답 안 한 것만 모아, 영상 내용까지 근거로
답글 초안을 만든다. 조회는 나오는데 구독이 안 붙는 문제(59영상 36만 조회
구독 38)에 직접 닿는 지점이라 여기부터 손댔다.
- 미응답 판정은 totalReplyCount 가 아니라 답글 작성자에 내 채널이 있는지로 본다.
남이 대댓글만 단 댓글은 여전히 내가 답해야 하기 때문이다.
- 수집 중 내가 단 답글을 발견하면 말투 샘플로 모아둔다. 실측 17개가 학습됐고
초안이 그 톤을 따른다. 8자 미만("ㅋㅋㅋ")은 말투 정보가 없어 제외.
- 영상 맥락은 Gemini 에 유튜브 URL 을 직접 준다. 내 영상은 30초 쇼츠라 토큰이
적고 화면에 박힌 자막까지 읽힌다. 영상당 1회만 만들어 캐시한다.
- 실제 게시는 OAuth 가 없어 불가 — 초안 복사까지가 끝이다.
실측에서 잡은 결함 두 개를 고쳤다.
1) 요약 생성 때 제목을 안 넘겨서 Gemini 가 출연자 이름을 추측했다. "이채영"
영상을 "이채연"으로 요약했고 그 오류가 답글까지 전파됐다. 제목을 함께 주고
"제목 표기를 글자 그대로" 규칙을 넣어 해결. 캐시가 오염된 경우를 위해
refreshContext 옵션을 두고, '다시 생성'은 요약도 다시 읽게 했다.
2) 영상 요약이 없는데도 규칙에 "[영상 내용]을 근거로"가 남아 없는 섹션을
가리켰다. 요약 유무에 따라 규칙을 갈랐다(테스트가 잡음).
쿼터: 영상당 1 unit — 59개 수집에 59 units.
테스트 11건 추가(미응답 판정·말투 샘플·프롬프트 조립·응답 파싱) — 총 106건 통과.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>