Datasets documentation

비디오 데이터 로드

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

비디오 데이터 로드

Video 지원은 실험적이며 변경될 수 있습니다.

Video 데이터셋에는 torchcodec 객체를 포함하는 Video 타입의 컬럼이 있습니다.

비디오 데이터셋을 다루려면 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>

dataset[0]["video"]와 같이 행 인덱스를 먼저 사용하고 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)을 호출할 수 있습니다. 이 메서드는 프레임 배치(frame batch)를 반환합니다. 긴 프레임 목록을 효율적으로 가져오는 방법입니다. 데이터를 효율적으로 접근하기 위한 추가 함수는 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() 함수를 사용하여 비디오 파일 경로 컬럼을 받아 Video 기능으로 torchcodec 비디오로 디코딩합니다:

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

비디오 객체를 디코딩하지 않고 비디오 데이터셋의 기본 경로만 로드하려면 Video 기능에서 decode=False를 설정하세요:

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

VideoFolder

VideoFolder dataset builder를 사용하여 커스텀 dataloader를 작성하지 않고도 dataset을 로드할 수 있습니다. 이를 통해 VideoFolder은 다양한 vision task에 대해 수천 개의 비디오로 구성된 video dataset을 빠르게 생성하고 로드하는 데 이상적입니다. 비디오 dataset 구조는 다음과 같아야 합니다:

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")

로컬 데이터셋의 경우, 이는 load_dataset()에서 videofolder를 수동으로 전달하고 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}

메타데이터 파일의 정보를 무시하려면 load_dataset()에서 drop_metadata=True를 설정하세요:

>>> 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 아카이브 폴더를 기반으로 하며, 대규모 비디오 데이터셋에 적합합니다. 크기가 크기 때문에 WebDataset은 일반적으로 스트리밍 모드( streaming=True 사용)로 로드됩니다.

WebDataset를 다음과 같이 로드할 수 있습니다:

>>> from datasets import load_dataset

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

Lance

Lance는 오픈 멀티모달 레이크하우스 테이블 형식입니다. Lance 테이블은 텍스트와 스칼라 값뿐만 아니라 이미지, 오디오, 비디오와 같은 대형 바이너리 객체(blobs)도 테이블 데이터와 함께 네이티브로 저장할 수 있습니다. Lance 테이블 내부에서 비디오와 같은 대형 blobs는 오프셋을 가진 바이트로 저장됩니다(blob 가이드에서 자세한 내용을 확인하세요). 이를 통해 무거운 비디오 blobs를 로드하지 않고도 메타데이터를 스캔하고 필터링할 수 있으며, 필요할 때에만 특정 비디오 blobs만 가져올 수 있습니다.

또한 Lance는 컬럼형(columnar) 형식이기 때문에, 관심 있는 메타데이터 컬럼만 투영(projection)하고 필터링할 수 있습니다(대용량 비디오 파일을 가져오지 않고도). 준비가 되면 비디오를 포함한 소수의 행만 가져오면 됩니다. 이를 통해 별도의 파일 저장소나 외부 인덱스 없이 메타데이터와 비디오를 한 곳에 유지할 수 있습니다.

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로 순차적으로 디코딩됩니다. 비디오의 메타데이터를 순차적으로 디코딩하며, 비디오 프레임을 직접 접근하기 전까지는 읽지 않습니다.

그러나 멀티스레드 디코딩을 사용하면 데이터셋을 상당히 빠르게 처리할 수 있습니다:

>>> 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보다 느려질 수 있습니다.

torchcodec VideoDecoders로 디코딩된 비디오에 관심이 없고 대신 경로/바이트에 액세스하려면 디코딩을 비활성화할 수 있습니다:

>>> dataset = dataset.decode(False)

참고: IterableDataset.decode()는 현재 스트리밍 데이터셋에서만 사용할 수 있습니다.

Update on GitHub