ytcollector 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: ytcollector
3
+ Version: 1.0.3
4
+ Summary: SBS 데이터셋 수집기
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: yt-dlp>=2024.1.0
8
+ Requires-Dist: ultralytics>=8.1.0
9
+ Requires-Dist: opencv-python>=4.9.0
10
+ Requires-Dist: tqdm>=4.66.0
11
+ Requires-Dist: imageio-ffmpeg>=0.4.9
12
+
13
+ # Downloader: SBS 데이터셋 수집기
14
+
15
+ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을 수집하고 YOLO-World로 검증하는 자동화 파이프라인입니다.
16
+
17
+ ## 1. 설치 및 시작
18
+
19
+ **필수 요구사항:**
20
+ - Python 3.8 이상
21
+ - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
22
+
23
+ **설치:**
24
+ ```bash
25
+ cd 260203_sbs_dataset
26
+ pip install -e .
27
+ ```
28
+
29
+ **프로젝트 초기화 (최초 1회):**
30
+ 필요한 폴더(`urls/`, `video/`)를 생성합니다.
31
+ ```bash
32
+ ytcollector init
33
+ ```
34
+
35
+ ---
36
+
37
+ ## 2. URL 관리
38
+
39
+ 다운로드할 YouTube 영상 리스트는 텍스트 파일로 관리합니다.
40
+ **파일 위치:** `urls/<태스크이름>/youtube_url.txt` (예: `urls/face/youtube_url.txt`)
41
+
42
+ **파일 형식 (CSV 스타일):**
43
+ ```text
44
+ task_type,url,timestamp_min,timestamp_sec,description
45
+ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
46
+ ```
47
+ * `init` 명령 실행 시 샘플 내용이 포함된 파일이 자동 생성됩니다.
48
+
49
+ ---
50
+
51
+ ## 3. 사용법 (다운로드 & 검증)
52
+
53
+ 이 프로그램은 **다운로드 → YOLO 검증 → (성공 시) 저장** 순서로 작동합니다. 타겟 객체가 없으면 자동으로 삭제됩니다.
54
+
55
+ ### 기본 다운로드 (순차 실행)
56
+ 안정적으로 하나씩 다운로드하고 검증합니다.
57
+ ```bash
58
+ ytcollector download --task face
59
+ ```
60
+
61
+ ### 🚀 Fast 모드 (병렬 다운로드)
62
+ 대량의 영상을 빠르게 수집할 때 사용합니다. (4개 스레드 동시 실행)
63
+ ```bash
64
+ ytcollector download --task face --fast
65
+ ```
66
+ * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
67
+ * **에러 무시**: 중간에 에러가 나도 멈추지 않고 다음 영상으로 넘어갑니다.
68
+
69
+ ### 저장 파일 규칙
70
+ * **파일명**: `face_0001.mp4`, `face_0002.mp4` ... (순차 번호)
71
+ * **중복 방지**: `download_history.json`에 기록하여, 이미 받은 URL은 중복해서 받지 않습니다.
72
+
73
+ ---
74
+
75
+ ## 4. NAS / 네트워크 저장 설정
76
+
77
+ 영상을 로컬이 아닌 NAS에 저장하려면 설정을 수정하세요.
78
+ OS(Windows/Mac)를 자동 감지하여 적절한 경로를 사용합니다.
79
+
80
+ **설정 파일 수정:** `ytcollector/config.py`
81
+ ```python
82
+ # Windows 예시
83
+ NAS_PATH_WINDOWS = r"\\NAS_SERVER_IP\Data\Private Dataset\..."
84
+
85
+ # Mac 예시 (/Volumes로 마운트된 경로 확인 필요)
86
+ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
87
+ ```
88
+
89
+ ---
90
+
91
+ ## 5. 전체 명령어 목록
92
+
93
+ | 명령어 | 설명 | 예시 |
94
+ |--------|------|------|
95
+ | `init` | 프로젝트 초기화 | `ytcollector init` |
96
+ | `download` | 텍스트 파일 목록 대량 다운로드 | `ytcollector download --task face --fast` |
97
+ | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face ...` |
98
+ | `verify` | 수동 YOLO 검증 (기존 파일) | `ytcollector verify --task face` |
99
+ | `list-tasks` | 지원하는 태스크 목록 확인 | `ytcollector list-tasks` |
100
+
101
+ ## 6. 문제 해결
102
+ * **검증 실패가 너무 많음**: `config.py`에서 `CONFIDENCE_THRESHOLD` (기본 0.25) 값을 낮춰보세요.
103
+ * **IP 차단**: Fast 모드 사용 중 YouTube 접근이 막히면 잠시 기다린 후 다시 시도하거나 딜레이 시간을 늘리세요.
@@ -0,0 +1,91 @@
1
+ # Downloader: SBS 데이터셋 수집기
2
+
3
+ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을 수집하고 YOLO-World로 검증하는 자동화 파이프라인입니다.
4
+
5
+ ## 1. 설치 및 시작
6
+
7
+ **필수 요구사항:**
8
+ - Python 3.8 이상
9
+ - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
10
+
11
+ **설치:**
12
+ ```bash
13
+ cd 260203_sbs_dataset
14
+ pip install -e .
15
+ ```
16
+
17
+ **프로젝트 초기화 (최초 1회):**
18
+ 필요한 폴더(`urls/`, `video/`)를 생성합니다.
19
+ ```bash
20
+ ytcollector init
21
+ ```
22
+
23
+ ---
24
+
25
+ ## 2. URL 관리
26
+
27
+ 다운로드할 YouTube 영상 리스트는 텍스트 파일로 관리합니다.
28
+ **파일 위치:** `urls/<태스크이름>/youtube_url.txt` (예: `urls/face/youtube_url.txt`)
29
+
30
+ **파일 형식 (CSV 스타일):**
31
+ ```text
32
+ task_type,url,timestamp_min,timestamp_sec,description
33
+ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
34
+ ```
35
+ * `init` 명령 실행 시 샘플 내용이 포함된 파일이 자동 생성됩니다.
36
+
37
+ ---
38
+
39
+ ## 3. 사용법 (다운로드 & 검증)
40
+
41
+ 이 프로그램은 **다운로드 → YOLO 검증 → (성공 시) 저장** 순서로 작동합니다. 타겟 객체가 없으면 자동으로 삭제됩니다.
42
+
43
+ ### 기본 다운로드 (순차 실행)
44
+ 안정적으로 하나씩 다운로드하고 검증합니다.
45
+ ```bash
46
+ ytcollector download --task face
47
+ ```
48
+
49
+ ### 🚀 Fast 모드 (병렬 다운로드)
50
+ 대량의 영상을 빠르게 수집할 때 사용합니다. (4개 스레드 동시 실행)
51
+ ```bash
52
+ ytcollector download --task face --fast
53
+ ```
54
+ * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
55
+ * **에러 무시**: 중간에 에러가 나도 멈추지 않고 다음 영상으로 넘어갑니다.
56
+
57
+ ### 저장 파일 규칙
58
+ * **파일명**: `face_0001.mp4`, `face_0002.mp4` ... (순차 번호)
59
+ * **중복 방지**: `download_history.json`에 기록하여, 이미 받은 URL은 중복해서 받지 않습니다.
60
+
61
+ ---
62
+
63
+ ## 4. NAS / 네트워크 저장 설정
64
+
65
+ 영상을 로컬이 아닌 NAS에 저장하려면 설정을 수정하세요.
66
+ OS(Windows/Mac)를 자동 감지하여 적절한 경로를 사용합니다.
67
+
68
+ **설정 파일 수정:** `ytcollector/config.py`
69
+ ```python
70
+ # Windows 예시
71
+ NAS_PATH_WINDOWS = r"\\NAS_SERVER_IP\Data\Private Dataset\..."
72
+
73
+ # Mac 예시 (/Volumes로 마운트된 경로 확인 필요)
74
+ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
75
+ ```
76
+
77
+ ---
78
+
79
+ ## 5. 전체 명령어 목록
80
+
81
+ | 명령어 | 설명 | 예시 |
82
+ |--------|------|------|
83
+ | `init` | 프로젝트 초기화 | `ytcollector init` |
84
+ | `download` | 텍스트 파일 목록 대량 다운로드 | `ytcollector download --task face --fast` |
85
+ | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face ...` |
86
+ | `verify` | 수동 YOLO 검증 (기존 파일) | `ytcollector verify --task face` |
87
+ | `list-tasks` | 지원하는 태스크 목록 확인 | `ytcollector list-tasks` |
88
+
89
+ ## 6. 문제 해결
90
+ * **검증 실패가 너무 많음**: `config.py`에서 `CONFIDENCE_THRESHOLD` (기본 0.25) 값을 낮춰보세요.
91
+ * **IP 차단**: Fast 모드 사용 중 YouTube 접근이 막히면 잠시 기다린 후 다시 시도하거나 딜레이 시간을 늘리세요.
@@ -0,0 +1,39 @@
1
+ """
2
+ SBS Dataset Collection Pipeline - Settings
3
+ """
4
+ from pathlib import Path
5
+
6
+ # Base paths
7
+ BASE_DIR = Path(__file__).parent.parent
8
+ DATA_DIR = BASE_DIR / "data"
9
+ URLS_DIR = DATA_DIR / "urls"
10
+ VIDEOS_DIR = DATA_DIR / "videos"
11
+ CLIPS_DIR = DATA_DIR / "clips"
12
+ OUTPUTS_DIR = BASE_DIR / "outputs"
13
+ REPORTS_DIR = OUTPUTS_DIR / "reports"
14
+
15
+ # Video settings
16
+ CLIP_DURATION_BEFORE = 90 # 1분 30초 (초 단위)
17
+ CLIP_DURATION_AFTER = 90 # 1분 30초 (초 단위)
18
+ MAX_CLIP_DURATION = 180 # 최대 3분
19
+
20
+ # Download settings
21
+ VIDEO_FORMAT = "best[ext=mp4]/best"
22
+ DOWNLOAD_RETRIES = 3
23
+
24
+ # YOLO-World settings
25
+ YOLO_MODEL = "yolov8s-worldv2.pt"
26
+ CONFIDENCE_THRESHOLD = 0.25
27
+ FRAME_SAMPLE_RATE = 30 # 매 30프레임마다 샘플링 (약 1초)
28
+
29
+ # Task-specific class prompts
30
+ TASK_CLASSES = {
31
+ "face": ["human face", "person face", "close-up face"],
32
+ "license_plate": ["car license plate", "vehicle license plate", "korean license plate"],
33
+ "tattoo": ["tattoo", "body tattoo", "skin tattoo"],
34
+ "text": ["text on screen", "subtitle", "korean text", "caption"]
35
+ }
36
+
37
+ # Create directories if not exist
38
+ for dir_path in [URLS_DIR, VIDEOS_DIR, CLIPS_DIR, REPORTS_DIR]:
39
+ dir_path.mkdir(parents=True, exist_ok=True)
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ytcollector"
7
+ version = "1.0.3"
8
+ description = "SBS 데이터셋 수집기"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ dependencies = [
12
+ "yt-dlp>=2024.1.0",
13
+ "ultralytics>=8.1.0",
14
+ "opencv-python>=4.9.0",
15
+ "tqdm>=4.66.0",
16
+ "imageio-ffmpeg>=0.4.9",
17
+ ]
18
+
19
+ [project.scripts]
20
+ ytcollector = "ytcollector.cli:main"
21
+
22
+ [tool.setuptools.packages.find]
23
+ where = ["."]
24
+ include = ["ytcollector*", "config*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,14 @@
1
+ """
2
+ SBS Dataset Collector - YouTube 영상 수집 및 YOLO-World 검증 파이프라인
3
+ """
4
+ from pathlib import Path
5
+
6
+ __version__ = "1.0.3"
7
+ __author__ = "SBS Dataset Team"
8
+
9
+ # Package root directory
10
+ PACKAGE_DIR = Path(__file__).parent
11
+
12
+ # Default data directories (can be overridden)
13
+ DEFAULT_DATA_DIR = Path.cwd() / "data"
14
+ DEFAULT_OUTPUT_DIR = Path.cwd() / "outputs"
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ SBS Dataset Collector CLI (Updated)
4
+ """
5
+ import argparse
6
+ import logging
7
+ from pathlib import Path
8
+
9
+ # Package import modified to 'downloader'
10
+ from .config import TASK_CLASSES, VALID_TASKS, get_paths
11
+ from .utils import ensure_dir, get_url_file_path
12
+
13
+ logging.basicConfig(
14
+ level=logging.INFO,
15
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
16
+ )
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ def init_project(args):
21
+ """프로젝트 디렉토리 초기화"""
22
+ base_dir = Path(args.dir) if args.dir else Path.cwd()
23
+
24
+ # 1. 태스크별 폴더 및 youtube_url.txt 생성
25
+ for task in VALID_TASKS:
26
+ # get_url_file_path 내부에서 ensure_dir 호출로 폴더 생성됨
27
+ txt_path = get_url_file_path(base_dir, task)
28
+
29
+ if not txt_path.exists():
30
+ txt_path.write_text(
31
+ "task_type,url,timestamp_min,timestamp_sec,description\n"
32
+ f"{task},https://www.youtube.com/watch?v=EXAMPLE,2,30,샘플\n",
33
+ encoding='utf-8'
34
+ )
35
+
36
+ # 2. config.py의 get_paths 로직에 따른 폴더들 생성 확인
37
+ paths = get_paths(base_dir)
38
+ ensure_dir(paths['outputs'])
39
+
40
+ print(f"✓ Project initialized at: {base_dir}")
41
+ print(f" - Add URLs to: urls/<task>/youtube_url.txt")
42
+ print(f" - Videos will be saved to configured OUTPUT_DIR (or video/ folder)")
43
+
44
+
45
+ def run_download(args):
46
+ """TXT 파일에서 영상 다운로드"""
47
+ from .downloader import download_from_txt # Changed function name
48
+
49
+ base_dir = Path(args.dir) if args.dir else Path.cwd()
50
+
51
+ # 파일 경로: video/{task}/youtube_url.txt
52
+ txt_file = get_url_file_path(base_dir, args.task)
53
+
54
+ if not txt_file.exists():
55
+ logger.error(f"URL file not found: {txt_file}")
56
+ logger.info("Run 'downloader init' first to create project structure")
57
+ return
58
+
59
+ logger.info(f"Starting{' fast' if args.fast else ''} download for task: {args.task}")
60
+
61
+ if args.fast:
62
+ from .downloader import download_from_txt_parallel
63
+ results = download_from_txt_parallel(txt_file, args.task, base_dir)
64
+ else:
65
+ results = download_from_txt(txt_file, args.task, base_dir)
66
+
67
+ success_count = sum(1 for r in results if r.get('success'))
68
+ print(f"✓ Download complete: {success_count}/{len(results)} successful")
69
+
70
+
71
+ def run_download_single(args):
72
+ """단일 URL 다운로드"""
73
+ from .downloader import VideoDownloader
74
+
75
+ base_dir = Path(args.dir) if args.dir else Path.cwd()
76
+ downloader = VideoDownloader(args.task, base_dir)
77
+
78
+ try:
79
+ output_path, metadata = downloader.download_clip_at_timestamp(
80
+ url=args.url,
81
+ timestamp_min=args.timestamp_min,
82
+ timestamp_sec=args.timestamp_sec
83
+ )
84
+ status = "Cached" if metadata.get('cached') else "Downloaded"
85
+ print(f"✓ {status}: {output_path}")
86
+ if not metadata.get('cached'):
87
+ print(f" Clip duration: {metadata['clip_duration']}s")
88
+
89
+ except Exception as e:
90
+ logger.error(f"Download failed: {e}")
91
+
92
+
93
+ def run_verify(args):
94
+ """클립 영상 검증"""
95
+ from .verifier import verify_clip, batch_verify
96
+
97
+ base_dir = Path(args.dir) if args.dir else Path.cwd()
98
+
99
+ if args.video:
100
+ video_path = Path(args.video)
101
+ result = verify_clip(video_path, args.task, base_dir)
102
+ print_verification_result(result)
103
+ else:
104
+ # 폴더 경로: video/{task}/
105
+ clips_dir = base_dir / "video" / args.task
106
+ if not clips_dir.exists():
107
+ logger.error(f"Video directory not found: {clips_dir}")
108
+ return
109
+
110
+ results = batch_verify(clips_dir, args.task, base_dir)
111
+ valid_count = sum(1 for r in results if r.get('is_valid'))
112
+ print(f"✓ Verification complete: {valid_count}/{len(results)} valid")
113
+
114
+
115
+ def run_pipeline(args):
116
+ """다운로드 + 검증 전체 파이프라인"""
117
+ print(f"=== Starting pipeline for task: {args.task} ===")
118
+
119
+ run_download(args)
120
+
121
+ if args.verify:
122
+ print("\n--- Running verification ---")
123
+ run_verify(args)
124
+
125
+ print("=== Pipeline complete ===")
126
+
127
+
128
+ def print_verification_result(result: dict):
129
+ """검증 결과 출력"""
130
+ summary = result.get('summary', {})
131
+
132
+ print("\n" + "="*50)
133
+ print(f"Video: {Path(result['video_path']).name}")
134
+ print(f"Task: {result['task_type']}")
135
+ print(f"Classes: {result['classes']}")
136
+ print("-"*50)
137
+ print(f"Duration: {summary.get('duration_sec', 0):.1f}s")
138
+ print(f"Frames with detection: {summary.get('frames_with_detection', 0)}")
139
+ print(f"Detection rate: {summary.get('detection_rate', 0):.1%}")
140
+ print(f"Valid: {'✓ YES' if result.get('is_valid') else '✗ NO'}")
141
+ print("="*50)
142
+
143
+
144
+ def list_tasks(args):
145
+ """태스크 목록 출력"""
146
+ print("\nAvailable Tasks and YOLO-World Classes:")
147
+ print("-" * 50)
148
+ for task, classes in TASK_CLASSES.items():
149
+ print(f"\n{task}:")
150
+ for cls in classes:
151
+ print(f" - {cls}")
152
+
153
+
154
+ def main():
155
+ parser = argparse.ArgumentParser(
156
+ description='Downloader - SBS Dataset Collector',
157
+ formatter_class=argparse.RawDescriptionHelpFormatter,
158
+ epilog="""
159
+ Examples:
160
+ downloader init # 프로젝트 초기화
161
+ downloader download --task face # 텍스트 파일에서 다운로드
162
+ downloader verify --task face # YOLO 검증
163
+ """
164
+ )
165
+
166
+ parser.add_argument('--dir', '-d', help='Project directory (default: current)')
167
+
168
+ subparsers = parser.add_subparsers(dest='command', help='Commands')
169
+
170
+ # Init
171
+ init_parser = subparsers.add_parser('init', help='Initialize project directory')
172
+
173
+ # Download
174
+ download_parser = subparsers.add_parser('download', help='Download from youtube_url.txt')
175
+ download_parser.add_argument('--task', '-t', required=True, choices=VALID_TASKS)
176
+ download_parser.add_argument('--fast', action='store_true', help='Enable fast parallel downloading')
177
+
178
+ # Download single
179
+ single_parser = subparsers.add_parser('download-single', help='Download single video')
180
+ single_parser.add_argument('--task', '-t', required=True, choices=VALID_TASKS)
181
+ single_parser.add_argument('--url', '-u', required=True, help='YouTube URL')
182
+ single_parser.add_argument('--timestamp-min', '-m', type=int, required=True)
183
+ single_parser.add_argument('--timestamp-sec', '-s', type=int, required=True)
184
+
185
+ # Verify
186
+ verify_parser = subparsers.add_parser('verify', help='Verify with YOLO-World')
187
+ verify_parser.add_argument('--task', '-t', required=True, choices=VALID_TASKS)
188
+ verify_parser.add_argument('--video', '-v', help='Specific video file')
189
+
190
+ # Pipeline
191
+ pipeline_parser = subparsers.add_parser('pipeline', help='Full pipeline')
192
+ pipeline_parser.add_argument('--task', '-t', required=True, choices=VALID_TASKS)
193
+ pipeline_parser.add_argument('--verify', action='store_true')
194
+
195
+ # List tasks
196
+ subparsers.add_parser('list-tasks', help='List available tasks')
197
+
198
+ args = parser.parse_args()
199
+
200
+ if args.command is None:
201
+ parser.print_help()
202
+ return
203
+
204
+ commands = {
205
+ 'init': init_project,
206
+ 'download': run_download,
207
+ 'download-single': run_download_single,
208
+ 'verify': run_verify,
209
+ 'pipeline': run_pipeline,
210
+ 'list-tasks': list_tasks,
211
+ }
212
+
213
+ commands[args.command](args)
214
+
215
+
216
+ if __name__ == '__main__':
217
+ main()
@@ -0,0 +1,65 @@
1
+ """
2
+ SBS Dataset Collector - Configuration
3
+ """
4
+ from pathlib import Path
5
+ import platform
6
+
7
+ # Default paths (will use current working directory)
8
+ def get_paths(base_dir: Path = None):
9
+ """Get all paths based on base directory"""
10
+ if base_dir is None:
11
+ base_dir = Path.cwd()
12
+
13
+ return {
14
+ 'base': base_dir,
15
+ 'data': base_dir / "data",
16
+ # 'urls' removed - now inside video/{task}/youtube_url.txt
17
+ 'videos': base_dir / "data" / "videos", # 원본 전체 영상
18
+ 'clips': base_dir / "video", # 클리핑된 영상 (요구사항: video/task_이름)
19
+ 'outputs': base_dir / "outputs",
20
+ 'reports': base_dir / "outputs" / "reports",
21
+ 'history': base_dir / "download_history.json",
22
+ }
23
+
24
+ # 사용자 지정 출력 경로 (네트워크 드라이브 등)
25
+ # macOS에서는 "/Volumes/Data/..." 등으로 마운트된 경로를 사용해야 함
26
+ NAS_PATH_WINDOWS = r"\\NAS_SERVER_IP\Data\Private Dataset\SBS_De-Identification_YouTube"
27
+ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/SBS_De-Identification_YouTube"
28
+
29
+ if platform.system() == 'Windows':
30
+ CUSTOM_OUTPUT_DIR = NAS_PATH_WINDOWS
31
+ elif platform.system() == 'Darwin': # macOS
32
+ CUSTOM_OUTPUT_DIR = NAS_PATH_MAC
33
+ else:
34
+ CUSTOM_OUTPUT_DIR = None
35
+
36
+ # Video settings
37
+ CLIP_DURATION_BEFORE = 90 # 1분 30초 (초 단위)
38
+ CLIP_DURATION_AFTER = 90 # 1분 30초 (초 단위)
39
+ MAX_CLIP_DURATION = 180 # 최대 3분
40
+
41
+ # Download settings
42
+ VIDEO_FORMAT = "best[ext=mp4]/best"
43
+ DOWNLOAD_RETRIES = 3
44
+ MAX_VIDEOS_PER_TASK = 100 # 태스크별 최대 영상 저장 수
45
+
46
+ # Fast Mode Settings (Parallel)
47
+ MAX_WORKERS = 4 # 병렬 작업 프로세스 수
48
+ REQUEST_DELAY_MIN = 1.0 # 최소 대기 시간 (초)
49
+ REQUEST_DELAY_MAX = 3.0 # 최대 대기 시간 (초)
50
+ PROXY_URL = None # 프록시 (예: "http://user:pass@host:port")
51
+
52
+ # YOLO-World settings
53
+ YOLO_MODEL = "yolov8s-worldv2.pt"
54
+ CONFIDENCE_THRESHOLD = 0.25
55
+ FRAME_SAMPLE_RATE = 30 # 매 30프레임마다 샘플링 (약 1초)
56
+
57
+ # Task-specific class prompts
58
+ TASK_CLASSES = {
59
+ "face": ["human face", "person face", "close-up face"],
60
+ "license_plate": ["car license plate", "vehicle license plate", "korean license plate"],
61
+ "tattoo": ["tattoo", "body tattoo", "skin tattoo"],
62
+ "text": ["text on screen", "subtitle", "korean text", "caption"]
63
+ }
64
+
65
+ VALID_TASKS = list(TASK_CLASSES.keys())