Datasets documentation
Cargar datos de video
Cargar datos de video
El soporte para video es experimental y está sujeto a cambios.
Los conjuntos de datos de video tienen columnas de tipo Video, que contienen objetos torchcodec.
Para trabajar con conjuntos de datos de video, es necesario tener instalados los paquetes
torchcodecyffmpeg. Consulta la guía de instalación para aprender a instalarlos.
Cuando cargas un conjunto de datos de video y llamas a la columna de video, los videos se decodifican como Videos de torchcodec:
>>> 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>Índice en un conjunto de datos de video usando primero el índice de fila y luego la columna
video-dataset[0]["video"]- para evitar crear todos los objetos de video en el conjunto de datos. De lo contrario, este puede ser un proceso lento y que consume mucho tiempo si tiene un conjunto de datos grande.
Para una guía sobre cómo cargar cualquier tipo de conjunto de datos, consulte la guía general de carga.
Leer fotogramas
Acceda a los fotogramas directamente desde un video usando VideoReader con 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.0Para obtener varios fotogramas a la vez, puede llamar a .get_frames_in_range(start: int, stop: int, step: int). Esto devolverá un lote de fotogramas.
Esta es la forma eficiente de obtener una lista larga de fotogramas; consulte la documentación de torchcodec para ver más funciones para acceder a los datos de manera eficiente:
>>> import torch
>>> frames = video.get_frames_in_range(0, 6, 1)
>>> frames.data.shape
torch.Size([5, 3, 240, 320])También existe .get_frames_played_in_range(start_seconds: float, stop_seconds: float) para acceder a todos los frames reproducidos dentro de un cierto rango de tiempo.
>>> frames = video.get_frames_played_in_range(.5, 1.2)
>>> frames.data.shape
torch.Size([42, 3, 240, 320])Archivos locales
Puedes cargar un conjunto de datos desde la ruta del video. Utiliza la función cast_column() para aceptar una columna de rutas de archivos de video y decodificarla en un video torchcodec con la función 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>Si solo desea cargar la ruta subyacente del conjunto de datos de video sin decodificar el objeto de video, establezca decode=False en la característica Video:
>>> dataset = dataset.cast_column("video", Video(decode=False))
>>> dataset[0]["video"]
{'bytes': None,
'path': 'path/to/video/folder/video0.mp4'}VideoFolder
También puede cargar un conjunto de datos con el creador de conjuntos de datos VideoFolder, que no requiere escribir un dataloader personalizado. Esto hace que VideoFolder sea ideal para crear y cargar rápidamente conjuntos de datos de video con varios miles de videos para diferentes tareas de visión. La estructura de su conjunto de datos de video debe ser así:
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.mp4Si el conjunto de datos sigue la estructura VideoFolder, puede cargarlo directamente con load_dataset():
>>> from datasets import load_dataset
>>> dataset = load_dataset("username/dataset_name")
>>> # OR locally:
>>> dataset = load_dataset("/path/to/folder")Para conjuntos de datos locales, esto es equivalente a pasar videofolder manualmente en load_dataset() y el directorio en data_dir:
>>> dataset = load_dataset("videofolder", data_dir="/path/to/folder")Luego puedes acceder a los videos como objetos 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}Para ignorar la información en el archivo de metadatos, establezca drop_metadata=True en load_dataset():
>>> from datasets import load_dataset
>>> dataset = load_dataset("username/dataset_with_metadata", drop_metadata=True)Si no tiene un archivo de metadatos, VideoFolder infiere automáticamente el nombre de la etiqueta a partir del nombre del directorio.
Si desea eliminar las etiquetas creadas automáticamente, establezca drop_labels=True.
En este caso, su conjunto de datos solo contendrá una columna de video:
>>> from datasets import load_dataset
>>> dataset = load_dataset("username/dataset_without_metadata", drop_labels=True)Por último, el argumento filters permite cargar solo un subconjunto del conjunto de datos, basado en una condición sobre la etiqueta o los metadatos. Esto es especialmente útil si los metadatos están en formato Parquet, ya que este formato permite un filtrado rápido. También se recomienda usar este argumento con streaming=True, porque por defecto el conjunto de datos se descarga por completo antes de aplicar el filtrado.
>>> filters = [("label", "=", 0)]
>>> dataset = load_dataset("username/dataset_name", streaming=True, filters=filters)Para obtener más información sobre cómo crear tu propio conjunto de datos
VideoFolder, consulta la guía Crear un conjunto de datos de video.
WebDataset
El formato WebDataset se basa en una carpeta de archivos TAR y es adecuado para grandes conjuntos de datos de video.
Debido a su tamaño, los WebDatasets generalmente se cargan en modo de transmisión (usando streaming=True).
Puedes cargar un WebDataset de esta manera:
>>> from datasets import load_dataset
>>> dataset = load_dataset("webdataset", data_dir="/path/to/folder", streaming=True)Lance
Lance es un formato de tabla de lakehouse multimodal abierto. Las tablas Lance pueden almacenar de forma nativa no solo texto y valores escalares, sino también objetos binarios grandes (blobs) como imágenes, audio y video junto a sus datos tabulares. Dentro de una tabla Lance, los blobs grandes como los videos se almacenan como bytes con desplazamientos (consulte la guía de blobs para más detalles), lo que facilita escanear y filtrar metadatos sin cargar los blobs de video más pesados, y luego recuperar solo los blobs de video específicos que necesite bajo demanda.
Además, dado que Lance es un formato columnar, puedes proyectar y filtrar solo las columnas de metadatos que te interesan (sin tener que recuperar archivos de video grandes) y, cuando estés listo, obtener un subconjunto pequeño de filas (incluido el video). Esto mantiene tus metadatos y videos en un solo lugar, sin necesidad de un almacén de archivos separado ni de un índice externo.
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())En este ejemplo, el video se almacena de forma nativa (como sus bytes codificados) en la tabla Lance, por lo que puedes escribirlo directamente en un archivo mp4 en tu sistema de archivos local sin ningún paso de conversión adicional.
Para más detalles sobre el trabajo con conjuntos de datos Lance, consulte la documentación de Lance.
Decodificación de video
Por defecto, los vídeos se decodifican de forma secuencial como VideoDecoders de torchcodec al iterar sobre un conjunto de datos.
Decodifica secuencialmente los metadatos de los vídeos y no lee los fotogramas del vídeo hasta que accedes a ellos.
Sin embargo, es posible acelerar significativamente el conjunto de datos mediante la decodificación multihilo:
>>> 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 !
... ...Puede habilitar el multihilo usando num_threads. Esto es especialmente útil para acelerar el streaming de datos remotos.
Sin embargo, puede ser más lento que num_threads=0 para datos locales en discos rápidos.
Si no le interesan los videos decodificados como VideoDecoders de torchcodec y prefiere acceder a la ruta/bytes en su lugar, puede deshabilitar la decodificación:
>>> dataset = dataset.decode(False)Nota: IterableDataset.decode() solo está disponible actualmente para conjuntos de datos en streaming.
Update on GitHub