Datasets documentation

Загрузка данных видео

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Загрузка данных видео

Поддержка видео является экспериментальной и может быть изменена.

Наборы данных видео имеют столбцы типа Video, которые содержат объекты torchcodec.

Для работы с наборами данных видео необходимо установить пакеты torchcodec и ffmpeg. Ознакомьтесь с руководством по установке, чтобы узнать, как их установить.

При загрузке набора данных с видео и обращении к столбцу с видео, видео декодируются как torchcodec Videos:

>>> from datasets import load_dataset, Video

>>> dataset = load_dataset("path/to/video/folder", split="train")
>>> dataset[0]["video"]
<torchcodec.decoders._video_decoder.VideoDecoder object at 0x14a61d5a0>

Обращайтесь к набору данных видео сначала по индексу строки, а затем по столбцу video — dataset[0]["video"] — чтобы избежать создания всех объектов видео в наборе данных. В противном случае, если у вас большой набор данных, этот процесс может быть медленным и требовать много времени.

Справочник по загрузке любого типа набора данных — в общем руководстве по загрузке.

Чтение кадров

Обращайтесь к кадрам видео напрямую с помощью VideoReader, используя next():

>>> video = dataset[0]["video"]
>>> first_frame = video.get_frame_at(0)
>>> first_frame.data.shape
(3, 240, 320)
>>> first_frame.pts_seconds  # timestamp
0.0

Чтобы получить несколько кадров за один раз, можно вызвать .get_frames_in_range(start: int, stop: int, step: int). Это вернёт пакет кадров. Это эффективный способ получить длинный список кадров. См. документацию torchcodec, чтобы узнать о других функциях для эффективного доступа к данным:

>>> import torch
>>> frames = video.get_frames_in_range(0, 6, 1)
>>> frames.data.shape
torch.Size([5, 3, 240, 320])

Также существует .get_frames_played_in_range(start_seconds: float, stop_seconds: float) для доступа ко всем кадрам, воспроизведённым в определённом временном диапазоне.

>>> frames = video.get_frames_played_in_range(.5, 1.2)
>>> frames.data.shape
torch.Size([42, 3, 240, 320])

Локальные файлы

Вы можете загрузить набор данных из пути к видео. Используйте функцию cast_column(), чтобы принять столбец с путями к файлам видео и декодировать его в видео torchcodec с фичей Video:

>>> from datasets import Dataset, Video

>>> dataset = Dataset.from_dict({"video": ["path/to/video_1", "path/to/video_2", ..., "path/to/video_n"]}).cast_column("video", Video())
>>> dataset[0]["video"]
<torchcodec.decoders._video_decoder.VideoDecoder object at 0x14a61e080>

Если вам нужно загрузить только базовый путь к набору данных видео без декодирования объекта видео, установите decode=False в фиче Video:

>>> dataset = dataset.cast_column("video", Video(decode=False))
>>> dataset[0]["video"]
{'bytes': None,
 'path': 'path/to/video/folder/video0.mp4'}

VideoFolder

Также можно загрузить набор данных с помощью конструктора 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("username/dataset_name")
>>> # OR locally:
>>> dataset = load_dataset("/path/to/folder")

Для локальных наборов данных это эквивалентно ручной передаче videofolder в load_dataset() и директории в data_dir:

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

Затем вы можете обращаться к видео как к объектам torchcodec.decoders._video_decoder.VideoDecoder:

>>> dataset["train"][0]
{"video": <torchcodec.decoders._video_decoder.VideoDecoder object at 0x14a61e080>, "label": 0}

>>> dataset["train"][-1]
{"video": <torchcodec.decoders._video_decoder.VideoDecoder object at 0x14a61e090>, "label": 1}

Чтобы игнорировать информацию в файле метаданных, установите drop_metadata=True в load_dataset():

>>> from datasets import load_dataset

>>> dataset = load_dataset("username/dataset_with_metadata", drop_metadata=True)

Если у вас нет файла метаданных, VideoFolder автоматически определяет имя метки по имени каталога. Если вы хотите отбросить автоматически созданные метки, установите drop_labels=True. В этом случае ваш набор данных будет содержать только столбец с видео:

