Commit Graph

36 Commits

Author SHA1 Message Date
김보곤
9a7c548246 style: Pint 포맷팅 적용 2026-02-25 11:45:01 +09:00
김보곤
f4879de9ba feat: [video] 3-pass 크롭 검증 추가
- 2-pass 보정 후 각 step의 좌표 영역을 원본에서 크롭하여 Gemini 검증
- 크롭에 패딩 확장 (30% 또는 최소 80px) + 최소 크롭 200x150px 보장
- 빨간 사각형으로 타겟 영역 표시하여 false positive 방지
- 재추정 실패 시 그리드 오버레이 이미지로 3차 재시도
- _verification 메타데이터에 crop_verified, crop_corrected 추가
- PASS율: 37.5% → 100% (FAIL 5 → 0)
2026-02-21 18:30:57 +09:00
김보곤
7991f3e6d4 feat: [video] 좌표 검증 및 영상 메타데이터를 analysis_data에 저장
- 각 step별 검증 결과 저장 (accurate/corrected + 원본 좌표)
- 스크린 단위 검증 통계 저장 (정확/보정 수, 검증 시각)
- 영상 완료 시 _output 메타데이터 저장 (경로, GCS, 비용, 슬라이드수, 총 재생시간)
2026-02-21 16:37:08 +09:00
김보곤
cf6525c8f3 feat: [video] 좌표 검증 루프(Coordinate Verification Loop) 추가
- Gemini 2-pass 자기 검증 메커니즘 구현
- runCoordinateVerification: 검증 오케스트레이터
- createVerificationImage: 색상별 스포트라이트 렌더링
- verifyCoordinates: Gemini에게 좌표 정확도 확인 요청
- applyVerifiedCoordinates: 보정 좌표 적용
2026-02-21 16:02:10 +09:00
김보곤
1c9879b989 refactor: [video] 튜토리얼 영상 좌표 정교화 개선
- Phase 1: 그리드 오버레이를 비율 보존 레터박스 배치로 변경 (annotateSlideWithSpotlight과 동일)
- Phase 2: 그리드 밀도 10x10 → 20x12 향상, 주요 그리드선/좌표 라벨 추가
- Phase 3: 좌표 정규화 경계 클램핑 개선, 편향 패딩 구현, 디버깅 로그 추가
2026-02-21 15:30:37 +09:00
김보곤
b00fd45650 fix:트렌딩 키워드 가져오기 실패 개선 (빈 결과 캐시 방지 + 리프레이밍 폴백)
- 빈 결과를 30분간 캐시하는 문제 수정 (성공 결과만 캐시)
- 건강 키워드가 없을 때 리프레이밍 폴백 추가 (트렌드를 건강 관점으로 재해석)
- 최종 폴백: 원본 인기 키워드 표시
- 프론트엔드 에러/안내 메시지 분리 (오류 vs 건강 키워드 없음)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 06:16:13 +09:00
김보곤
0afe2d7896 fix:스포트라이트 UX 개선 (영역 크기/패딩/시각)
- ScreenAnalysisService: Gemini 프롬프트에 UI 타입별 최소 크기 가이드라인 추가
- ScreenAnalysisService: normalizeCoordinates에 타입별 최소크기 보정 + 1.5% 패딩
- SlideAnnotationService: STEP 배지 1/2 축소 (300x76→150x38)
- SlideAnnotationService: 이중 테두리 (안쪽 흰색 + 바깥 빨간색) 적용
- SlideAnnotationService: 번호 마커 위치를 테두리 바깥으로 이동

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:19:04 +09:00
김보곤
cf7cf9fd7a fix:ASS 자막 비활성화 (슬라이드 캡션바와 중복 제거)
- TutorialVideoJob: 자막 생성 제거, subtitlePath에 null 전달
- TutorialAssemblyService: subtitlePath 파라미터 nullable 변경
- VideoAssemblyService: subtitlePath nullable + null일 때 ass 필터 생략

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:10:38 +09:00
김보곤
edb832bc6a fix:슬라이드 폰트 크기 2배 확대 + 좌표 정확도 개선
- SlideAnnotationService: 아웃트로 메인텍스트 36→72, 서브텍스트 24→48
- ScreenAnalysisService: 그리드 오버레이 레터박스 제거 (전체 채움)
  → Gemini 좌표가 이미지 비율과 직접 매핑되어 스포트라이트 위치 정확도 향상

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:04:12 +09:00
김보곤
ff80d50c9b fix:자막 하단 정렬 + 인트로 자막 중복 제거
- FFmpeg subtitles 필터 → ass 필터 변경 (ASS 스타일 Alignment 완전 보존)
- 인트로/아웃트로 씬 자막 제거를 이중 보장:
  1. Job에서 자막용 scenes 복사본의 인트로/아웃트로 narration을 빈 문자열로 설정
  2. generateAssSubtitle에서 scene_number int 캐스팅 + <= 1 비교로 안전장치 강화

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 17:39:39 +09:00
김보곤
c05ebab380 fix:튜토리얼 자막을 하단 한줄로 변경 (중앙 3줄 → 하단 1줄)
- generateAssSubtitle()에 layout 파라미터 추가 (portrait/landscape)
- landscape 모드: PlayRes 1920x1080, 폰트 48pt, Alignment=2(하단 중앙)
- WrapStyle=2 (줄바꿈 없음) + maxCharsPerLine=999 → 한줄 유지
- BorderStyle=3 (반투명 배경 박스) → 가독성 확보
- MarginL/R=20 (좌우 여백 최소) → 최대한 길게
- TutorialVideoJob에서 'landscape' 레이아웃으로 호출

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 17:22:02 +09:00
김보곤
098bb3d4a8 feat:스크린샷 1920x1080 정규화 + 그리드 좌표 라벨 개선
- 모든 스크린샷을 1920x1080으로 정규화 후 Gemini에 전송
  (비율 유지, 여백은 검정 → 일관된 해상도로 좌표 정확도 향상)
