---
name: youtube-transcript
description: "YouTube 영상 URL에서 자막을 추출하고 텍스트로 변환한다. 보험 교육 영상, 경쟁사 콘텐츠, 금융 설명회 영상 분석 등 리서치 목적으로 활용한다."
triggers:
  - "youtube-transcript"
  - "유튜브 자막"
  - "유튜브 transcript"
  - "youtube 자막 추출"
  - "영상 자막"
  - "youtube caption"
  - "유튜브 텍스트 추출"
  - "영상 텍스트 변환"
  - "자막 다운로드"
  - "subtitle download"
  - "영상 내용 분석"
  - "유튜브 리서치"
usage: "/youtube-transcript [URL] [--lang ko] [--summary] [--timestamps]"
---

# /youtube-transcript — YouTube 자막 추출 및 분석

> 출처: michalparkola/tapestry-skills-for-claude-code (MIT 라이선스)
> 우리 시스템에 맞게 커스텀 (한국어 우선, 보험/금융 도메인 특화, youtube-transcript-api 방식 추가)

YouTube 영상에서 자막을 추출하여 텍스트로 변환한다. 보험 교육 영상 분석, 경쟁사 콘텐츠 리서치, 금융감독원 설명회 요약 등 다양한 리서치 용도로 활용한다.

**프레이야(개발2팀 프론트엔드 전문가)** 가 이 스킬을 주도한다.

---

## User-invocable

사용자가 `/youtube-transcript`를 입력하거나, YouTube URL과 함께 자막 추출을 요청할 때 이 스킬을 실행한다.

---

## Arguments

- `/youtube-transcript [URL]` — 기본 자막 추출 (한국어 우선, 영어 대안)
- `/youtube-transcript [URL] --lang ko` — 한국어 자막만 추출
- `/youtube-transcript [URL] --lang en` — 영어 자막만 추출
- `/youtube-transcript [URL] --summary` — 자막 추출 후 요약 생성
- `/youtube-transcript [URL] --timestamps` — 타임스탬프 포함하여 출력

---

## 워크플로우

```
Step 1: 환경 확인 (도구 설치 여부)
    ↓
Step 2: YouTube URL 수신 및 영상 정보 확인
    ↓
Step 3: 사용 가능한 자막 목록 조회
    ↓
Step 4: 자막 다운로드 (수동 > 자동생성 순서)
    ↓
Step 5: VTT → 텍스트 변환 (중복 제거, 타임스탬프 처리)
    ↓
Step 6: 저장 및 출력
    ↓
Step 7: 요약 생성 (--summary 옵션 시)
```

---

## Step 1: 환경 확인

두 가지 방법 중 하나로 자막을 추출한다. 아래 순서로 확인한다.

### 방법 1: youtube-transcript-api (권장, 경량)

```bash
python3 -c "import youtube_transcript_api; print('OK')" 2>/dev/null || echo "NOT_INSTALLED"
```

설치가 안 되어 있으면:

```bash
pip install youtube-transcript-api
```

### 방법 2: yt-dlp (대안, 더 많은 기능)

```bash
which yt-dlp || command -v yt-dlp || echo "NOT_INSTALLED"
```

설치가 안 되어 있으면:

```bash
# Linux (apt)
sudo apt update && sudo apt install -y yt-dlp

# 또는 pip (모든 환경)
pip install yt-dlp
```

### 우선순위 결정

- youtube-transcript-api 설치됨 → 방법 1 사용 (빠르고 가벼움)
- youtube-transcript-api 미설치, yt-dlp 설치됨 → 방법 2 사용
- 둘 다 미설치 → youtube-transcript-api 설치 권장 안내 후 설치

---

## Step 2: YouTube URL 확인

URL에서 VIDEO_ID를 추출한다.

```python
import re

def extract_video_id(url):
    patterns = [
        r'(?:youtube\.com\/watch\?v=)([a-zA-Z0-9_-]{11})',
        r'(?:youtu\.be\/)([a-zA-Z0-9_-]{11})',
        r'(?:youtube\.com\/shorts\/)([a-zA-Z0-9_-]{11})',
    ]
    for pattern in patterns:
        match = re.search(pattern, url)
        if match:
            return match.group(1)
    return None
```

