# YouTube 요약 파이프라인 수정 — 오디오 추출 + 자막 추출 + 처리 로그

## 배경
YouTube가 API 응답 구조를 변경하여 InsuWiki 유튜브 요약 파이프라인의 Track A(자막) + Track B(Whisper STT) 모두 실패하고 있음.
결과: 자막 없는 영상이 Track C(제목+설명만)로 빠져 품질 저하. 오늘 생성된 3개 요약 파일 모두 "⚠️ 설명+제목만 (자막 없음)" 상태.

### 문제 상세
1. **Track A 실패** — `crawlYoutubeChannels.ts` 의 InnerTube Android API가 `FAILED_PRECONDITION` 반환. 기존 파라미터(`clientName: ANDROID, clientVersion: 19.09.37`)로는 서버사이드 호출 차단됨.
2. **Track B 실패** — `whisperStt.ts`의 `extractAudioStreamUrl()`에서 `ytInitialPlayerResponse.streamingData.adaptiveFormats`의 모든 오디오 포맷에 `url` 필드가 없음 (12개 포맷 모두 URL 제거됨). YouTube가 `serverAbrStreamingUrl`로 전환.
3. **Whisper GPU 서비스 자체는 정상** — yt-dlp로 오디오 다운로드 후 Whisper 전송 시 4,597자 한국어 전사 성공 확인됨 (localhost:8200, CUDA medium 모델).

## 참조 파일 (반드시 읽을 것)
1. `/home/jay/projects/insuwiki/functions/src/whisperStt.ts` (489줄) — Whisper STT 모듈
2. `/home/jay/projects/insuwiki/functions/src/crawlYoutubeChannels.ts` (918줄) — 메인 크롤링 파이프라인
3. `/home/jay/projects/insuwiki/functions/src/__tests__/youtubeWhisper.test.ts` — 기존 테스트

## 요구사항

### 1. Track B 수정 — yt-dlp 기반 오디오 추출 (whisperStt.ts)

현재 `extractAudioStreamUrl()` + `downloadAudioBuffer()` → YouTube HTML 파싱 방식 **폐기**

**새 방식: yt-dlp 서브프로세스**
- Cloud Functions 환경에서도 동작해야 하므로, **서버(100.76.130.39)에서 yt-dlp + Whisper를 수행하는 HTTP API 엔드포인트** 방식 권장
- 또는 Cloud Functions에 yt-dlp 바이너리 포함이 어려우면, **로컬 Whisper 서비스(localhost:8200)에 video_id를 받아 yt-dlp → STT를 일괄 처리하는 엔드포인트 추가** 방식

**구현 옵션 (우선순위 순)**:

**옵션 A (권장): Whisper 서비스에 youtube 엔드포인트 추가**
- `/v1/youtube-transcribe` POST — `{ "video_id": "xxx" }` 받으면:
  1. `yt-dlp -f 'ba' --no-playlist -o '/tmp/{video_id}.%(ext)s' 'https://youtube.com/watch?v={video_id}'`
  2. 다운로드된 오디오를 Whisper로 전사
  3. 임시 파일 삭제
  4. `{ "text": "전사 결과...", "source": "whisper_local_ytdlp" }` 반환
- Whisper 서비스 코드: `/home/jay/workspace/services/whisper-gpu/server.py`

**옵션 B: whisperStt.ts에서 직접 yt-dlp 호출**
- Cloud Functions 배포 환경에 yt-dlp가 없으므로 비권장
- 로컬 테스트에서만 가능

**whisperStt.ts 수정사항**:
- `whisperTranscribe(videoId)` 함수를 수정:
  - 기존 HTML 파싱 → 오디오 추출 → Whisper 호출 로직 제거
  - 새로: `LOCAL_WHISPER_URL/v1/youtube-transcribe` POST → `{ video_id }` 전송 → 텍스트 반환
  - timeout: 600초 (긴 영상 대비)
  - 에러 시 null 반환 (기존과 동일한 인터페이스)

### 2. Track A 수정 — InnerTube API 업데이트 (crawlYoutubeChannels.ts)

현재 `fetchYouTubeTranscript()` 의 InnerTube API 파라미터 업데이트.

**시도할 방법들 (우선순위 순)**:

**방법 1: WEB 클라이언트로 전환**
```typescript
context: {
    client: {
        clientName: 'WEB',
        clientVersion: '2.20240313.00.00',  // 최신 버전으로 업데이트
        hl: 'ko',
        gl: 'KR',
    }
}
// User-Agent도 웹 브라우저로 변경
```

**방법 2: TVHTML5_SIMPLY_EMBEDDED_PLAYER 클라이언트**
```typescript
context: {
    client: {
        clientName: 'TVHTML5_SIMPLY_EMBEDDED_PLAYER',
        clientVersion: '2.0',
        hl: 'ko',
        gl: 'KR',
    },
    thirdParty: {
        embedUrl: 'https://www.google.com'
    }
}
```

