# Tạo bộ dữ liệu video

Hướng dẫn này sẽ cho bạn thấy cách tạo một tập dữ liệu video bằng `VideoFolder` cùng một số metadata. Đây là giải pháp không cần viết code để nhanh chóng tạo tập dữ liệu video gồm vài nghìn video.

> [!TIP]
> Bạn có thể kiểm soát quyền truy cập vào bộ dữ liệu của mình bằng cách yêu cầu người dùng chia sẻ thông tin liên hệ trước. Xem hướng dẫn [Gated datasets](https://huggingface.co/docs/hub/datasets-gated) để biết thêm thông tin về cách bật tính năng này trên Hub.

## VideoFolder

`VideoFolder` là một trình xây dựng tập dữ liệu được thiết kế để nhanh chóng nạp một tập dữ liệu video gồm vài nghìn video mà không yêu cầu bạn phải viết bất kỳ mã nào.

> [!TIP]
> 💡 Xem [Hierarchie mẫu Split](repository_structure#split-pattern-hierarchy) để tìm hiểu thêm về cách `VideoFolder` tạo các phần chia dataset dựa trên cấu trúc kho dataset của bạn.

`VideoFolder` tự động suy luận nhãn lớp của bộ dữ liệu dựa trên tên thư mục. Hãy lưu bộ dữ liệu của bạn trong cấu trúc thư mục như sau:

```
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
```

Nếu bộ dữ liệu tuân theo cấu trúc `VideoFolder`, bạn có thể tải nó trực tiếp bằng [load_dataset()](/docs/datasets/main/vi/package_reference/loading_methods#datasets.load_dataset):

```py
>>> from datasets import load_dataset

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

Điều này tương đương với việc truyền `videofolder` thủ công trong [load_dataset()](/docs/datasets/main/vi/package_reference/loading_methods#datasets.load_dataset) và thư mục trong `data_dir`:

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

Bạn cũng có thể sử dụng `videofolder` để tải các bộ dữ liệu liên quan đến nhiều phần chia. Để làm điều này, thư mục bộ dữ liệu của bạn nên có cấu trúc sau:

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

> [!WARNING]
> Nếu tất cả các tệp video nằm trong một thư mục duy nhất hoặc không cùng cấp trong cấu trúc thư mục, cột `label` sẽ không được thêm tự động. Nếu bạn cần cột này, hãy đặt `drop_labels=False` một cách tường minh.

Nếu có thêm thông tin bạn muốn bao gồm về bộ dữ liệu của mình, chẳng hạn như chú thích văn bản hoặc hộp bao quanh, hãy thêm chúng dưới dạng tệp `metadata.csv` trong thư mục của bạn. Điều này cho phép bạn nhanh chóng tạo các bộ dữ liệu cho các tác vụ thị giác máy tính khác nhau như chú thích văn bản hoặc phát hiện đối tượng. Bạn cũng có thể sử dụng tệp JSONL `metadata.jsonl` hoặc tệp Parquet `metadata.parquet`.

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

Tệp `metadata.csv` của bạn phải có trường `file_name` hoặc `*_file_name` để liên kết các tệp video với metadata của chúng:

```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
```

hoặc sử dụng `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"}
```

Ở đây, `file_name` phải là tên của tệp video nằm cạnh tệp metadata. Nói chung, nó phải là đường dẫn tương đối từ thư mục chứa metadata đến tệp video.

Bạn có thể trỏ đến nhiều hơn một video trong mỗi hàng của bộ dữ liệu, ví dụ nếu cả đầu vào và đầu ra của bạn đều là video:

```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"}
```

Bạn cũng có thể định nghĩa các danh sách video. Trong trường hợp đó, bạn cần đặt tên trường là `file_names` hoặc `*_file_names`. Dưới đây là một ví dụ:

```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"}
```

### Chú thích video

Bộ dữ liệu chú thích video có văn bản mô tả một video. Một ví dụ về `metadata.csv` có thể trông như sau:

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

Tải bộ dữ liệu bằng `VideoFolder`, và nó sẽ tạo một cột `text` cho chú thích video:

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

### Tải bộ dữ liệu lên Hub

Sau khi tạo xong một dataset, bạn có thể chia sẻ nó bằng cách sử dụng `huggingface_hub`, chẳng hạn. Hãy đảm bảo rằng bạn đã cài đặt thư viện [huggingface_hub](https://huggingface.co/docs/huggingface_hub/index) và đã đăng nhập vào tài khoản Hugging Face của mình (xem [hướng dẫn Upload with Python](upload_dataset#upload-with-python) để biết thêm chi tiết).

Tải lên bộ dữ liệu của bạn bằng `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

Định dạng [WebDataset](https://github.com/webdataset/webdataset) dựa trên các tệp lưu trữ TAR và phù hợp cho các bộ dữ liệu video lớn. Bạn có thể nhóm các video của mình vào các tệp lưu trữ TAR (ví dụ: 1GB video cho mỗi tệp lưu trữ TAR) và có hàng nghìn tệp lưu trữ TAR:

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

Trong kho lưu trữ, mỗi ví dụ được tạo thành từ các tệp chia sẻ cùng một tiền tố:

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

Bạn có thể đặt nhãn/mô tả/đặc trưng cho video của mình bằng cách sử dụng các tệp JSON hoặc văn bản, chẳng hạn.

Để biết thêm chi tiết về định dạng WebDataset và thư viện python, vui lòng xem [tài liệu WebDataset](https://webdataset.github.io/webdataset).

Nạp WebDataset của bạn và nó sẽ tạo ra một cột cho mỗi hậu tố tệp (ở đây là "mp4" và "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) là định dạng bảng lakehouse đa phương thức mã nguồn mở. Các bảng Lance có thể lưu trữ bản địa không chỉ văn bản và giá trị vô hướng mà còn cả các đối tượng nhị phân lớn (blobs) như hình ảnh, âm thanh và video cùng với dữ liệu bảng của bạn.

Lance cung cấp [blob API](https://lance.org/guide/blob/) giúp việc lưu trữ và truy xuất các blob lớn trong các dataset Lance trở nên thuận tiện. Ví dụ sau minh họa cách duyệt metadata một cách hiệu quả mà không cần tải các blob video nặng hơn, sau đó lấy các blob video liên quan theo yêu cầu.

Dưới đây là một cái nhìn đại diện về cách một bảng Lance lưu trữ video có thể trông như thế nào (cột `video_blob` sử dụng mã hóa blob của Lance):

```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}       |
+------------------------------------------+-----------------+-----+------------------------------------------+
```

### Viết một tập dữ liệu Lance từ các tệp video thô

Bắt đầu từ các tệp video thô trên đĩa cùng với các metadata liên quan (ví dụ: chú thích và điểm số), bạn có thể viết một dataset Lance tự chứa vào một thư mục `*.lance` cục bộ (một dataset Lance là một thư mục trên đĩa, và thông thường được đặt tên với hậu tố `.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",
)
```

Điều này lưu trữ metadata và byte video của bạn cùng nhau bên trong `videos.lance/`, cho phép bạn di chuyển/sao chép một thư mục duy nhất mà không cần phải đồng bộ hóa các tệp `*.mp4` riêng biệt.

Dưới đây là một cái nhìn đại diện về cách một bảng Lance lưu trữ video có thể trông như thế nào (cột `video_blob` chứa dữ liệu được lưu trữ dưới dạng blob gốc bên trong bộ dữ liệu Lance):

```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}       |
+------------------------------------------+-----------------+-----+------------------------------------------+
```

Bạn có thể tải thư mục `videos.lance/` kết quả lên Hub (ví dụ bằng `huggingface_hub.HfApi.upload_folder`) và chia sẻ nó như một kho dữ liệu, giữ nguyên metadata và video cùng nhau như một sản phẩm duy nhất.

> [!TIP]
> Bộ dữ liệu Lance có thể mở rộng lên kích thước rất lớn (terabyte và hơn thế) vì dữ liệu được lưu trữ trên đĩa theo định dạng cột. Xem hướng dẫn [blob API](https://lance.org/guide/blob/) để biết thông tin mới nhất về các thực hành tốt nhất khi lưu trữ và truy xuất các blob lớn trong Lance.

Khi ghi các bộ dữ liệu lớn, thường nên giới hạn kích thước của từng tệp `*.lance` riêng lẻ ở mức vài gigabyte trở xuống. Chỉ cần thu thập dữ liệu qua một trình lặp và chỉ định tham số `max_bytes_per_file` khi ghi bộ dữ liệu:

```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,
)
```

Để biết thêm chi tiết về việc làm việc với bộ dữ liệu Lance, hãy xem [tài liệu Lance](https://lance.org).

