# 비디오 데이터셋 만들기

이 가이드에서는 `VideoFolder`와 일부 메타데이터를 사용하여 비디오 데이터셋을 만드는 방법을 보여줍니다. 수천 개의 비디오로 구성된 비디오 데이터셋을 빠르게 생성하기 위한 무코드(no-code) 솔루션입니다.

> [!TIP]
> 사용자가 먼저 연락처 정보를 공유하도록 요구하여 데이터셋에 대한 액세스를 제어할 수 있습니다. Hub에서 이 기능을 활성화하는 방법에 대한 자세한 내용은 [Gated datasets](https://huggingface.co/docs/hub/datasets-gated) 가이드를 참고하세요.

## VideoFolder

`VideoFolder`는 수천 개의 비디오로 구성된 비디오 데이터셋을 코드를 작성하지 않고도 빠르게 로드하도록 설계된 데이터셋 빌더입니다.

> [!TIP]
> 💡 `VideoFolder`가 데이터셋 저장소 구조를 기반으로 데이터셋 분할을 생성하는 방법에 대해 자세히 알아보려면 [Split pattern hierarchy](repository_structure#split-pattern-hierarchy)를 확인해 보세요.

`VideoFolder`는 디렉터리 이름을 기반으로 데이터셋의 클래스 라벨을 자동으로 추론합니다. 데이터셋을 다음과 같은 디렉터리 구조로 저장하세요:

```
folder/train/dog/golden_retriever.mp4
folder/train/dog/german_shepherd.mp4
folder/train/dog/chihuahua.mp4

folder/train/cat/maine_coon.mp4
folder/train/cat/bengal.mp4
folder/train/cat/birman.mp4
```

데이터셋이 `VideoFolder` 구조를 따르는 경우, [load_dataset()](/docs/datasets/v5.2.0/ko/package_reference/loading_methods#datasets.load_dataset)를 사용하여 직접 로드할 수 있습니다:

```py
>>> from datasets import load_dataset

>>> dataset = load_dataset("path/to/folder")
```

`videofolder`를 [load_dataset()](/docs/datasets/v5.2.0/ko/package_reference/loading_methods#datasets.load_dataset)에 수동으로 전달하고 `data_dir`에 디렉터리를 지정하는 것과 동일합니다:

```py
>>> dataset = load_dataset("videofolder", data_dir="/path/to/folder")
```

`videofolder`를 사용하여 여러 스플릿을 포함하는 데이터셋을 로드할 수도 있습니다. 이를 위해 데이터셋 디렉토리는 다음 구조를 가져야 합니다:

```
folder/train/dog/golden_retriever.mp4
folder/train/cat/maine_coon.mp4
folder/test/dog/german_shepherd.mp4
folder/test/cat/bengal.mp4
```

> [!WARNING]
> 모든 비디오 파일이 단일 디렉터리에 포함되어 있거나 동일한 디렉터리 구조 레벨에 있지 않은 경우, `label` 열이 자동으로 추가되지 않습니다. 이 열이 필요한 경우 `drop_labels=False`를 명시적으로 설정하세요.

데이터셋에 텍스트 캡션이나 바운딩 박스처럼 포함하고 싶은 추가 정보가 있다면, 폴더에 `metadata.csv` 파일로 추가하세요. 이를 통해 텍스트 캡션이나 객체 탐지와 같은 다양한 컴퓨터 비전 작업용 데이터셋을 빠르게 만들 수 있습니다. JSONL 파일 `metadata.jsonl` 또는 Parquet 파일 `metadata.parquet`도 사용할 수 있습니다.

```
folder/train/metadata.csv
folder/train/0001.mp4
folder/train/0002.mp4
folder/train/0003.mp4
```

`metadata.csv` 파일에는 비디오 파일과 메타데이터를 연결하는 `file_name` 또는 `*_file_name` 필드가 있어야 합니다:

```csv
file_name,additional_feature
0001.mp4,This is a first value of a text feature you added to your videos
0002.mp4,This is a second value of a text feature you added to your videos
0003.mp4,This is a third value of a text feature you added to your videos
```

또는 `metadata.jsonl`을(를) 사용하여:

```jsonl
{"file_name": "0001.mp4", "additional_feature": "This is a first value of a text feature you added to your videos"}
{"file_name": "0002.mp4", "additional_feature": "This is a second value of a text feature you added to your videos"}
{"file_name": "0003.mp4", "additional_feature": "This is a third value of a text feature you added to your videos"}
```

여기서 `file_name`은 메타데이터 파일 옆에 있는 비디오 파일의 이름이어야 합니다. 더 일반적으로, 메타데이터가 포함된 디렉터리에서 비디오 파일까지의 상대 경로여야 합니다.

데이터셋의 각 행에 두 개 이상의 비디오를 지정할 수 있습니다. 예를 들어 입력과 출력 모두 비디오인 경우:

```jsonl
{"input_file_name": "0001.mp4", "output_file_name": "0001_output.mp4"}
{"input_file_name": "0002.mp4", "output_file_name": "0002_output.mp4"}
{"input_file_name": "0003.mp4", "output_file_name": "0003_output.mp4"}
```

비디오 목록도 정의할 수 있습니다. 이 경우 필드 이름을 `file_names` 또는 `*_file_names`으로 지정해야 합니다. 예시는 다음과 같습니다:

```jsonl
{"videos_file_names": ["0001_left.mp4", "0001_right.mp4"], "label": "moving_up"}
{"videos_file_names": ["0002_left.mp4", "0002_right.mp4"], "label": "moving_down"}
{"videos_file_names": ["0003_left.mp4", "0003_right.mp4"], "label": "moving_right"}
```

### 비디오 캡셔닝

Video captioning 데이터셋에는 비디오를 설명하는 텍스트가 포함되어 있습니다. `metadata.csv`의 예시는 다음과 같습니다:

```csv
file_name,text
0001.mp4,This is a golden retriever playing with a ball
0002.mp4,A german shepherd
0003.mp4,One chihuahua
```

`VideoFolder`로 데이터셋을 로드하면, 비디오 캡션을 위한 `text` 열이 생성됩니다:

```py
>>> dataset = load_dataset("videofolder", data_dir="/path/to/folder", split="train")
>>> dataset[0]["text"]
"This is a golden retriever playing with a ball"
```

### Hub에 데이터셋 업로드

데이터셋을 생성한 후에는 `huggingface_hub` 등을 사용하여 공유할 수 있습니다. [huggingface_hub](https://huggingface.co/docs/huggingface_hub/index) 라이브러리가 설치되어 있고 Hugging Face 계정에 로그인되어 있는지 확인하세요(자세한 내용은 [Upload with Python tutorial](upload_dataset#upload-with-python)를 참고하세요).

`huggingface_hub.HfApi.upload_folder`로 데이터셋을 업로드하세요:

```py
from huggingface_hub import HfApi
api = HfApi()

api.upload_folder(
    folder_path="/path/to/local/dataset",
    repo_id="username/my-cool-dataset",
    repo_type="dataset",
)
```

## WebDataset

[WebDataset](https://github.com/webdataset/webdataset) 형식은 TAR 아카이브를 기반으로 하며 대규모 비디오 데이터셋에 적합합니다. 실제로 비디오를 TAR 아카이브(예: TAR 아카이브당 1GB의 비디오)로 묶고 수천 개의 TAR 아카이브를 가질 수 있습니다:

```
folder/train/00000.tar
folder/train/00001.tar
folder/train/00002.tar
...
```

아카이브에서 각 예제는 동일한 접두사를 공유하는 파일들로 구성됩니다:

```
e39871fd9fd74f55.mp4
e39871fd9fd74f55.json
f18b91585c4d3f3e.mp4
f18b91585c4d3f3e.json
ede6e66b2fb59aab.mp4
ede6e66b2fb59aab.json
ed600d57fcee4f94.mp4
ed600d57fcee4f94.json
...
```

JSON 또는 텍스트 파일 등을 사용하여 비디오의 라벨/캡션/기능을 지정할 수 있습니다.

WebDataset 형식과 python 라이브러리에 대한 자세한 내용은 [WebDataset 문서](https://webdataset.github.io/webdataset)를 참고하세요.

WebDataset를 로드하면 파일 확장자(여기서는 "mp4"와 "json")별로 컬럼이 하나씩 생성됩니다:

```python
>>> from datasets import load_dataset

>>> dataset = load_dataset("webdataset", data_dir="/path/to/folder", split="train")
>>> dataset[0]["json"]
{"bbox": [[302.0, 109.0, 73.0, 52.0]], "categories": [0]}
```

## Lance

[Lance](https://lance.org)는 오픈 멀티모달 레이크하우스 테이블 형식입니다. Lance 테이블은 텍스트와 스칼라 값뿐만 아니라 이미지, 오디오, 비디오와 같은 대형 바이너리 객체(blobs)도 테이블 데이터와 함께 네이티브로 저장할 수 있습니다.

Lance는 Lance 데이터셋에서 대용량 blob을 저장하고 검색하는 데 편리한 [blob API](https://lance.org/guide/blob/)를 제공합니다. 다음 예제는 무거운 video blob을 로드하지 않고 메타데이터를 효율적으로 탐색한 후, 필요한 video blob을 온디맨드로 가져오는 방법을 보여줍니다.

비디오를 저장하는 Lance 테이블의 대표적인 예시는 다음과 같습니다(`video_blob` 컬럼은 Lance의 blob 인코딩을 사용합니다):

```text
+------------------------------------------+-----------------+-----+------------------------------------------+
| caption                                  | aesthetic_score | ... | video_blob                               |
+------------------------------------------+-----------------+-----+------------------------------------------+
| "a breathtaking view of a mounta..."     | 5.2401          | ... | {position: 0, size: 4873879}             |
| "a captivating view of the sun, b..."    | 5.2401          | ... | {position: 4873920, size: 3370571}       |
+------------------------------------------+-----------------+-----+------------------------------------------+
```

### Write a Lance dataset from raw video files

디스크에 있는 원본 비디오 파일과 관련 메타데이터(예: 캡션 및 점수)를 기반으로, 자체적으로 완결된 Lance 데이터셋을 로컬의 `*.lance` 디렉터리(Lance 데이터셋은 디스크상의 디렉터리이며, `.lance` 접미사로 이름을 붙이는 것이 일반적입니다)에 작성할 수 있습니다:

```py
import lance
import pyarrow as pa

import urllib.request

schema = pa.schema(
    [
        pa.field("caption", pa.utf8()),
        pa.field("aesthetic_score", pa.float64()),
        pa.field(
            "video_blob",
            pa.large_binary(),
            metadata={"lance-encoding:blob": "true"},
        ),
    ]
)

# Provide video files alongside metadata
rows = [
    {
        "video_path": "/path/to/videos/0001.mp4",
        "caption": "a breathtaking view of a mountainous landscape ...",
        "aesthetic_score": 5.240138053894043,
    },
    {
        "video_path": "0002.mp4",
        "caption": "a captivating view of the sun, bathed in hues ...",
        "aesthetic_score": 5.240137100219727,
    },
]

video_bytes = []
for r in rows:
    with open(r["video_path"], "rb") as f:
        video_bytes.append(f.read())

table = pa.table(
    {
        "caption": [r["caption"] for r in rows],
        "aesthetic_score": [r["aesthetic_score"] for r in rows],
        "video_blob": video_bytes,
    },
    schema=schema,
)

ds = lance.write_dataset(
    table,
    "./videos.lance",
    schema=schema,
    mode="create",
)
```

`videos.lance/` 안에 메타데이터와 비디오 바이트를 함께 저장하므로, 별도의 `*.mp4` 파일을 동기화할 필요 없이 단일 디렉터리만 이동/복사하면 됩니다.

Lance 테이블에 비디오를 저장할 때의 대표적인 예시를 보여 드리겠습니다(`video_blob` 컬럼에는 Lance 데이터셋 내에서 네이티브로 blob으로 저장되는 데이터가 포함되어 있습니다):

```text
+------------------------------------------+-----------------+-----+------------------------------------------+
| caption                                  | aesthetic_score | ... | video_blob                               |
+------------------------------------------+-----------------+-----+------------------------------------------+
| "a breathtaking view of a mounta..."     | 5.2401          | ... | {position: 0, size: 4873879}             |
| "a captivating view of the sun, b..."    | 5.2401          | ... | {position: 4873920, size: 3370571}       |
+------------------------------------------+-----------------+-----+------------------------------------------+
```

생성된 `videos.lance/` 디렉터리를 Hub에 업로드(예: `huggingface_hub.HfApi.upload_folder` 사용)하고 데이터셋 저장소로 공유할 수 있습니다. 이렇게 하면 메타데이터와 비디오가 단일 아티팩트로 함께 유지됩니다.

> [!TIP]
> Lance 데이터셋은 데이터가 디스크에 컬럼형 형식으로 저장되므로 테라바이트 이상으로 확장할 수 있습니다. Lance에서 대용량 blob을 저장하고 검색하는 데 대한 모범 사례의 최신 정보는 [blob API](https://lance.org/guide/blob/) 가이드를 참고하세요.

대용량 데이터셋을 작성할 때는 각 `*.lance` 파일의 크기를 기가바이트 몇 개로 제한하는 것이 일반적으로 가장 좋습니다. 반복자를 통해 데이터를 수집한 다음, 데이터셋을 작성할 때 `max_bytes_per_file` 매개변수를 지정하면 됩니다:

```python
MAX_BYTES_PER_FILE = 5 * 1024 * 1024 * 1024  # ~5 GB per file

# Write as Lance dataset with file size limits for each *.lance file
ds = lance.write_dataset(
    table,
    "./videos.lance",
    schema=schema,
    mode="create",
    max_bytes_per_file=MAX_BYTES_PER_FILE,
)
```

Lance 데이터셋을 다루는 방법에 대한 자세한 내용은 [Lance 문서](https://lance.org)를 참고하세요.

