# task-204.1 완료 보고서: InsuWiki 유튜브 자막 추출 디버깅

**작업일**: 2026-03-03 ~ 2026-03-04
**팀**: dev2-team (오딘 팀장)
**팀원 활동**: 토르(진단/수정), 헤임달(통합테스트)

---

## 1. 문제 요약

보험명의정닥터(23개) + 인스킹(20개) = 43개 영상 모두 `hasTranscript=false` 상태.
자막 추출 0%, Whisper STT도 `OPENAI_API_KEY` 미설정으로 미작동.

---

## 2. 원인 분석

### 근본 원인: YouTube timedtext API 서버 환경 차단

- **기존 방식**: YouTube 영상 HTML 페이지 fetch → 정규식으로 `captionTracks` 파싱 → timedtext URL 요청
- **정규식은 정상 동작**: captionTracks를 HTML에서 성공적으로 찾음
- **실패 지점**: timedtext API URL에 `ip=0.0.0.0&ipbits=0` 파라미터가 포함되어 있어, 서버 환경(Cloud Functions)에서 YouTube가 **빈 응답(0 bytes, HTTP 200)** 반환
- **결과**: `rawData.trim().length === 0` 조건에 걸려 모든 영상에서 `null` 반환

### OPENAI_API_KEY 미설정 (별도 이슈)

- Whisper STT 폴백이 작동하지 않아 최종적으로 제목+설명 기반 요약만 생성
- 이 부분은 환경변수 설정 문제로, 제이회장님과 별도 논의 필요

---

## 3. 수정 내용

### 수정 파일

- `/home/jay/projects/insuwiki/functions/src/crawlYoutubeChannels.ts`

### 수정 상세

**A. Android InnerTube API 방식으로 전면 교체**

기존 HTML 스크래핑 → 정규식 파싱 방식 대신 YouTube Android InnerTube API (`youtubei/v1/player`) 사용:

- `postJson()` 함수 추가: InnerTube API POST 요청 유틸
- `fetchUrlContentWithUA()` 함수 추가: Android YouTube 앱 User-Agent로 자막 데이터 fetch
- `fetchYouTubeTranscript()` 함수 전체 교체:
  1. InnerTube API에 POST → 구조화된 JSON으로 `captionTracks` 직접 수신
  2. 한국어 자막 우선 선택 (수동 ko > 수동 ko-KR > ASR ko > ASR ko-KR)
  3. Android UA로 자막 URL 요청 (서버 환경 차단 우회)
  4. JSON3 + XML 이중 파싱 (자동생성 자막의 `<s>` 태그 포함)

**B. 기존 함수 보존**

- `fetchPageHtml`, `fetchUrlContent`는 `whisperStt.ts`에서 import할 수 있도록 `export`로 변경
- 함수 로직 자체는 미변경

---

## 4. 테스트 결과

### 통합 테스트 (실제 YouTube 영상)

- **보험명의정닥터 (LLkU9k4ZNs4)**: PASS
  - captionTracks 발견: 1개 (ko, vssId=a.ko)
  - 자막 데이터: 562,771 bytes
  - 추출된 텍스트: 53,126자
  - 파싱 방식: XML `<s>` 태그

- **인스킹 ins-king (dEFHkqcpfcM)**: PASS
  - captionTracks 발견: 1개 (ko, vssId=a.ko)
  - 자막 데이터: 24,380 bytes
  - 추출된 텍스트: 2,353자
  - 파싱 방식: XML `<s>` 태그

### TypeScript 빌드

- `npx tsc --noEmit`: 오류 없음 (PASS)

---

## 5. 생성/수정 파일 목록

- **수정**: `functions/src/crawlYoutubeChannels.ts` (fetchYouTubeTranscript 함수 교체 + postJson, fetchUrlContentWithUA 추가)

---

## 6. 버그 유무

- 발견된 버그 없음
- 수정 코드 TypeScript 컴파일 통과
- 실제 YouTube 영상 2개에서 자막 추출 성공 검증

---

## 7. 비고

### OPENAI_API_KEY 설정 관련 권장 사항

- Whisper STT 폴백은 `OPENAI_API_KEY` 환경변수가 필요
- 자막이 없는 영상(자동생성 자막도 없는 경우)을 처리하려면 설정 필요
- Cloud Functions Secret 등록: `firebase functions:secrets:set OPENAI_API_KEY`
- **현재 수정으로 대부분의 영상은 자동생성 자막(ASR)을 추출할 수 있으므로 Whisper STT 필요성은 크게 감소**

### 배포 필요

- 수정 사항을 적용하려면 Cloud Functions 재배포 필요:
  ```bash
  cd /home/jay/projects/insuwiki/functions
  npm run build && npm run deploy
  ```

### 기존 43개 영상 재처리

- 이미 `youtube_knowledge`에 `hasTranscript=false`로 저장된 43개 영상은 자동으로 재처리되지 않음
- 재처리하려면 해당 문서를 삭제하거나 별도 마이그레이션 스크립트 필요
- 또는 `youtube_knowledge`에서 기존 문서를 삭제 후 다음 크롤링 주기에서 자동 처리

---

**보고서 작성 완료**: 2026-03-04 00:10 KST
