Datasets documentation
Загрузка данных видео
Загрузка данных видео
Поддержка видео является экспериментальной и может быть изменена.
Наборы данных видео имеют столбцы типа 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