update plan

This commit is contained in:
Kyush 2026-06-06 18:27:03 +09:00
commit a492fc6887

View file

@ -2,7 +2,11 @@
## 1. 목표
Turbo Download Manager(v3.m3) 확장 프로그램의 m3u8 탐지·병합 로직을 참고하여, Tampermonkey/Violentmonkey 등에서 실행 가능한 **싱글 파일 UserScript**(`m3u8-download.user.js`)를 구현한다.
Turbo Download Manager(v3.m3) 확장 프로그램의 m3u8 탐지·병합 로직을 참고하여, Tampermonkey/Violentmonkey 등에서 실행 가능한 UserScript를 구현한다.
- **개발 시:** `src/` 폴더 아래 모듈화된 구조로 작성하여 유지보수성 확보
- **빌드 시:** esbuild로 단일 파일로 번들링 후, 파일 상단에 UserScript 메타데이터 주입
- **출력:** `dist/m3u8-download.user.js` (minify 안 된 가독성 있는 번들 파일)
---
@ -62,45 +66,59 @@ Turbo Download Manager(v3.m3) 확장 프로그램의 m3u8 탐지·병합 로직
| iframe 내부 요청 탐지 | `content_scripts` + `all_frames: true` | `@all-frames true` 필요 | iframe별 독립 후킹 + `unsafeWindow` 처리 |
| 크로스 오리진 iframe | `webRequest`로 전역 가로챔 | ❌ `unsafeWindow` 접근 불가 | 크로스 오리진 iframe은 탐지 불가 (브라우저 보안 정책) |
### 3.2 단일 파일 구조
### 3.2 프로젝트 디렉토리 구조
```
m3u8-download.user.js
├── // ==UserScript== header block
├── m3u8-parser 라이브러리 인라인 삽입 (minified)
├── 유틸리티 함수
│ ├── resolveUri(root, rel) // 상대 URI → 절대 URI
│ ├── decryptSegment(key, data) // AES-CBC 복호화
│ └── guessFilename(url, mime) // URL에서 파일명 추출
├── m3u8 탐지 모듈
│ ├── xhrIntercept() // XMLHttpRequest.open 패치
│ ├── fetchIntercept() // fetch() 패치 (옵션)
│ └── domMonitor() // <video>/<audio> source 추적
├── m3u8 처리 모듈
│ ├── parseM3U8(url) // 플레이리스트 파싱
│ ├── resolveMasterPlaylist(...) // 마스터 플레이리스트 처리
│ ├── fetchSegments(...) // 세그먼트 다운로드
│ └── mergeAndDownload(...) // 병합 + 다운로드
├── UI 모듈
│ ├── createPanel() // 페이지 상단 UI 패널
│ ├── showStatus(...) // 진행률 표시
│ └── showPlaylistSelector(...) // 해상도 선택 (마스터 플레이리스트)
└── 초기화 코드
├── 탐지 모듈 활성화
└── UI 패널 생성/숨김 토글
m3u8-monkey-script/
├── package.json
├── esbuild.config.mjs # esbuild 빌드 설정
├── metadata.user.js # UserScript 메타데이터 블록 (banner로 주입)
├── src/
│ ├── index.ts # 진입점: 초기화, 모듈 조립
│ ├── logger.ts # 로깅 유틸리티 (unsafeWindow.console 기반)
│ ├── utils/
│ │ ├── uri.ts # resolveUri(root, rel) 등 URI 유틸
│ │ ├── crypto.ts # decryptSegment(key, data) AES-CBC 복호화
│ │ └── filename.ts # guessFilename(url, mime) 파일명 추출
│ ├── detection/
│ │ ├── xhr-intercept.ts # XMLHttpRequest.open/send 패치
│ │ ├── fetch-intercept.ts # fetch() 패치
│ │ └── dom-monitor.ts # <video>/<audio> source 추적
│ ├── parser/
│ │ ├── m3u8-parse.ts # parseM3U8(url), resolveMasterPlaylist
│ │ └── key-fetch.ts # 암호화 키 fetch + 검증 + 캐싱
│ ├── downloader/
│ │ ├── segment-fetch.ts # fetchSegments(...) 세그먼트 다운로드
│ │ └── merge.ts # mergeAndDownload(...) 병합 + 다운로드
│ └── ui/
│ ├── panel.ts # createPanel() 페이지 상단 UI 패널
│ ├── progress.ts # showStatus(...) 진행률 표시
│ └── selector.ts # showPlaylistSelector(...) 해상도 선택
├── dist/
│ └── m3u8-download.user.js # 빌드 결과 (banner + 번들 코드)
└── plans/
└── implementation-plan.md
```
**빌드 흐름:**
1. `src/index.ts`를 entry point로 esbuild 실행
2. `--bundle`로 모든 모듈 + 의존성(m3u8-parser)를 단일 파일로 번들
3. `--banner``metadata.user.js`의 메타데이터 블록을 파일 상단에 주입
4. `--format=iife`로 Tampermonkey 호환 IIFE 생성
5. minify 미적용 (`--minify` 생략)하여 가독성 유지
6. 결과물 `dist/m3u8-download.user.js` 출력
### 3.3 파일 크기 예상
| 구성 요소 | 예상 크기 |
|-----------|-----------|
| UserScript header | ~1KB |
| m3u8-parser (minified) | ~30-40KB |
| UserScript header (banner) | ~1KB |
| m3u8-parser (bundled) | ~30-40KB |
| 탐지 모듈 | ~5KB |
| 파싱/다운로드/병합 로직 | ~10KB |
| UI 모듈 | ~5KB |
| 로깅 유틸리티 | ~1KB |
| **총계** | **~52-62KB** |
| **총계 (dist)** | **~52-62KB** |
### 3.4 로깅 전략
@ -456,25 +474,28 @@ GM_xmlhttpRequest({
- **videojs/m3u8-parser** (v4.4.0)
- Turbo Download Manager에서 사용 중인 동일한 버전
- Apache-2.0 라이선스
- Turbo DM의 `data/add/m3u8-parser.js` (~39KB)에서 인라인 삽입
- npm 패키지로 설치하여 번들러에 위임
### 5.2 통합 방식
UserScript 내부에 minified 버전의 m3u8-parser를 직접 삽입:
```javascript
// ==UserScript==
// ...header...
// ==/UserScript==
npm 의존성으로 설치하면 esbuild가 자동으로 번들에 포함:
/* m3u8-parser v4.4.0 - Apache-2.0 */
// [minified source code here]
(function() {
'use strict';
// main script logic
})();
```bash
pnpm add m3u8-parser@4.4.0
```
`src/parser/m3u8-parse.ts`에서 import:
```typescript
import * as m3u8Parser from 'm3u8-parser';
function parseM3U8(url: string) {
const parser = new m3u8Parser.Parser();
// ...
}
```
esbuild가 번들링 시 m3u8-parser의 모든 의존성(mp4box 등)을 자동으로 포함하여 단일 파일로 생성.
---
## 6. 구현 단계 (작업 순서)