- 그리드 라벨에 실제 0-1000 좌표 병기 (0=0, 1=100, ..., 9=900)
- 교차점에 빨간 십자 마커 추가 (더 정밀한 참조점)
- 프롬프트에 정규화 해상도 + 그리드 간격 정보 명시

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 17:07:52 +09:00
김보곤
c6bd8c8ae1 fix:인트로/아웃트로 자막 중복 표시 제거
인트로(scene 1)와 아웃트로(scene 999) 슬라이드는 이미지에
텍스트가 포함되어 있으므로 ASS 자막 생성에서 제외

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:59:05 +09:00
김보곤
b47c27614b feat:스크린샷 분석 좌표 정확도 개선 (그리드 오버레이 + 0-1000 좌표계)
- 10x10 그리드 오버레이를 스크린샷에 그려서 Gemini에 전송
  (가로 0~9, 세로 A~J 라벨로 AI에게 시각적 참조점 제공)
- 좌표계를 0~1 소수 → 0~1000 정수로 변경 (AI 추정 정확도 향상)
- ERP 화면 기준 좌표 예시 추가 (사이드바, 헤더, 테이블 등)
- normalizeCoordinates()로 1000좌표 → 0~1 비율 자동 변환
- 범위 클램핑으로 비정상 좌표 방지

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:53:53 +09:00
김보곤
46f1577d65 feat:튜토리얼 영상 멀티스텝 개선 (8초 → 30초~2분)
- ScreenAnalysisService: Gemini 프롬프트를 멀티스텝(3~5 steps) 출력으로 변경 + 하위 호환 fallback
- SlideAnnotationService: 스포트라이트 효과(annotateSlideWithSpotlight), 인트로/아웃트로 슬라이드 생성
- TutorialVideoJob: screen→steps 중첩 루프 + 인트로/아웃트로 씬 추가
- index.blade.php: 단계별 나레이션 편집 UI + 예상 시간 표시

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:36:56 +09:00
김보곤
768bc30a6d feat:사용자 매뉴얼 영상 자동 생성 기능 구현
- TutorialVideo 모델 (상태 관리, TenantScope)
- GeminiScriptService에 callGeminiWithParts() 멀티모달 지원 추가
- ScreenAnalysisService: Gemini Vision 스크린샷 AI 분석
- SlideAnnotationService: PHP GD 이미지 어노테이션 (마커, 캡션)
- TutorialAssemblyService: FFmpeg 이미지→영상 합성 (crossfade)
- TutorialVideoJob: 분석→슬라이드→TTS→BGM→합성 파이프라인
- TutorialVideoController: 업로드/분석/생성/상태/다운로드/이력 API
- React-in-Blade UI: 3단계 (업로드→분석확인→생성모니터링) + 이력

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 15:56:39 +09:00
김보곤
e4d8dbddb3 fix:자막-음성 싱크 개선 + 나레이션 밀도 증가 + BGM 볼륨 상향
1. 자막 싱크: ffprobe로 실제 TTS 오디오 길이 측정 → 자막 타이밍 반영
   - 기존: 장면 길이 * 0.75 추정 → 음성과 자막 불일치
   - 변경: 실제 나레이션 오디오 길이 기반 문장별 타이밍 계산
