ytcollector 1.0.6__tar.gz → 1.0.7__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.6
3
+ Version: 1.0.7
4
4
  Summary: SBS 데이터셋 수집기
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
@@ -18,7 +18,7 @@ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을
18
18
 
19
19
  **필수 요구사항:**
20
20
  - Python 3.8 이상
21
- - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
21
+ - FFmpeg (pip 설치 시 `imageio-ffmpeg`를 통해 자동으로 구성되나, 실패 시 Mac: `brew install ffmpeg` 설치 권장)
22
22
 
23
23
  **설치:**
24
24
  ```bash
@@ -52,15 +52,17 @@ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
52
52
 
53
53
  이 프로그램은 **다운로드 → YOLO 검증 → (성공 시) 저장** 순서로 작동합니다. 타겟 객체가 없으면 자동으로 삭제됩니다.
54
54
 
55
- ### 기본 다운로드 (순차 실행)
56
- 안정적으로 하나씩 다운로드하고 검증합니다.
55
+ ### 주요 명령어 예시
56
+ 안정적으로 하나씩 다운로드하거나, 여러 태스크를 동시에 처리하고 목표 수량을 설정할 수 있습니다.
57
+
57
58
  ```bash
59
+ # 기본 다운로드 (태스크 하나)
58
60
  ytcollector download --task face
59
- ```
60
61
 
61
- ### 🚀 Fast 모드 (병렬 다운로드)
62
- 대량의 영상을 빠르게 수집할 사용합니다. (4개 스레드 동시 실행)
63
- ```bash
62
+ # 여러 태스크 동시에 실행 및 목표 수량(-n) 설정
63
+ ytcollector download --task face tattoo text -n 100
64
+
65
+ # 🚀 Fast 모드 (병렬 다운로드)
64
66
  ytcollector download --task face --fast
65
67
  ```
66
68
  * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
@@ -93,8 +95,8 @@ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
93
95
  | 명령어 | 설명 | 예시 |
94
96
  |--------|------|------|
95
97
  | `init` | 프로젝트 초기화 | `ytcollector init` |
96
- | `download` | 텍스트 파일 목록 대량 다운로드 | `ytcollector download --task face --fast` |
97
- | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face ...` |
98
+ | `download` | 대량 다운로드 (여러 태스크, 개수 제한 가능) | `ytcollector download --task face tattoo -n 50` |
99
+ | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face -u ...` |
98
100
  | `verify` | 수동 YOLO 검증 (기존 파일) | `ytcollector verify --task face` |
99
101
  | `list-tasks` | 지원하는 태스크 목록 확인 | `ytcollector list-tasks` |
100
102
 
@@ -6,7 +6,7 @@ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을
6
6
 
7
7
  **필수 요구사항:**
8
8
  - Python 3.8 이상
9
- - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
9
+ - FFmpeg (pip 설치 시 `imageio-ffmpeg`를 통해 자동으로 구성되나, 실패 시 Mac: `brew install ffmpeg` 설치 권장)
10
10
 
11
11
  **설치:**
12
12
  ```bash
@@ -40,15 +40,17 @@ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
40
40
 
41
41
  이 프로그램은 **다운로드 → YOLO 검증 → (성공 시) 저장** 순서로 작동합니다. 타겟 객체가 없으면 자동으로 삭제됩니다.
42
42
 
43
- ### 기본 다운로드 (순차 실행)
44
- 안정적으로 하나씩 다운로드하고 검증합니다.
43
+ ### 주요 명령어 예시
44
+ 안정적으로 하나씩 다운로드하거나, 여러 태스크를 동시에 처리하고 목표 수량을 설정할 수 있습니다.
45
+
45
46
  ```bash
47
+ # 기본 다운로드 (태스크 하나)
46
48
  ytcollector download --task face
47
- ```
48
49
 
49
- ### 🚀 Fast 모드 (병렬 다운로드)
50
- 대량의 영상을 빠르게 수집할 사용합니다. (4개 스레드 동시 실행)
51
- ```bash
50
+ # 여러 태스크 동시에 실행 및 목표 수량(-n) 설정
51
+ ytcollector download --task face tattoo text -n 100
52
+
53
+ # 🚀 Fast 모드 (병렬 다운로드)
52
54
  ytcollector download --task face --fast
53
55
  ```
54
56
  * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
@@ -81,8 +83,8 @@ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
81
83
  | 명령어 | 설명 | 예시 |
82
84
  |--------|------|------|
83
85
  | `init` | 프로젝트 초기화 | `ytcollector init` |