>>> from datasets import load_dataset

>>> dataset = load_dataset("username/dataset_without_metadata", drop_labels=True)

Наконец, аргумент filters позволяет загрузить только часть набора данных на основе условия, наложенного на метку или метаданные. Это особенно полезно, если метаданные хранятся в формате Parquet, поскольку этот формат обеспечивает быструю фильтрацию. Также рекомендуется использовать этот аргумент вместе с streaming=True, так как по умолчанию набор данных полностью загружается до применения фильтрации.

>>> filters = [("label", "=", 0)]
>>> dataset = load_dataset("username/dataset_name", streaming=True, filters=filters)

Для получения дополнительной информации о создании собственного набора данных VideoFolder ознакомьтесь с руководством Создание набора данных видео.

WebDataset

Формат WebDataset основан на папке с TAR-архивами и подходит для больших наборов данных с видео. Из-за своего размера WebDatasets, как правило, загружаются в режиме потоковой передачи (с использованием streaming=True).

Вы можете загрузить WebDataset следующим образом:

>>> from datasets import load_dataset

>>> dataset = load_dataset("webdataset", data_dir="/path/to/folder", streaming=True)

Lance

Lance — это открытый формат таблиц для мультимодальных lakehouse-хранилищ. Таблицы Lance могут нативно хранить не только текст и скалярные значения, но и крупные бинарные объекты (blobs), такие как изображения, аудио и видео, наряду с табличными данными. Внутри таблицы Lance крупные объекты, например видео, хранятся в виде байтов со смещениями (см. руководство по blob для подробностей), что позволяет легко просматривать и фильтровать метаданные без загрузки тяжёлых видео-блобов, а затем по запросу извлекать только нужные видео-блобы.

Кроме того, поскольку Lance представляет собой колоночный формат, вы можете выполнять проекцию и фильтрацию только тех колонок метаданных, которые вас интересуют (без загрузки крупных файлов видео), а затем извлекать небольшой подмножество строк (включая видео), когда будете готовы. Это позволяет хранить метаданные и видео в одном месте, без необходимости использовать отдельное файловое хранилище или внешний индекс.

import lance

ds = lance.dataset("hf://datasets/lance-format/openvid-lance/data/train.lance")

# 1. Browse metadata without loading video blobs.
metadata = ds.scanner(
    columns=["caption", "aesthetic_score"],
    filter="aesthetic_score >= 4.5",
    limit=2,
).to_table().to_pylist()

# 2. Fetch a single video blob by row index.
selected_index = 0
blob_file = ds.take_blobs("video_blob", ids=[selected_index])[0]
with open("video_0.mp4", "wb") as f:
    f.write(blob_file.read())

В этом примере видео хранится в таблице Lance в нативном виде (в виде закодированных байтов), поэтому вы можете записать его напрямую в файл mp4 на локальной файловой системе без дополнительных шагов конвертации.

Для получения подробной информации о работе с наборами данных Lance см. документацию Lance.

Декодирование видео

По умолчанию, при итерации по набору данных, видео декодируются последовательно как VideoDecoders torchcodec. Метаданные видео декодируются последовательно, а кадры видео не читаются, пока вы к ним не обратитесь.

Однако с помощью многопоточного декодирования можно значительно ускорить работу с набором данных:

>>> import os
>>> num_threads = num_threads = min(32, (os.cpu_count() or 1) + 4)
>>> dataset = dataset.decode(num_threads=num_threads)
>>> for example in dataset:  # up to 20 times faster !
...     ...

Вы можете включить многопоточность с помощью num_threads. Это особенно полезно для ускорения потоковой передачи удалённых данных. Однако для локальных данных на быстрых дисках это может работать медленнее, чем num_threads=0.

Если вас не интересуют видео, декодированные как VideoDecoders torchcodec, и вы хотите получить доступ к пути/байтам, вы можете отключить декодирование:

>>> dataset = dataset.decode(False)

Примечание: IterableDataset.decode() в настоящее время доступен только для потоковых наборов данных.

Update on GitHub