2. 나레이션 밀도: 장면당 40~70자 → 60~100자 (빈 시간 없이 채움)
3. BGM 볼륨: 0.4 → 1.2 (안 들리던 문제 해결)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:50:52 +09:00
김보곤
0f162d1df9 fix:건강 트렌드 필터에서 연예인/인물 키워드 제외
- 프롬프트에 엄격한 제외 규칙 추가 (연예인/정치인/스포츠선수/드라마 등)
- "간접 연결 가능하면 포함" 조건 삭제 (억지 건강 앵글 방지)
- 컨트롤러: 필터 결과가 비면 원본 대신 빈 배열 반환

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:39:58 +09:00
김보곤
073e4c4877 fix:자막 정규식 lookbehind → \K 방식으로 변경 (멀티바이트 호환)
PCRE lookbehind는 멀티바이트 문자 클래스에서 가변길이 오류 발생
→ \K (match reset)로 대체하여 구두점은 앞 문장에 유지

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:38:04 +09:00
김보곤
e9ad735be9 fix:자막 preg_split 가변길이 lookbehind 오류 수정
PCRE는 (?<=[.!?]+) 가변길이 lookbehind 미지원
→ (?<=[.!?])(?![.!?]) 고정길이 lookbehind + negative lookahead 조합으로 변경

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:24:59 +09:00
김보곤
746d350c5e fix:자막 구두점(!?.)이 다음 페이지로 넘어가는 버그 수정
- splitIntoSentences 정규식: 연속 구두점(?!, !!, ?!?)을 하나로 취급
- 분리 조건: 구두점 후 공백이 있을 때만 분리 (공백 없으면 분리 안 함)
- 짧은 조각 병합 방향: forward → backward (이전 문장에 붙임)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:14:54 +09:00
김보곤
06c6005771 feat:Google Lyria API로 AI 배경음악 생성 연동
Lyria API 연동:
- Vertex AI 기반 Google Lyria 음악 생성 API 추가
- 분위기(mood)별 영어 프롬프트 매핑 (upbeat, energetic, calm 등 8종)
- 생성된 30초 WAV → MP3 변환 + 영상 길이에 맞춰 루프/트림
- 페이드인(1초) + 페이드아웃(3초) 자동 적용
- 비용: $0.06/30초

BGM 우선순위 변경:
- 1순위: Lyria AI 배경음악 (신규)
- 2순위: 프리셋 BGM 파일 (storage/app/bgm/)
- 3순위: FFmpeg 앰비언트 (기존 폴백)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:51:38 +09:00
김보곤
85e8d8635d fix:음성+자막 속도 20% 증가 (1.2x → 1.4x)
- TTS 속도: 1.2x → 1.4x
- 자막 타이밍: 장면의 90% → 75% 구간에 압축 (음성과 싱크)
- 쇼츠 트렌드에 맞춘 빠른 템포

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:35:50 +09:00
김보곤
85654799be fix:이모지 TTS 읽기 버그 + 자막 과다 표시 수정
이모지/특수문자 제거:
- TtsService: TTS 전송 전 이모지, *강조*, (효과음), [동작] 등 제거
- VideoAssemblyService: 자막 생성 시에도 동일하게 이모지 제거
- 유니코드 이모지 전체 블록 커버 (이모티콘~태그 문자)

