ytcollector 1.0.2__tar.gz → 1.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ytcollector
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: SBS 데이터셋 수집기
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
@@ -8,6 +8,7 @@ Requires-Dist: yt-dlp>=2024.1.0
8
8
  Requires-Dist: ultralytics>=8.1.0
9
9
  Requires-Dist: opencv-python>=4.9.0
10
10
  Requires-Dist: tqdm>=4.66.0
11
+ Requires-Dist: imageio-ffmpeg>=0.4.9
11
12
 
12
13
  # Downloader: SBS 데이터셋 수집기
13
14
 
@@ -17,7 +18,7 @@ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을
17
18
 
18
19
  **필수 요구사항:**
19
20
  - Python 3.8 이상
20
- - FFmpeg (Mac: `brew install ffmpeg`)
21
+ - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
21
22
 
22
23
  **설치:**
23
24
  ```bash
@@ -28,7 +29,7 @@ pip install -e .
28
29
  **프로젝트 초기화 (최초 1회):**
29
30
  필요한 폴더(`urls/`, `video/`)를 생성합니다.
30
31
  ```bash
31
- downloader init
32
+ ytcollector init
32
33
  ```
33
34
 
34
35
  ---
@@ -54,13 +55,13 @@ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
54
55
  ### 기본 다운로드 (순차 실행)
55
56
  안정적으로 하나씩 다운로드하고 검증합니다.
56
57
  ```bash
57
- downloader download --task face
58
+ ytcollector download --task face
58
59
  ```
59
60
 
60
61
  ### 🚀 Fast 모드 (병렬 다운로드)
61
62
  대량의 영상을 빠르게 수집할 때 사용합니다. (4개 스레드 동시 실행)
62
63
  ```bash
63
- downloader download --task face --fast
64
+ ytcollector download --task face --fast
64
65
  ```
65
66
  * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
66
67
  * **에러 무시**: 중간에 에러가 나도 멈추지 않고 다음 영상으로 넘어갑니다.
@@ -76,7 +77,7 @@ downloader download --task face --fast
76
77
  영상을 로컬이 아닌 NAS에 저장하려면 설정을 수정하세요.
77
78
  OS(Windows/Mac)를 자동 감지하여 적절한 경로를 사용합니다.
78
79
 
79
- **설정 파일 수정:** `downloader/config.py`
80
+ **설정 파일 수정:** `ytcollector/config.py`
80
81
  ```python
81
82
  # Windows 예시
82
83
  NAS_PATH_WINDOWS = r"\\NAS_SERVER_IP\Data\Private Dataset\..."
@@ -91,11 +92,11 @@ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
91
92
 
92
93
  | 명령어 | 설명 | 예시 |
93
94
  |--------|------|------|
94
- | `init` | 프로젝트 초기화 | `downloader init` |
95
- | `download` | 텍스트 파일 목록 대량 다운로드 | `downloader download --task face --fast` |
96
- | `download-single` | URL 1개만 테스트 다운로드 | `downloader download-single --task face ...` |
97
- | `verify` | 수동 YOLO 검증 (기존 파일) | `downloader verify --task face` |
98
- | `list-tasks` | 지원하는 태스크 목록 확인 | `downloader list-tasks` |
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` |
99
100
 
100
101
  ## 6. 문제 해결
101
102
  * **검증 실패가 너무 많음**: `config.py`에서 `CONFIDENCE_THRESHOLD` (기본 0.25) 값을 낮춰보세요.
@@ -6,7 +6,7 @@ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을
6
6
 
7
7
  **필수 요구사항:**
8
8
  - Python 3.8 이상
9
- - FFmpeg (Mac: `brew install ffmpeg`)
9
+ - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
10
10
 
11
11
  **설치:**
12
12
  ```bash
@@ -17,7 +17,7 @@ pip install -e .
17
17
  **프로젝트 초기화 (최초 1회):**
18
18
  필요한 폴더(`urls/`, `video/`)를 생성합니다.
19
19
  ```bash
20
- downloader init
20
+ ytcollector init
21
21
  ```
22
22
 
23
23
  ---