84
- | `download` | 텍스트 파일 목록 대량 다운로드 | `ytcollector download --task face --fast` |
85
- | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face ...` |
86
+ | `download` | 대량 다운로드 (여러 태스크, 개수 제한 가능) | `ytcollector download --task face tattoo -n 50` |
87
+ | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face -u ...` |
86
88
  | `verify` | 수동 YOLO 검증 (기존 파일) | `ytcollector verify --task face` |
87
89
  | `list-tasks` | 지원하는 태스크 목록 확인 | `ytcollector list-tasks` |
88
90
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ytcollector"
7
- version = "1.0.6"
7
+ version = "1.0.7"
8
8
  description = "SBS 데이터셋 수집기"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -3,7 +3,7 @@ SBS Dataset Collector - YouTube 영상 수집 및 YOLO-World 검증 파이프라
3
3
  """
4
4
  from pathlib import Path
5
5
 
6
- __version__ = "1.0.6"
6
+ __version__ = "1.0.7"
7
7
  __author__ = "SBS Dataset Team"
8
8
 
9
9
  # Package root directory
@@ -49,6 +49,35 @@ class VideoDownloader:
49
49
  'channel': info.get('channel'),
50
50
  'upload_date': info.get('upload_date'),
51
51
  }
52
+
53
+ def search_youtube(self, query: str, max_results: int = 50) -> List[Dict]:
54
+ """YouTube 검색을 통해 상위 결과의 URL 목록 반환"""
55
+ ydl_opts = {
56
+ 'quiet': True,
57
+ 'no_warnings': True,
58
+ 'extract_flat': True,
59
+ 'force_generic_extractor': False,
60
+ }
61
+
62
+ search_query = f"ytsearch{max_results}:{query}"
63
+ logger.info(f"Searching YouTube for: '{query}' (Max {max_results} results)")
64
+
65
+ results = []
66
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
67
+ try:
68
+ info = ydl.extract_info(search_query, download=False)
69
+ if 'entries' in info:
70
+ for entry in info['entries']:
71
+ if entry:
72
+ results.append({
73
+ 'url': f"https://www.youtube.com/watch?v={entry['id']}",
74
+ 'title': entry.get('title'),
75
+ 'id': entry['id']
76
+ })
77
+ except Exception as e:
78
+ logger.error(f"Search failed: {e}")
79
+
80
+ return results
52
81
 
53
82
  def calculate_clip_range(
54
83
  self,
@@ -357,34 +386,81 @@ def _process_download_loop(txt_path: Path, task_type: str, base_dir: Path = None
357
386
  'status': 'error'
358
387
  }
359
388
 
360
- if parallel:
361
- with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
362
- futures = [executor.submit(process_item, item) for item in items]
363
-
364
- # 진행 상황 표시
365
- from tqdm import tqdm
366
- for future in tqdm(as_completed(futures), total=len(items), desc="Fast Download"):
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
376
- else:
377
- # 순차 실행
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
389
+ # --- 1단계: youtube_url.txt 파일 목록 처리 ---
390
+ if items:
391
+ if parallel:
392
+ with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
393
+ futures = [executor.submit(process_item, item) for item in items]
383
394
 
384
- res = process_item(item)
385
- results.append(res)
386
- if res.get('status') == 'limit_reached':
387
- logger.info(f"Target count ({limit}) reached. Stopping.")
388
- break
395
+ # 진행 상황 표시
396
+ from tqdm import tqdm
397
+ for future in tqdm(as_completed(futures), total=len(items), desc="Fast Download"):
398
+ try:
399
+ res = future.result()
400
+ results.append(res)
401
+ if res.get('status') == 'limit_reached' or downloader.get_saved_video_count() >= limit:
402
+ logger.info(f"Download limit ({limit}) reached. Stopping.")
403
+ executor.shutdown(wait=False, cancel_futures=True)
404
+ break
405
+ except Exception:
406
+ continue
407
+ else:
408
+ # 순차 실행
409
+ for item in items:
410
+ if downloader.get_saved_video_count() >= limit:
411
+ break
412
+ res = process_item(item)
413
+ results.append(res)
414
+ if res.get('status') == 'limit_reached':
415
+ break
416
+
417
+ # --- 2단계: 목표 수량을 못 채웠을 경우 YouTube 검색Fallback ---
418
+ current_count = downloader.get_saved_video_count()
419
+ if current_count < limit:
420
+ remaining = limit - current_count
421
+ logger.info(f"\nTarget not reached ({current_count}/{limit}). Starting YouTube Search fallback for '{task_type}'...")
422
+
423
+ # 검색어: 태스크 이름 (필요시 config에서 태스크별 검색어 별도 지정 가능)
424
+ search_results = downloader.search_youtube(task_type, max_results=remaining * 2)
425
+
426
+ if not search_results:
427
+ logger.warning("No search results found.")
428
+ return results
429
+
430
+ # 검색 결과는 타임스탬프 정보가 없으므로, 기본적으로 영상의 1:00 지점 혹은 0:00 지점을 시도
431
+ # 여기서는 영상의 대략 1분 지점(영상이 짧으면 0)을 타겟으로 시도해봄
432
+ search_items = []
433
+ for entry in search_results:
434
+ search_items.append({
435
+ 'task_type': task_type,
436
+ 'url': entry['url'],
437
+ 'timestamp_min': 1, # 1분 지점 샘플링 시도
438
+ 'timestamp_sec': 0,
439
+ 'description': f"Auto-searched: {entry['title']}"
440
+ })
441
+
442
+ logger.info(f"Processing {len(search_items)} search results...")
443
+
444
+ if parallel:
445
+ with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
446
+ futures = [executor.submit(process_item, item) for item in search_items]
447
+ from tqdm import tqdm
448
+ for future in tqdm(as_completed(futures), total=len(search_items), desc="Search Fallback"):
449
+ try:
450
+ res = future.result()
451
+ results.append(res)
452
+ if res.get('status') == 'limit_reached' or downloader.get_saved_video_count() >= limit:
453
+ executor.shutdown(wait=False, cancel_futures=True)
454
+ break
455
+ except Exception:
456
+ continue
457
+ else:
458
+ for item in search_items:
459
+ if downloader.get_saved_video_count() >= limit:
460
+ break
461
+ res = process_item(item)
462
+ results.append(res)
463
+ if res.get('status') == 'limit_reached':
464
+ break
389
465
 
390
466
  return results
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ytcollector
3
- Version: 1.0.6
3
+ Version: 1.0.7
4
4
  Summary: SBS 데이터셋 수집기
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
@@ -18,7 +18,7 @@ YouTube 영상에서 얼굴, 자동차 번호판, 타투, 텍스트 자막을
18
18
 
19
19
  **필수 요구사항:**
20
20
  - Python 3.8 이상
21
- - FFmpeg (Mac: `brew install ffmpeg`) **👈 필수 설치! (영상 자르기에 필요)**
21
+ - FFmpeg (pip 설치 시 `imageio-ffmpeg`를 통해 자동으로 구성되나, 실패 시 Mac: `brew install ffmpeg` 설치 권장)
22
22
 
23
23
  **설치:**
24
24
  ```bash
@@ -52,15 +52,17 @@ face,https://www.youtube.com/watch?v=VIDEO_ID,2,30,설명
52
52
 
53
53
  이 프로그램은 **다운로드 → YOLO 검증 → (성공 시) 저장** 순서로 작동합니다. 타겟 객체가 없으면 자동으로 삭제됩니다.
54
54
 
55
- ### 기본 다운로드 (순차 실행)
56
- 안정적으로 하나씩 다운로드하고 검증합니다.
55
+ ### 주요 명령어 예시
56
+ 안정적으로 하나씩 다운로드하거나, 여러 태스크를 동시에 처리하고 목표 수량을 설정할 수 있습니다.
57
+
57
58
  ```bash
59
+ # 기본 다운로드 (태스크 하나)
58
60
  ytcollector download --task face
59
- ```
60
61
 
61
- ### 🚀 Fast 모드 (병렬 다운로드)
62
- 대량의 영상을 빠르게 수집할 사용합니다. (4개 스레드 동시 실행)
63
- ```bash
62
+ # 여러 태스크 동시에 실행 및 목표 수량(-n) 설정
63
+ ytcollector download --task face tattoo text -n 100
64
+
65
+ # 🚀 Fast 모드 (병렬 다운로드)
64
66
  ytcollector download --task face --fast
65
67
  ```
66
68
  * **방화벽 우회**: 랜덤 딜레이(1~3초)가 적용되어 차단을 방지합니다.
@@ -93,8 +95,8 @@ NAS_PATH_MAC = "/Volumes/Data/Private Dataset/..."
93
95
  | 명령어 | 설명 | 예시 |
94
96
  |--------|------|------|
95
97
  | `init` | 프로젝트 초기화 | `ytcollector init` |
96
- | `download` | 텍스트 파일 목록 대량 다운로드 | `ytcollector download --task face --fast` |
97
- | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face ...` |
98
+ | `download` | 대량 다운로드 (여러 태스크, 개수 제한 가능) | `ytcollector download --task face tattoo -n 50` |
99
+ | `download-single` | URL 1개만 테스트 다운로드 | `ytcollector download-single --task face -u ...` |
98
100
  | `verify` | 수동 YOLO 검증 (기존 파일) | `ytcollector verify --task face` |
99
101
  | `list-tasks` | 지원하는 태스크 목록 확인 | `ytcollector list-tasks` |
100
102
 
File without changes