자막 분리 로직 개선:
- 5자 미만 조각만 병합 (기존 10자 → 과도한 병합 제거)
- 정상 문장(5자+)은 독립 자막으로 표시
- 장면당 2~3개 자막으로 깔끔하게 전환

시나리오 프롬프트 수정:
- 이모지/이모티콘 절대 금지 규칙 명시
- *강조*, (효과음), [동작], ○기호 금지
- 숫자 한글 표기 권장 (3가지 → 세 가지)
- 장면당 글자 수 40~70자로 조정 (1.2x 속도에 맞춤)
- 한 문장 10~20자로 축소 (자막 가독성)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:34:04 +09:00
김보곤
a8d87e2b92 fix:여성 음성 변경 + 속도 20% 감속 + 자막 한글자 버그 수정
TTS 설정:
- 음성: Neural2-C (남성) → Neural2-A (여성)
- 속도: 1.5x → 1.2x (20% 감속)
- 피치: 2.0 → 0.0 (자연스러운 여성 톤)

자막 한글자/한단어 버그 수정:
- 최소 청크 길이 10자 보장 (짧은 조각 인접 청크에 병합)
- 전체 25자 이하면 분리하지 않고 한 블록으로 표시
- 남은 짧은 버퍼는 마지막 청크에 합치기
- 최소 표시 시간 0.8초 → 1.5초로 증가
- 줄바꿈 기준 14자 → 16자 (가독성 향상)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:18:47 +09:00
김보곤
ed1967405c feat:트렌드 키워드를 건강 채널용으로 필터링
건강 채널 전용 트렌딩 시스템:
- Gemini로 실시간 트렌드에서 건강 관련 키워드만 필터링
- 간접적 키워드도 건강 앵글로 리프레이밍 (예: 김치 → 장건강)
- 필터 결과 30분 캐싱 (Gemini 호출 최소화)
- 필터 실패 시 원본 키워드 폴백

제목 생성 건강 앵글 반영:
- generateTrendingHookTitles 프롬프트에 건강 채널 명시
- trending_context에 health_angle, suggested_topic 추가
- 모든 제목이 건강/웰빙 관점으로 생성되도록 가이드

UI 건강 테마 적용:
- 버튼/칩 색상: orange/indigo → green 테마
- 칩에 건강 앵글 태그 배지 표시
- 칩 클릭 시 건강 주제(suggested_topic)가 인풋에 채워짐

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:08:57 +09:00
김보곤
e093c7b7e7 fix:TTS 속도 1.5x + Neural2 음성 변경 + 자막 문장 단위 싱크
TTS 개선:
- 음성: ko-KR-Wavenet-A → ko-KR-Neural2-C (남성, 자연스럽고 개성있는 음성)
- 속도: 1.0x → 1.5x (기존 대비 50% 빠르게)
- 피치: 0.0 → 2.0 (더 에너지 있는 톤)

자막 싱크 버그 수정:
- 장면 전체 나레이션을 한 블록으로 표시 → 문장 단위로 분리 표시
- 각 문장 타이밍을 글자 수 비례로 자동 계산
- 문장 분리 로직: 마침표/느낌표/물음표 기준, 폴백으로 쉼표 분리
- 장면 끝 0.3초 여백으로 자연스러운 전환