URL 형식이 유효하지 않으면 사용자에게 올바른 URL 형식을 안내한다:
- `https://youtube.com/watch?v=VIDEO_ID`
- `https://youtu.be/VIDEO_ID`
- `https://youtube.com/shorts/VIDEO_ID`

---

## Step 3: 사용 가능한 자막 목록 조회

### 방법 1 (youtube-transcript-api)

```python
from youtube_transcript_api import YouTubeTranscriptApi

video_id = "VIDEO_ID"
transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)

print("수동 자막:")
for t in transcript_list._manually_created_transcripts.values():
    print(f"  - {t.language} ({t.language_code})")

print("자동 생성 자막:")
for t in transcript_list._generated_transcripts.values():
    print(f"  - {t.language} ({t.language_code})")
```

### 방법 2 (yt-dlp)

```bash
yt-dlp --list-subs "YOUTUBE_URL"
```

자막 목록을 사용자에게 표시한 후 진행한다.

---

## Step 4: 자막 다운로드

### 방법 1 (youtube-transcript-api) — 권장

```python
from youtube_transcript_api import YouTubeTranscriptApi

video_id = "VIDEO_ID"
target_langs = ['ko', 'en']  # 한국어 우선, 영어 대안

try:
    # 수동 자막 우선 시도
    transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
    transcript = transcript_list.find_manually_created_transcript(target_langs)
    entries = transcript.fetch()
    lang_used = transcript.language_code
    is_auto = False
except Exception:
    try:
        # 자동 생성 자막 대안
        transcript = transcript_list.find_generated_transcript(target_langs)
        entries = transcript.fetch()
        lang_used = transcript.language_code
        is_auto = True
    except Exception as e:
        print(f"자막을 찾을 수 없습니다: {e}")
        # 에러 처리 섹션 참조

# 결과: [{'text': '...', 'start': 0.0, 'duration': 2.5}, ...]
```

### 방법 2 (yt-dlp)

```bash
# 수동 자막 우선 시도
yt-dlp --write-sub --sub-langs "ko,en" --skip-download --output "transcript_temp" "YOUTUBE_URL" 2>/dev/null

# 수동 자막 없으면 자동 생성 자막
yt-dlp --write-auto-sub --sub-langs "ko,en" --skip-download --output "transcript_temp" "YOUTUBE_URL"
```

---

## Step 5: 텍스트 변환 및 후처리

### 방법 1 (youtube-transcript-api) 후처리

```python
def process_transcript(entries, include_timestamps=False):
    lines = []
    seen = set()

    for entry in entries:
        text = entry['text'].strip()
        # HTML 태그 제거
        import re
        text = re.sub(r'<[^>]+>', '', text)
        # HTML 엔티티 변환
        text = text.replace('&amp;', '&').replace('&gt;', '>').replace('&lt;', '<')
        text = text.replace('&#39;', "'").replace('&quot;', '"')

        if not text or text in seen:
            continue

        seen.add(text)

        if include_timestamps:
            start = entry['start']
            minutes = int(start // 60)
            seconds = int(start % 60)
            lines.append(f"[{minutes:02d}:{seconds:02d}] {text}")
        else:
            lines.append(text)

    return '\n'.join(lines)
```

### 방법 2 (yt-dlp VTT) 후처리

```python
import re

def vtt_to_text(vtt_file, include_timestamps=False):
    lines = []
    seen = set()

    with open(vtt_file, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if (not line
                or line.startswith('WEBVTT')
                or line.startswith('Kind:')
                or line.startswith('Language:')
                or '-->' in line):
                continue

            clean = re.sub(r'<[^>]+>', '', line)
            clean = clean.replace('&amp;', '&').replace('&gt;', '>').replace('&lt;', '<')

            if clean and clean not in seen:
                seen.add(clean)
                lines.append(clean)

    return '\n'.join(lines)
```

---

## Step 6: 저장

추출된 자막은 아래 경로에 저장한다:

```
/home/jay/workspace/memory/research/transcripts/
  └── YYYYMMDD_[영상제목-슬러그].txt
```

