feat(pipeline): YouTube Tab → PDF 자동 추출 파이프라인 초기 구현
- 5단계 파이프라인: 다운로드 → 프레임 추출 → 패턴 감지 → 중복 제거 → PDF 생성 - 3가지 패턴 지원: overlay, split, scroll - MSE 기반 픽셀 비교 프레임 중복 제거 - split 모드: 42% 크롭 + 밝기 필터 + Tab 라인 검증 - overlay 모드: 320x120 정규화 + 슬라이딩 윈도우 비교 - 프로젝트 문서 초기 작성 (architecture, tech-stack, STATUS, known-issues)
This commit is contained in:
29
.agent/references/STATUS.md
Normal file
29
.agent/references/STATUS.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Project Status
|
||||
|
||||
## 기능 현황
|
||||
|
||||
| 기능 | 상태 | 비고 |
|
||||
|------|------|------|
|
||||
| YouTube 다운로드 | ✅ 완료 | yt-dlp + 쿠키 인증 |
|
||||
| 프레임 추출 | ✅ 완료 | fps=2 기본값 |
|
||||
| 패턴 감지 (overlay) | ✅ 완료 | Tab 라인 검증 포함 |
|
||||
| 패턴 감지 (split) | ✅ 완료 | 밝기 기준 엄격화 |
|
||||
| 패턴 감지 (scroll) | ✅ 완료 | 기본 폴백 |
|
||||
| MSE 기반 중복 제거 | ✅ 완료 | 히스토그램 → MSE 전환 |
|
||||
| 오버레이 정규화 비교 | ✅ 완료 | 320×120 정규화 + 슬라이딩 윈도우 |
|
||||
| PDF/PNG 생성 | ✅ 완료 | A4 + 롱 이미지 |
|
||||
|
||||
## 최근 변경
|
||||
|
||||
| 날짜 | 변경 내용 |
|
||||
|------|-----------|
|
||||
| 2026-03-24 | 패턴 감지 고도화: overlay→split→scroll 우선순위 |
|
||||
| 2026-03-24 | 히스토그램 비교 → MSE 픽셀 비교로 전환 |
|
||||
| 2026-03-24 | split 모드: 42% 크롭 + 밝기 필터 + Tab 라인 검증 |
|
||||
| 2026-03-24 | overlay 모드: 정규화 + 슬라이딩 윈도우 중복 제거 |
|
||||
| 2026-03-24 | split 감지 조건 엄격화 (top>180, bottom<100) |
|
||||
|
||||
## 알려진 제한사항
|
||||
|
||||
- 오버레이형 영상(空奏列車)에서 추출 프레임 수가 아직 많을 수 있음 (MSE 임계값 추가 튜닝 필요)
|
||||
- 영상 내 Tab이 반복되는 곡은 실제 고유 프레임 수가 적음 (正常 동작)
|
||||
58
.agent/references/architecture.md
Normal file
58
.agent/references/architecture.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Architecture
|
||||
|
||||
> YouTube 기타 TAB 영상 → PDF 자동 추출 파이프라인
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
YouTube 기타 TAB 튜토리얼 영상을 입력받아, 컴퓨터 비전으로 TAB 악보 영역만 추출하고 중복을 제거하여 깨끗한 PDF/PNG로 출력하는 CLI 도구.
|
||||
|
||||
## 디렉토리 구조
|
||||
|
||||
```
|
||||
project-root/
|
||||
├── youtube_tab_to_pdf.py # 메인 파이프라인 (단일 파일)
|
||||
├── .env # yt-dlp 쿠키 경로 설정
|
||||
├── .gitignore
|
||||
├── output/ # 생성된 PDF/PNG/디버그 프레임
|
||||
├── .agent/ # AI 에이전트 설정
|
||||
│ ├── AGENT.md
|
||||
│ ├── references/ # 프로젝트 문서
|
||||
│ └── workflows/ # 워크플로우 정의
|
||||
└── docs/devlog/ # 개발 로그
|
||||
```
|
||||
|
||||
## 핵심 모듈 (youtube_tab_to_pdf.py 내부)
|
||||
|
||||
| 모듈 | 역할 | 비고 |
|
||||
|------|------|------|
|
||||
| `download_video()` | yt-dlp로 영상 다운로드 | .env의 쿠키 경로 사용 |
|
||||
| `extract_frames()` | 영상 → 프레임 분리 (fps=2) | OpenCV VideoCapture |
|
||||
| `detect_pattern()` | 영상 패턴 분류 (overlay→split→scroll) | 우선순위: overlay > split > scroll |
|
||||
| `_detect_tab_overlay()` | 흰 박스 + Tab 라인 검출 | HoughLinesP 기반 |
|
||||
| `_detect_split_screen()` | 상단 Tab + 하단 핸드캠 분할 검출 | 밝기 기준 (top>180, bottom<100) |
|
||||
| `_has_tab_lines()` | 수평 Staff 라인 존재 여부 | 모폴로지 + HoughLinesP |
|
||||
| `compare_frames()` | MSE 기반 프레임 유사도 비교 | 320px 리사이즈, factor 8 |
|
||||
| `extract_unique_*()` | 패턴별 고유 프레임 추출 | scroll/overlay/split 3종 |
|
||||
| `generate_pdf()` | 프레임 → A4 PDF + 롱 이미지 생성 | ReportLab + Pillow |
|
||||
|
||||
## 데이터 흐름
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[YouTube URL] --> B[yt-dlp 다운로드]
|
||||
B --> C[프레임 추출<br>fps=2]
|
||||
C --> D{패턴 감지}
|
||||
D -->|overlay| E1[Tab 오버레이 크롭<br>+ 정규화 비교]
|
||||
D -->|split| E2[상단 42% 크롭<br>+ 밝기/라인 필터]
|
||||
D -->|scroll| E3[상단 크롭]
|
||||
E1 --> F[중복 제거<br>MSE 비교]
|
||||
E2 --> F
|
||||
E3 --> F
|
||||
F --> G[PDF + PNG 생성]
|
||||
```
|
||||
|
||||
## 패턴 감지 우선순위
|
||||
|
||||
1. **overlay** — 화면 위에 떠 있는 Tab 박스 (가장 구체적)
|
||||
2. **split** — 상단 Tab 용지 + 하단 핸드캠 (엄격한 밝기 기준)
|
||||
3. **scroll** — 상단 크롭 (기본 폴백)
|
||||
45
.agent/references/conventions.md
Normal file
45
.agent/references/conventions.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Coding Conventions
|
||||
|
||||
> AI 에이전트는 코드를 작성하기 전 이 컨벤션을 확인합니다.
|
||||
|
||||
## 네이밍
|
||||
|
||||
| 대상 | 규칙 | 예시 |
|
||||
|------|------|------|
|
||||
| 변수/함수 | camelCase | `getUserData()` |
|
||||
| 클래스 | PascalCase | `UserService` |
|
||||
| 상수 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
|
||||
| 파일명 | kebab-case | `user-service.js` |
|
||||
| CSS 클래스 | kebab-case | `.nav-header` |
|
||||
|
||||
## 코드 스타일
|
||||
|
||||
- 들여쓰기: (2 spaces / 4 spaces / tab)
|
||||
- 세미콜론: (사용 / 미사용)
|
||||
- 따옴표: (single / double)
|
||||
- 줄바꿈: LF (Unix style)
|
||||
|
||||
## 커밋 메시지
|
||||
|
||||
```
|
||||
<type>(<scope>): <description>
|
||||
|
||||
type: feat|fix|refactor|test|docs|chore|ci|infra
|
||||
scope: (선택)
|
||||
```
|
||||
|
||||
**예시:**
|
||||
- `feat(server): add WebSocket reconnection logic`
|
||||
- `fix(frontend): resolve button overlap on mobile`
|
||||
- `docs: update API documentation`
|
||||
|
||||
## 주석
|
||||
|
||||
- 한국어/영어 혼용 가능
|
||||
- TODO 주석: `// TODO: 설명` 형식
|
||||
- 복잡한 로직에는 반드시 WHY(왜) 주석 추가
|
||||
|
||||
## 테스트
|
||||
|
||||
- 테스트 파일 위치: (예: `__tests__/` 또는 `*.test.js`)
|
||||
- 테스트 네이밍: `should [expected behavior] when [condition]`
|
||||
57
.agent/references/known-issues.md
Normal file
57
.agent/references/known-issues.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Known Issues & Lessons Learned
|
||||
|
||||
> **이 파일은 SSOT(Single Source of Truth)입니다.**
|
||||
> 디버깅이나 구현 전에 **반드시** 이 파일을 확인하세요.
|
||||
> 세션 종료 시 새로 발견된 이슈를 이 파일에 추가합니다.
|
||||
|
||||
---
|
||||
|
||||
## 포맷
|
||||
|
||||
각 항목은 아래 형식을 따릅니다:
|
||||
|
||||
```markdown
|
||||
### [날짜] [키워드] — 한줄 요약
|
||||
- **증상**: 무엇이 잘못되었는가
|
||||
- **원인**: 근본 원인
|
||||
- **해결**: 올바른 해결 방법
|
||||
- **주의**: 재발 방지를 위한 교훈
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 공통 이슈
|
||||
|
||||
### [2026-03-08] PowerShell curl — Invoke-WebRequest 충돌
|
||||
- **증상**: `curl` 명령이 예상과 다른 응답 형식을 반환
|
||||
- **원인**: PowerShell에서 `curl`은 `Invoke-WebRequest`의 별칭
|
||||
- **해결**: **`curl.exe`**를 명시적으로 사용
|
||||
- **주의**: HTTP 관련 모든 명령에서 `curl.exe` 사용 필수
|
||||
|
||||
### [2026-03-08] PowerShell npm — 실행 정책 오류
|
||||
- **증상**: `npm run` 명령이 `실행 정책` 관련 오류로 실패
|
||||
- **원인**: PowerShell 스크립트 실행 정책이 제한적으로 설정됨
|
||||
- **해결**: `cmd /c npm run dev` 형식으로 cmd를 통해 실행
|
||||
- **주의**: npm 관련 명령은 항상 `cmd /c` 접두어 사용 권장
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트별 이슈
|
||||
|
||||
### [2026-03-24] 히스토그램 비교 — Tab 프레임 구분 불가
|
||||
- **증상**: 서로 다른 Tab 페이지가 "동일"로 판정되어 프레임 수가 과소 추출
|
||||
- **원인**: 히스토그램 상관관계는 밝기 분포만 비교 — Tab 용지 배경이 같으면 다른 내용도 동일로 판정
|
||||
- **해결**: MSE 픽셀 비교로 전환 (320px 리사이즈, factor 8)
|
||||
- **주의**: MSE scaling factor는 영상 타입에 따라 다르게 동작할 수 있음
|
||||
|
||||
### [2026-03-24] split 감지 — 밝은 배경 오분류
|
||||
- **증상**: 밝은 배경 기타 연주 영상(空奏列車)이 split으로 오분류
|
||||
- **원인**: 흰 셔츠/밝은 배경이 상단 밝기 조건 통과, 기타줄이 _has_tab_lines 통과
|
||||
- **해결**: split 검증 강화 (top>180, bottom<100, diff>80, 4+ lines) + overlay 우선 검사
|
||||
- **주의**: 패턴 감지 순서는 반드시 overlay → split → scroll 유지
|
||||
|
||||
### [2026-03-24] overlay 크롭 크기 불일치
|
||||
- **증상**: overlay 프레임 비교 시 모든 프레임이 "다르다"로 판정 (1000+개 추출)
|
||||
- **원인**: _detect_tab_overlay가 프레임마다 다른 크기의 바운딩박스 반환 (69~360px)
|
||||
- **해결**: 320×120 흰색 캔버스에 정규화 후 비교 + 슬라이딩 윈도우(5프레임)
|
||||
- **주의**: overlay 프레임 수 최적화는 아직 진행 중 (추가 튜닝 필요)
|
||||
38
.agent/references/tech-stack.md
Normal file
38
.agent/references/tech-stack.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Tech Stack
|
||||
|
||||
> AI 에이전트는 구현 전 이 문서를 확인하여 올바른 기술/버전을 사용합니다.
|
||||
|
||||
## 언어 & 런타임
|
||||
|
||||
| 항목 | 버전 | 비고 |
|
||||
|------|------|------|
|
||||
| Python | 3.x | `C:\ProgramData\miniforge3\envs\score\python.exe` |
|
||||
|
||||
## 주요 라이브러리
|
||||
|
||||
| 항목 | 용도 |
|
||||
|------|------|
|
||||
| OpenCV (cv2) | 프레임 추출, 이미지 처리, HoughLinesP 라인 검출 |
|
||||
| NumPy | 배열 연산, 밝기 계산, MSE 비교 |
|
||||
| yt-dlp | YouTube 영상 다운로드 |
|
||||
| Pillow (PIL) | 이미지 변환 (BGR→RGB), 롱 이미지 생성 |
|
||||
| ReportLab | PDF 생성 (A4 레이아웃) |
|
||||
| python-dotenv | .env 파일 로딩 (쿠키 경로) |
|
||||
|
||||
## 패키지 관리
|
||||
|
||||
- 패키지 매니저: conda (miniforge3, `score` 환경)
|
||||
- 가상환경: `C:\ProgramData\miniforge3\envs\score`
|
||||
|
||||
## 개발 도구
|
||||
|
||||
| 도구 | 명령어 |
|
||||
|------|--------|
|
||||
| 실행 | `C:\ProgramData\miniforge3\envs\score\python.exe youtube_tab_to_pdf.py <URL>` |
|
||||
| 디버그 실행 | 위 명령어 + `--debug` |
|
||||
|
||||
## 환경 변수
|
||||
|
||||
| 변수명 | 용도 | 설정 위치 |
|
||||
|--------|------|-----------|
|
||||
| COOKIE_PATH | yt-dlp 쿠키 파일 경로 | `.env` |
|
||||
Reference in New Issue
Block a user