시나리오 프롬프트:
- 나레이션 문장 길이 규칙 추가 (한 문장 15~25자)
- 반드시 마침표/느낌표/물음표로 문장 구분하도록 명시
- 장면당 글자 수 60~100자로 밀도 향상

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:59:36 +09:00
김보곤
1d512e8acc fix:시나리오 프롬프트 개선 (후킹 강화, CTA 제거, 나레이션 밀도 향상)
- 초반 3초 후킹 규칙 강화 (충격/의문/공감 필수, 평범한 인사 금지)
- 나레이션 속도감 향상 (장면당 50~80자, 빠른 말투)
- 매 장면마다 놀라운 팩트 또는 감정 변화 필수
- 마지막 장면 CTA(좋아요/구독/알림설정) 완전 제거 → 여운 남기는 마무리로 대체
- 장면 구성 6→5장면으로 변경 (CTA 장면 삭제, 시간 재분배)
- 나레이션 좋은/나쁜 예시 추가로 AI 출력 품질 가이드

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:47:37 +09:00
김보곤
0be763b05a feat:트렌딩 키워드 수집 + Veo 3.1 프롬프트 강화 파이프라인
- Google Trends RSS 기반 실시간 급상승 키워드 수집 서비스 추가
- 트렌딩 컨텍스트 활용 후킹 제목 생성 (5패턴: 충격/비교/숫자/질문/반전)
- Veo 3.1 공식 가이드 기반 visual_prompt 5요소 프레임워크 적용
- GET /video/veo3/trending 엔드포인트 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:36:36 +09:00
김보곤
60edc28a17 fix:한국인 여성 캐릭터 고정 + 나레이션-영상 싱크 버그 수정
- Gemini 프롬프트: visual_prompt에 한국인 여성(20대) 등장인물 규칙 추가
- Veo 프롬프트: 모든 클립에 "Korean woman in her 20s" 프리픽스 자동 추가
- 싱크 버그: activeNarrationPaths 인덱스 off-by-one ($num-1→$num) 수정
  - 나레이션이 영상보다 1장면 앞서 재생되던 근본 원인
- concatNarrations: atrim+apad로 나레이션을 장면 길이에 정확히 매칭

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 10:50:51 +09:00
김보곤
01efd99004 fix:자막 중앙배치+크기2배, TTS 볼륨 증가, BGM 앰비언트 자동생성
- 자막: 하단→중앙(Alignment=5), 48→96pt, 외곽선 5px, 줄바꿈 12자
- TTS: 나레이션 볼륨 1.0→2.0 (2배 증가)
- BGM: 무음 대신 분위기별 앰비언트 화음 자동생성 (FFmpeg aevalsrc)
- BGM 볼륨: 0.15→0.4 (나레이션 방해 안 하는 수준)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 10:45:22 +09:00
김보곤
fb69877330 fix:영상 클립 RAI 필터링 대응 (재시도 + 건너뛰기)
- VeoVideoService.waitAndSave() 반환값을 array로 변경 (실패 원인 포함)
- 클립 생성 실패 시 프롬프트 수정 후 자동 재시도
- 재시도 실패 시 해당 장면 건너뛰고 나머지로 합성 진행
- 성공 클립이 절반 미만일 때만 전체 실패 처리
- 건너뛴 장면의 나레이션/자막 자동 필터링

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 10:01:32 +09:00
김보곤
cff3adfd6d fix:Veo 3.1 API 폴링 엔드포인트 수정 (fetchPredictOperation)
- GET /v1/{operationName} → POST fetchPredictOperation 변경
- 응답 구조 predictions → response.videos 수정
- 연속 5회 HTTP 에러 시 조기 중단 로직 추가
- 30초 간격 대기 로그 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 09:44:23 +09:00
김보곤
8a6f3f20c9 fix:Gemini 3.0 Flash 모델 적용 + 제목 선택 UI/UX 개선
- 기본 모델을 gemini-3.0-flash로 변경
- @apply를 순수 CSS로 전환 (Tailwind CDN 호환)
- 제목 카드에 라디오 도트, 체크 뱃지, hover/selected 효과 추가
- 선택 시 border glow + 체크마크 표시

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 08:56:02 +09:00
김보곤
2fbbaad713 fix:GeminiScriptService를 AiConfig(DB) 기반으로 연결
- .env API 키 대신 시스템 > AI 설정의 활성 Gemini 설정 사용
- API Key / Vertex AI(서비스 계정) 방식 자동 분기 지원

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 08:50:26 +09:00
김보곤
6ab93aedd2 feat:YouTube Shorts AI 자동 생성 시스템 구현 (Veo 3.1 + Gemini)
- GeminiScriptService: 트렌딩 제목/시나리오 생성
- VeoVideoService: Veo 3.1 영상 클립 생성
- TtsService: Google TTS 나레이션 생성
- BgmService: 분위기별 BGM 선택
- VideoAssemblyService: FFmpeg 영상 합성
- VideoGenerationJob: 백그라운드 처리
- Veo3Controller: API 엔드포인트
- React 프론트엔드 (5단계 위저드)
- GoogleCloudService.getAccessToken() public 변경

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 08:46:28 +09:00