```python
import os
from datetime import datetime

def save_transcript(text, video_title, video_id):
    save_dir = "/home/jay/workspace/memory/research/transcripts"
    os.makedirs(save_dir, exist_ok=True)

    # 파일명 생성 (특수문자 제거)
    import re
    slug = re.sub(r'[^\w\s-]', '', video_title.lower())
    slug = re.sub(r'[\s_]+', '-', slug)[:50]
    date_str = datetime.now().strftime('%Y%m%d')
    filename = f"{date_str}_{slug}.txt"

    filepath = os.path.join(save_dir, filename)
    with open(filepath, 'w', encoding='utf-8') as f:
        f.write(text)

    return filepath
```

---

## Step 7: 요약 생성 (--summary 옵션)

`--summary` 옵션이 있을 때, 추출된 자막 텍스트를 바탕으로 아래 항목을 분석한다:

- 핵심 주제 (영상이 다루는 중심 내용)
- 주요 포인트 3~5개 (핵심 메시지, 데이터, 주장)
- 보험/금융 도메인 관련성이 있으면 규제, 상품, 시장 트렌드 항목 추가

---

## 출력 형식

```
## YouTube 자막 추출 결과

**영상 제목**: [제목]
**URL**: [URL]
**VIDEO ID**: [VIDEO_ID]
**언어**: 한국어 / 한국어 (자동 생성) / 영어
**자막 유형**: 수동 자막 / 자동 생성 자막
**저장 위치**: /home/jay/workspace/memory/research/transcripts/[파일명]

---

### 전체 텍스트

[자막 내용...]

---

### 요약 (--summary 옵션 사용 시)

**핵심 주제**: ...

**주요 포인트**:
- ...
- ...
- ...

**보험/금융 관련 인사이트** (해당 시):
- 규제/정책 변화: ...
- 상품/서비스 동향: ...
- 시장 트렌드: ...
```

---

## 에러 처리

### 자막 없음

```
자막을 찾을 수 없습니다.
- 해당 영상에 자막(수동/자동 생성)이 없거나 비활성화되어 있습니다.
- 비공개 영상이거나 지역 제한이 걸려 있을 수 있습니다.
- Whisper 로컬 전사는 무거운 작업(~1-10GB 모델)이므로, 별도 확인 후에만 진행합니다.
  진행하시겠습니까? (y/n)
```

### 비공개/지역 제한 영상

```
해당 영상에 접근할 수 없습니다.
원인: 비공개 영상, 지역 제한, 연령 제한 중 하나일 수 있습니다.
다른 URL을 제공해주세요.
```

### 자동 생성 자막 품질 안내

자동 생성 자막 사용 시 항상 안내한다:

```
주의: 자동 생성 자막을 사용했습니다. 오탈자, 고유명사 오류, 문장 경계 누락이 있을 수 있습니다.
중요한 내용은 원본 영상과 대조 확인을 권장합니다.
```

---

## 보험/금융 도메인 활용 사례

| 활용 목적 | 입력 | 출력 |
|-----------|------|------|
| 보험 설계사 교육 영상 분석 | 보험 연수원 유튜브 영상 URL | 자막 텍스트 → 교육 자료 초안 |
| 경쟁사 유튜브 채널 콘텐츠 분석 | 경쟁 보험사 영상 URL | 메시지 전략, 상품 강조점 정리 |
| 금융감독원 설명회 요약 | 금감원 공식 영상 URL | 규제 변화 핵심 포인트 추출 |
| 보험 상품 리뷰 영상 분석 | 유튜브 보험 비교 영상 URL | 시장 인사이트, 소비자 인식 정리 |

---

## 제약사항

- 비공개 영상, 지역 제한 영상은 추출 불가 (에러 안내)
- 자동 생성 자막은 오류 가능성 항상 고지
- 한국어 우선, 영어 대안 순서로 처리
- Whisper 로컬 전사는 범위 외. 자막이 없는 경우 사용자 명시적 확인 후에만 진행
- 이모지 사용 금지

---

## 빠른 참조

- **자막 저장 위치**: `/home/jay/workspace/memory/research/transcripts/`
- **의존성**: `youtube-transcript-api` (권장) 또는 `yt-dlp` (대안)
- **연계 스킬**: `/research-prompt` (리서치 분석), `/insight-extractor` (인사이트 추출)

---

**스킬 버전**: v1.0
**작성일**: 2026-04-12
**작성자**: 프레이야 (개발2팀 프론트엔드 전문가)
**출처**: michalparkola/tapestry-skills-for-claude-code (MIT 라이선스) 참조 후 커스텀