@@ -43,13 +43,13 @@ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
43
43
  ### 기본 다운로드 (순차 실행)
44
44
  안정적으로 하나씩 다운로드하고 검증합니다.
45
45
  ```bash
46
- downloader download --task face
46
+ ytcollector download --task face
47
47
  ```
48
48
 
49
49
  ### 🚀 Fast 모드 (병렬 다운로드)
50
50
  대량의 영상을 빠르게 수집할 때 사용합니다. (4개 스레드 동시 실행)
51
51
  ```bash
52
- downloader download --task face --fast
52
+ ytcollector download --task face --fast
53
53
  ```
54
54
  * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
55
55
  * **에러 무시**: 중간에 에러가 나도 멈추지 않고 다음 영상으로 넘어갑니다.
@@ -65,7 +65,7 @@ downloader download --task face --fast
65
65
  영상을 로컬이 아닌 NAS에 저장하려면 설정을 수정하세요.
66
66
  OS(Windows/Mac)를 자동 감지하여 적절한 경로를 사용합니다.
67
67
 
68
- **설정 파일 수정:** `downloader/config.py`
68
+ **설정 파일 수정:** `ytcollector/config.py`
69
69
  ```python
70
70
  # Windows 예시
71
71
  NAS_PATH_WINDOWS = r"\\NAS_SERVER_IP\Data\Private Dataset\..."
@@ -80,11 +80,11 @@ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
80
80
 
81
81
  | 명령어 | 설명 | 예시 |
82
82
  |--------|------|------|
83
- | `init` | 프로젝트 초기화 | `downloader init` |
84
- | `download` | 텍스트 파일 목록 대량 다운로드 | `downloader download --task face --fast` |
85
- | `download-single` | URL 1개만 테스트 다운로드 | `downloader download-single --task face ...` |
86
- | `verify` | 수동 YOLO 검증 (기존 파일) | `downloader verify --task face` |
87
- | `list-tasks` | 지원하는 태스크 목록 확인 | `downloader list-tasks` |
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
88
 
89
89
  ## 6. 문제 해결
90
90
  * **검증 실패가 너무 많음**: `config.py`에서 `CONFIDENCE_THRESHOLD` (기본 0.25) 값을 낮춰보세요.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ytcollector"
7
- version = "1.0.2"
7
+ version = "1.0.4"
8
8
  description = "SBS 데이터셋 수집기"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -13,6 +13,7 @@ dependencies = [
13
13
  "ultralytics>=8.1.0",
14
14
  "opencv-python>=4.9.0",
15
15
  "tqdm>=4.66.0",
16
+ "imageio-ffmpeg>=0.4.9",
16
17
  ]
17
18
 
18
19
  [project.scripts]
@@ -3,7 +3,7 @@ SBS Dataset Collector - YouTube 영상 수집 및 YOLO-World 검증 파이프라
3
3
  """
4
4
  from pathlib import Path
5
5
 
6
- __version__ = "1.0.2"
6
+ __version__ = "1.0.4"
7
7
  __author__ = "SBS Dataset Team"
8
8
 
9
9
  # Package root directory
@@ -60,9 +60,9 @@ def run_download(args):
60
60
 
61
61
  if args.fast:
62
62
  from .downloader import download_from_txt_parallel
63
- results = download_from_txt_parallel(txt_file, args.task, base_dir)
63
+ results = download_from_txt_parallel(txt_file, args.task, base_dir, max_count=args.count)
64
64
  else:
65
- results = download_from_txt(txt_file, args.task, base_dir)
65
+ results = download_from_txt(txt_file, args.task, base_dir, max_count=args.count)
66
66
 
67
67
  success_count = sum(1 for r in results if r.get('success'))
68
68
  print(f"✓ Download complete: {success_count}/{len(results)} successful")
@@ -173,6 +173,7 @@ Examples:
173
173
  # Download
174
174
  download_parser = subparsers.add_parser('download', help='Download from youtube_url.txt')
175
175
  download_parser.add_argument('--task', '-t', required=True, choices=VALID_TASKS)
176
+ download_parser.add_argument('--count', '-n', type=int, help='Max videos to collect (default: 1000)')
176
177
  download_parser.add_argument('--fast', action='store_true', help='Enable fast parallel downloading')
177
178
 
178
179
  # Download single
@@ -41,7 +41,7 @@ MAX_CLIP_DURATION = 180 # 최대 3분
41
41
  # Download settings
42
42
  VIDEO_FORMAT = "best[ext=mp4]/best"
43
43
  DOWNLOAD_RETRIES = 3
44
- MAX_VIDEOS_PER_TASK = 100 # 태스크별 최대 영상 저장 수
44
+ MAX_VIDEOS_PER_TASK = 1000 # 태스크별 최대 영상 저장 수 (CLI -n 옵션으로 덮어쓰기 가능)
45
45
 
46
46
  # Fast Mode Settings (Parallel)
47
47
  MAX_WORKERS = 4 # 병렬 작업 프로세스 수
@@ -85,6 +85,15 @@ class VideoDownloader:
85
85
  'download_ranges': download_range_func(None, [(start_sec, end_sec)]),
86
86
  'force_keyframes_at_cuts': True,
87
87
  }
88
+
89
+ # Use ffmpeg from imageio-ffmpeg
90
+ try:
91
+ import imageio_ffmpeg
92
+ ffmpeg_path = imageio_ffmpeg.get_ffmpeg_exe()
93
+ ydl_opts['ffmpeg_location'] = ffmpeg_path
94
+ logger.debug(f"Using ffmpeg from: {ffmpeg_path}")
95
+ except ImportError:
96
+ logger.warning("imageio-ffmpeg not found, relying on system ffmpeg")
88
97
 
89
98
  logger.info(f"Downloading segment [{start_sec}s - {end_sec}s] from: {url}")
90
99
 
@@ -238,31 +247,34 @@ def parse_txt_line(line: str) -> Optional[Dict]:
238
247
  return None
239
248
 
240
249
 
241
- def download_from_txt(txt_path: Path, task_type: str, base_dir: Path = None) -> list:
250
+ def download_from_txt(txt_path: Path, task_type: str, base_dir: Path = None, max_count: int = None) -> list:
242
251
  """TXT 파일에서 다운로드 실행 (순차)"""
243
252
  # 기존 로직을 process_single_item 함수로 분리하여 재사용할 수 있으면 좋겠지만,
244
253
  # 코드 구조상 일단 순차 실행 유지하고 parallel 함수 별도 구현
245
- return _process_download_loop(txt_path, task_type, base_dir, parallel=False)
254
+ return _process_download_loop(txt_path, task_type, base_dir, parallel=False, max_count=max_count)
246
255
 
247
256
 
248
- def download_from_txt_parallel(txt_path: Path, task_type: str, base_dir: Path = None) -> list:
257
+ def download_from_txt_parallel(txt_path: Path, task_type: str, base_dir: Path = None, max_count: int = None) -> list:
249
258
  """TXT 파일에서 병렬 다운로드 실행 (Fast Mode)"""
250
- return _process_download_loop(txt_path, task_type, base_dir, parallel=True)
259
+ return _process_download_loop(txt_path, task_type, base_dir, parallel=True, max_count=max_count)
251
260
 
252
261
 
253
- def _process_download_loop(txt_path: Path, task_type: str, base_dir: Path = None, parallel: bool = False) -> list:
262
+ def _process_download_loop(txt_path: Path, task_type: str, base_dir: Path = None, parallel: bool = False, max_count: int = None) -> list:
254
263
  from .config import MAX_VIDEOS_PER_TASK, MAX_WORKERS, REQUEST_DELAY_MIN, REQUEST_DELAY_MAX
255
264
  import time
256
265
  import random
257
266
  from concurrent.futures import ThreadPoolExecutor, as_completed
258
267
 
268
+ # max_count가 없으면 config의 기본값 사용
269
+ limit = max_count if max_count is not None else MAX_VIDEOS_PER_TASK
270
+
259
271
  results = []
260
272
  downloader = VideoDownloader(task_type, base_dir)
261
273
 
262
274
  # 시작 전 개수 확인
263
275
  initial_count = downloader.get_saved_video_count()
264
- if initial_count >= MAX_VIDEOS_PER_TASK:
265
- logger.warning(f"Task '{task_type}' already has {initial_count} videos. Skipping.")
276
+ if initial_count >= limit:
277
+ logger.warning(f"Task '{task_type}' already has {initial_count} videos (Limit: {limit}). Skipping.")
266
278
  return results
267
279
 
268
280
  if not txt_path.exists():
@@ -282,14 +294,26 @@ def _process_download_loop(txt_path: Path, task_type: str, base_dir: Path = None
282
294
  if not items:
283
295
  return results
284
296
 
285
- logger.info(f"Found {len(items)} URLs. Starting {'parallel' if parallel else 'sequential'} download...")
297
+ logger.info(f"Found {len(items)} URLs. Target: {limit} videos (Current: {initial_count}). Starting {'parallel' if parallel else 'sequential'} download...")
286
298
 
287
299
  def process_item(data):
300
+ # 현재 개수 체크 (루프 도중 목표 달성 시 중단 위함)
301
+ # 주의: 병렬 처리 시 정확한 count 동기화는 Lock이 필요하지만, 여기선 대략적인 체크로 충분
302
+ current = downloader.get_saved_video_count()
303
+ if current >= limit:
304
+ raise LimitReachedError("Target count reached")
305
+
288
306
  # 방화벽 우회용 랜덤 딜레이 (병렬 모드에서도 적용하여 동시 요청 폭주 완화)
289
307
  if parallel:
290
308
  time.sleep(random.uniform(REQUEST_DELAY_MIN, REQUEST_DELAY_MAX))
291
309
 
292
310
  try:
311
+ # VideoDownloader 내부의 limit 체크는 config 값을 쓰므로,
312
+ # 여기서는 외부에서 주입된 limit을 강제할 방법이 필요하거나,
313
+ # 단순히 루프 레벨에서 제어하면 됨.
314
+ # download_clip_at_timestamp 메서드는 내부적으로 MAX_VIDEOS_PER_TASK를 체크하므로,
315
+ # 이를 우회하거나 단순 루프 제어로 처리.
316
+
293
317
  output_path, metadata = downloader.download_clip_at_timestamp(
294
318
  url=data['url'],
295
319
  timestamp_min=data['timestamp_min'],
@@ -320,8 +344,7 @@ def _process_download_loop(txt_path: Path, task_type: str, base_dir: Path = None
320
344
  }
321
345
 
322
346
  except LimitReachedError:
323
- # 병렬 실행 중에는 이 예외 처리 방식이 조금 다를 수 있음 (다른 스레드 멈추게 하려면 Event 사용 등)
324
- # 여기서는 개별 스레드 종료로 처리
347
+ # 내부에서 발생한 LimitReachedError도 처리
325
348
  return {'success': False, 'error': 'Limit reached', 'status': 'limit_reached'}
326
349
 
327
350
  except Exception as e:
@@ -341,18 +364,27 @@ def _process_download_loop(txt_path: Path, task_type: str, base_dir: Path = None
341
364
  # 진행 상황 표시
342
365
  from tqdm import tqdm
343
366
  for future in tqdm(as_completed(futures), total=len(items), desc="Fast Download"):
344
- res = future.result()
345
- results.append(res)
346
- if res.get('status') == 'limit_reached':
347
- logger.warning("Download limit reached. Stopping remaining tasks.")
348
- executor.shutdown(wait=False, cancel_futures=True)
349
- break
367
+ try:
368
+ res = future.result()
369
+ results.append(res)
370
+ if res.get('status') == 'limit_reached' or downloader.get_saved_video_count() >= limit:
371
+ logger.warning(f"Download limit ({limit}) reached. Stopping remaining tasks.")
372
+ executor.shutdown(wait=False, cancel_futures=True)
373
+ break
374
+ except Exception:
375
+ continue
350
376
  else:
351
377
  # 순차 실행
352
378
  for item in items:
379
+ # 루프 시작 전 체크
380
+ if downloader.get_saved_video_count() >= limit:
381
+ logger.info(f"Target count ({limit}) reached. Stopping.")
382
+ break
383
+
353
384
  res = process_item(item)
354
385
  results.append(res)
355
386
  if res.get('status') == 'limit_reached':
387
+ logger.info(f"Target count ({limit}) reached. Stopping.")
356
388
  break
357
389
 
358
390
  return results
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ytcollector
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: SBS 데이터셋 수집기
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
@@ -8,6 +8,7 @@ Requires-Dist: yt-dlp>=2024.1.0
8
8
  Requires-Dist: ultralytics>=8.1.0
9
9
  Requires-Dist: opencv-python>=4.9.0
10
10
  Requires-Dist: tqdm>=4.66.0
11
+ Requires-Dist: imageio-ffmpeg>=0.4.9
11
12
 
12
13
  # Downloader: SBS 데이터셋 수집기
13
14
 
@@ -17,7 +18,7 @@ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을
17
18
 
18
19
  **필수 요구사항:**
19
20
  - Python 3.8 이상
20
- - FFmpeg (Mac: `brew install ffmpeg`)
21
+ - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
21
22
 
22
23
  **설치:**
23
24
  ```bash
