# task-187.1 완료 보고서: 유튜브 파이프라인 확장 (Whisper STT + 전문/요약 분리 + Drive/dispatch 연동)

## 작업 개요
InsuWiki 유튜브 크롤링 시스템을 4개 Phase로 확장:
1. Whisper STT 비용 분석 + 자막 유무 자동 분기
2. 전문(Full Transcript) + 요약 분리 저장
3. 구글드라이브 연동 (project-map incremental)
4. dispatch --changed-files 연동

## 완료 사항

### Phase 1: Whisper STT 비용 분석 + 자막 유무 자동 분기

**비용 분석 결과:**
- 추천안: YouTube 자막 API (우선) + OpenAI Whisper API (폴백)
- 월간 예상 비용: $0.72~1.44 (약 970~1,940원, STT 240분/월 기준)
- Self-hosting 불가 판정: Cloud Functions 1GiB 메모리로 whisper 모델 구동 불가
- 저장: `memory/research/whisper-stt-cost-analysis.md`

**구현:**
- `whisperStt.ts` 신규 모듈: YouTube 페이지 HTML → 오디오 스트림 URL 추출 → 오디오 다운로드 → OpenAI Whisper API 호출
- 3단계 자막 분기: YouTube 자막 → Whisper STT → 제목+설명 (최종 폴백)
- `transcriptionSource` 필드 추가: `'youtube_caption' | 'whisper_stt' | 'title_description'`
- OPENAI_API_KEY를 Cloud Functions secrets에 추가
- 25MB 오디오 크기 제한 (이중 안전장치: URL 추출 시 + 다운로드 중 실시간 차단)

### Phase 2: 전문/요약 분리 저장

**Drive 구조 변경:**
```
04_유튜브요약/{채널명}/
├── {날짜}_{제목}_요약.md    (요약 파일)
└── {날짜}_{제목}_전문.md    (전문 파일 — 실제 자막/STT가 있을 때만)
```

**구현:**
- `uploadMarkdownToDrive` 함수에 `suffix` 파라미터 추가
- `buildTranscriptContent` 함수 신규 추가 (전문 마크다운 빌더)
- Drive에 요약(`_요약`)과 전문(`_전문`) 별도 파일 업로드
- `youtube_knowledge`에 `driveTranscriptUrl` 필드 추가
- 기존 `youtube_transcripts` L3 청크 저장 로직 유지

### Phase 3: 구글드라이브 연동 (project-map incremental)

**구현:**
- `drive-change-log.py`: Drive 업로드 변경사항 JSONL 로그 관리
  - 4개 서브커맨드: `add`, `list`, `mark-processed`, `cleanup`
  - fcntl 파일 잠금 + atomic write
- `project-map.py` 확장:
  - `--drive-log` CLI 옵션 추가
  - `IncrementalUpdater._process_drive_log()` 메서드 추가
  - `render_markdown()`에 "Drive Changes (Recent)" 섹션 추가
- 기존 테스트 15/15 PASS 확인 (비퇴행)

### Phase 4: dispatch --changed-files 연동

**구현:**
- `extract-changed-files.py`: 보고서에서 변경 파일 목록 자동 추출
  - 테이블/리스트 형식 파싱 지원
  - `--auto-update` 옵션으로 project-map.py 자동 트리거
- `post-task-hook.sh`: 작업 완료 후 자동 실행 후크 스크립트
  - 보고서 파싱 → changed-files 추출 → project-map.py --incremental 실행

## 생성/수정 파일 목록

| 파일 | 변경 유형 | 설명 |
|------|-----------|------|
| functions/src/whisperStt.ts | 생성 | Whisper STT 모듈 (346줄) |
| functions/src/crawlYoutubeChannels.ts | 수정 | 자막 분기 + 전문/요약 분리 저장 |
| nextapp/src/types/firestore.ts | 수정 | YoutubeKnowledge 타입 확장 + 컬렉션 상수 추가 |
| scripts/drive-change-log.py | 생성 | Drive 변경 로그 유틸리티 (295줄) |
| scripts/project-map.py | 수정 | --drive-log 옵션 + Drive Changes 섹션 |
| scripts/extract-changed-files.py | 생성 | 보고서 파일 목록 추출 유틸리티 (375줄) |
| scripts/post-task-hook.sh | 생성 | 작업 완료 후 자동 후크 |
| memory/research/whisper-stt-cost-analysis.md | 생성 | Whisper STT 비용 분석 리포트 (350줄) |

## 테스트 결과

- TypeScript 컴파일 (`npx tsc --noEmit`): PASS (에러 0)
- project-map incremental 테스트: 15/15 PASSED (0.17s)
- Python 문법 검증 (drive-change-log.py, extract-changed-files.py): PASS
- 보고서 파싱 실동작 테스트 (task-186.1.md): PASS (4개 파일 정확 추출)
- post-task-hook.sh 실행 권한: PASS (-rwxrwxr-x)

## 마아트 QC 검증 결과

- 테스트 재실행: PASS
- 파일 경로 확인: PASS (6개 파일 전부 올바른 경로)
- 코드 품질: PASS (25MB 이중 안전장치, null 처리, hasTranscript Whisper 포함)
- 결과 일치: PASS (보고된 결과 = 실제 결과)
- 종합 판정: **PASS**

## 버그 유무
- 없음

## 엣지 케이스 처리
- OPENAI_API_KEY 미설정: 기존 제목+설명 폴백으로 자동 전환
- YouTube signatureCipher 보호 오디오: 직접 URL만 사용, 실패 시 폴백
- 25MB 초과 오디오: 3단계 차단 (URL 추출 시, 다운로드 중, 버퍼 최종 확인)
- 빈 자막/빈 오디오: null 반환 → 제목+설명 폴백

## 비고
- 기존 파이프라인 하위 호환성 100% 유지 (확장만, 삭제 없음)
- Drive 파일명 변경: `{날짜}_{제목}.md` → `{날짜}_{제목}_요약.md` (기존 파일은 영향 없음, 새 파일부터 적용)
- Whisper STT는 OPENAI_API_KEY Secret 등록 후 활성화됨
- 프로덕션 배포 시 `firebase deploy --only functions` + OPENAI_API_KEY Secret 등록 필요
