Datasets documentation

创建视频数据集

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

创建视频数据集

本指南将展示如何使用 VideoFolder 创建包含一些元数据的视频数据集。这是一种无需编写代码的解决方案,可快速创建包含数千个视频的数据集。

您可以通过要求用户先共享其联系信息来控制对数据集的访问权限。有关如何在 Hub 上启用此功能的更多信息,请参阅 Gated datasets 指南。

VideoFolder

VideoFolder 是一个数据集构建器,旨在快速加载包含数千个视频的数据集,且无需编写任何代码。

💡 查看 Split pattern hierarchy 以了解 VideoFolder 如何根据数据集仓库结构创建数据集划分。

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() 加载:

>>> from datasets import load_dataset

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

这相当于在 load_dataset() 中手动传入 videofolder 以及 data_dir 中的目录:

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

您还可以使用 videofolder 来加载涉及多个 split 的数据集。为此,您的数据集目录应具有以下结构:

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

如果所有视频文件都位于同一个目录中,或者它们不在同一层级的目录结构中,则不会自动添加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 字段,用于将视频文件与其元数据关联起来:

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:

{"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 必须是位于元数据文件旁边的视频文件的名称。更一般地,它必须是包含元数据的目录到视频文件的相对路径。

在数据集中的每一行中,可以指向多个视频,例如当输入和输出都是视频时:

{"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。示例如下:

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

视频字幕

视频字幕数据集包含描述视频的文字。metadata.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 列用于视频字幕:

>>> 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 库,并已登录您的 Hugging Face 账户(更多详情请参阅 Upload with Python tutorial)。

使用 huggingface_hub.HfApi.upload_folder 上传您的数据集:

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 格式基于 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 文档。

加载您的 WebDataset,它会为每个文件后缀(此处为“mp4”和“json”)创建一个列:

>>> 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 是一种开放的多模态数据湖仓表格式。Lance 表不仅可以原生存储文本和标量值,还可以与您的表格数据一起存储大型二进制对象(blob),例如图像、音频和视频。

Lance 提供了一个 blob API,方便在 Lance 数据集中存储和检索大型 blob。 以下示例展示了如何在不加载较重的视频 blob 的情况下高效浏览元数据,然后按需获取相关的视频 blob。

以下是存储视频的 Lance 表的典型视图(video_blob 列使用 Lance 的 blob 编码):

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

从原始视频文件写入 Lance 数据集

从磁盘上的原始视频文件及其关联元数据(例如字幕和评分)出发,您可以将一个自包含的 Lance 数据集写入本地的 *.lance 目录(Lance 数据集是磁盘上的一个目录,通常以 .lance 后缀命名):

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 列包含以 blob 形式原生存储在 Lance 数据集内的数据):

+------------------------------------------+-----------------+-----+------------------------------------------+
| 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),并将其作为数据集仓库共享,从而将元数据和视频作为单个工件一起保存。

Lance 数据集可扩展至非常大的规模(TB 级别及以上),因为数据以列式格式存储在磁盘上。 有关在 Lance 中存储和检索大型 blob 的最佳实践的最新信息,请参阅 blob API 指南。

在写入大型数据集时,通常最好将每个单独的 *.lance 文件的大小限制在几 GB 以内。 只需通过迭代器收集数据,并在写入数据集时指定 max_bytes_per_file 参数即可:

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 文档。

Update on GitHub