@@ -28,7 +29,7 @@ pip install -e .
28
29
  **프로젝트 초기화 (최초 1회):**
29
30
  필요한 폴더(`urls/`, `video/`)를 생성합니다.
30
31
  ```bash
31
- downloader init
32
+ ytcollector init
32
33
  ```
33
34
 
34
35
  ---
@@ -54,13 +55,13 @@ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
54
55
  ### 기본 다운로드 (순차 실행)
55
56
  안정적으로 하나씩 다운로드하고 검증합니다.
56
57
  ```bash
57
- downloader download --task face
58
+ ytcollector download --task face
58
59
  ```
59
60
 
60
61
  ### 🚀 Fast 모드 (병렬 다운로드)
61
62
  대량의 영상을 빠르게 수집할 때 사용합니다. (4개 스레드 동시 실행)
62
63
  ```bash
63
- downloader download --task face --fast
64
+ ytcollector download --task face --fast
64
65
  ```
65
66
  * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
66
67
  * **에러 무시**: 중간에 에러가 나도 멈추지 않고 다음 영상으로 넘어갑니다.
@@ -76,7 +77,7 @@ downloader download --task face --fast
76
77
  영상을 로컬이 아닌 NAS에 저장하려면 설정을 수정하세요.
77
78
  OS(Windows/Mac)를 자동 감지하여 적절한 경로를 사용합니다.