**방법 3: 자막은 Whisper로 통합**
- InnerTube API가 완전히 차단된 경우, 모든 영상을 Whisper STT로 처리
- Track A를 `youtube-dl --list-subs`로 자막 존재 여부만 확인하고, 자막 URL은 yt-dlp에서 추출

**검증**: 각 방법 시도 후 실제 captionTracks가 반환되는지 확인. 실패 시 다음 방법으로 이동.

### 3. ★★★ 처리 로그 시스템 추가 (신규)

**제이회장님 요구**: 전사 작업이 실제로 제대로 되고 있는지, 어떤 경로로 처리됐는지 로그로 확인 가능해야 함.

**3-1. 처리 로그 파일 (Google Drive 저장)**

크롤링 실행 시마다 처리 로그 파일을 Google Drive에 저장:

**경로**: `04_유튜브요약/_처리로그/YYYY-MM-DD_크롤링로그.md`

**포맷**:
```markdown
# 유튜브 요약 처리 로그

**실행 시각**: 2026-03-26 09:00:00 KST
**처리 채널**: 보험명의정닥터, ins-king

---

## 처리 결과

| # | 영상 제목 | 처리 방식 | 전사 글자수 | 요약 글자수 | 상태 |
|---|----------|----------|-----------|-----------|------|
| 1 | 질병후유장해 3억원 | ✅ YouTube자막 | 8,230자 | 3,500자 | 완료 |
| 2 | 하나손보 입원수술플랜 | 🎤 Whisper STT | 12,450자 | 4,200자 | 완료 |
| 3 | 비급여 자기부담 | ⚠️ 제목+설명만 | 150자 | 2,100자 | 품질주의 |

## 상세 로그

### [1] 질병후유장해 3억원 (vTW1jEiz-Ik)
- 자막 경로: Track A (YouTube 자막)
- 자막 언어: ko (자동생성)
- 전사 텍스트 길이: 8,230자
- 요약 생성: Gemini 2.5 Flash
- Drive 저장: 04_유튜브요약/보험명의정닥터/2026-03-26_질병후유장해..._요약.md
- 처리 시간: 45초

### [2] 하나손보 입원수술플랜 (fhK4q8tXsLI)
- 자막 경로: Track A 실패 → Track B (Whisper STT)
- Track A 실패 사유: captionTracks 없음
- 오디오 다운로드: yt-dlp → 15.3MB webm
- Whisper 모델: medium (GPU)
- 전사 텍스트 길이: 12,450자
- 요약 생성: Gemini 2.5 Flash
- Drive 저장: 04_유튜브요약/보험명의정닥터/2026-03-26_하나손보..._요약.md
- 처리 시간: 2분 30초
```

**3-2. 요약 파일 메타데이터 강화**

각 요약 .md 파일 상단 메타데이터에 추가:
```markdown
- **전사 방식**: ✅ YouTube 자막 (ko, 자동생성) / 🎤 Whisper STT (GPU, 12,450자) / ⚠️ 제목+설명만
- **전사 텍스트 길이**: 12,450자
- **원본 전사 파일**: (Drive URL 또는 경로)
```

기존 `- **자막 기반**: ⚠️ 설명+제목만 (자막 없음)` 대신 위 형식으로 변경.

**3-3. Firestore youtube_knowledge 메타데이터 추가**

기존 필드에 추가:
```typescript
transcriptionLength: number,     // 전사 텍스트 글자수
transcriptionModel?: string,     // 'whisper-medium-gpu' | 'openai-whisper-1' | null
audioSizeMb?: number,            // 오디오 파일 크기 (MB)
processingTimeMs?: number,       // 전체 처리 시간 (ms)
```

**3-4. 대시보드 연동 (선택)**

대시보드의 기록 탭에서 유튜브 처리 로그를 볼 수 있으면 이상적이지만, 이번 Phase에서는 Google Drive 로그 파일로 충분.

## 수정 대상 파일 목록
1. `/home/jay/workspace/services/whisper-gpu/server.py` — youtube-transcribe 엔드포인트 추가
2. `/home/jay/projects/insuwiki/functions/src/whisperStt.ts` — yt-dlp 방식으로 전환
3. `/home/jay/projects/insuwiki/functions/src/crawlYoutubeChannels.ts` — InnerTube API 업데이트 + 처리 로그 추가
4. 테스트 파일 업데이트

## 테스트
- [ ] Track A: 자막 있는 영상으로 자막 추출 확인
- [ ] Track B: 자막 없는 영상으로 yt-dlp → Whisper STT 확인
- [ ] 처리 로그: Google Drive에 크롤링 로그 파일 저장 확인
- [ ] 요약 파일 메타데이터: 전사 방식/글자수 표시 확인
- [ ] 기존 테스트 회귀 없음

## 레벨
Lv.2 (코드 파악 + 구현)

## 프로젝트
insuwiki