78
79
 
79
- **설정 파일 수정:** `downloader/config.py`
80
+ **설정 파일 수정:** `ytcollector/config.py`
80
81
  ```python
81
82
  # Windows 예시
82
83
  NAS_PATH_WINDOWS = r"\\NAS_SERVER_IP\Data\Private Dataset\..."
@@ -91,11 +92,11 @@ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
91
92
 
92
93
  | 명령어 | 설명 | 예시 |
93
94
  |--------|------|------|
94
- | `init` | 프로젝트 초기화 | `downloader init` |
95
- | `download` | 텍스트 파일 목록 대량 다운로드 | `downloader download --task face --fast` |
96
- | `download-single` | URL 1개만 테스트 다운로드 | `downloader download-single --task face ...` |
97
- | `verify` | 수동 YOLO 검증 (기존 파일) | `downloader verify --task face` |
98
- | `list-tasks` | 지원하는 태스크 목록 확인 | `downloader list-tasks` |
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` |
99
100
 
100
101
  ## 6. 문제 해결
101
102
  * **검증 실패가 너무 많음**: `config.py`에서 `CONFIDENCE_THRESHOLD` (기본 0.25) 값을 낮춰보세요.
@@ -2,3 +2,4 @@ yt-dlp>=2024.1.0
2
2
  ultralytics>=8.1.0
3
3
  opencv-python>=4.9.0
4
4
  tqdm>=4.66.0
5
+ imageio-ffmpeg>=0.4.9
File without changes