Datasets documentation

Tải dữ liệu video

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v4.8.4).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Tải dữ liệu video

Hỗ trợ video đang ở giai đoạn thử nghiệm và có thể thay đổi.

Bộ dữ liệu video có các cột kiểu Video, chứa các đối tượng torchcodec.

Để làm việc với các bộ dữ liệu video, bạn cần cài đặt các gói torchcodec và ffmpeg. Xem hướng dẫn cài đặt để biết cách cài đặt chúng.

Khi bạn tải một tập dữ liệu video và gọi cột video, các video sẽ được giải mã thành các Video 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>

Truy cập vào bộ dữ liệu video bằng cách sử dụng chỉ số hàng trước, sau đó là cột video - dataset[0]["video"] - để tránh tạo ra tất cả các đối tượng video trong bộ dữ liệu. Nếu không, đây có thể là một quy trình chậm và tốn thời gian nếu bạn có một bộ dữ liệu lớn.

Để tìm hiểu cách tải bất kỳ loại bộ dữ liệu nào, hãy xem hướng dẫn tải chung.

Đọc các khung hình

Truy cập trực tiếp các khung hình từ một video bằng VideoReader sử dụng 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

Để lấy nhiều khung hình cùng lúc, bạn có thể gọi .get_frames_in_range(start: int, stop: int, step: int). Thao tác này sẽ trả về một lô khung hình. Đây là cách hiệu quả để lấy một danh sách dài các khung hình, hãy tham khảo tài liệu torchcodec để xem thêm các hàm khác cho phép truy cập dữ liệu một cách hiệu quả:

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

Ngoài ra còn có .get_frames_played_in_range(start_seconds: float, stop_seconds: float) để truy cập tất cả các khung hình đã được phát trong một khoảng thời gian nhất định.

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

Tệp cục bộ

Bạn có thể tải một tập dữ liệu từ đường dẫn video. Sử dụng hàm cast_column() để nhận một cột chứa các đường dẫn tệp video, và giải mã nó thành video torchcodec với tính năng 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>

Nếu bạn chỉ muốn tải đường dẫn gốc của tập dữ liệu video mà không giải mã đối tượng video, hãy đặt decode=False trong tính năng Video:

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

VideoFolder

Bạn cũng có thể tải một tập dữ liệu bằng trình xây dựng tập dữ liệu VideoFolder, không yêu cầu viết một dataloader tùy chỉnh. Điều này khiến VideoFolder trở nên lý tưởng để nhanh chóng tạo và tải các tập dữ liệu video với hàng nghìn video cho các tác vụ thị giác khác nhau. Cấu trúc tập dữ liệu video của bạn nên trông như sau:

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

Nếu bộ dữ liệu tuân theo cấu trúc VideoFolder, bạn có thể tải nó trực tiếp bằng load_dataset():

>>> from datasets import load_dataset

>>> dataset = load_dataset("username/dataset_name")
>>> # OR locally:
>>> dataset = load_dataset("/path/to/folder")

Đối với các bộ dữ liệu cục bộ, điều này tương đương với việc truyền videofolder thủ công trong load_dataset() và thư mục trong data_dir:

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

Sau đó, bạn có thể truy cập các video dưới dạng các đối tượng 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}

Để bỏ qua thông tin trong tệp metadata, đặt drop_metadata=True trong load_dataset():

>>> from datasets import load_dataset

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

Nếu bạn không có tệp metadata, VideoFolder sẽ tự động suy ra tên nhãn từ tên thư mục. Nếu bạn muốn loại bỏ các nhãn được tạo tự động, hãy đặt drop_labels=True. Trong trường hợp này, tập dữ liệu của bạn sẽ chỉ chứa một cột video:

>>> from datasets import load_dataset

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

Cuối cùng, đối số filters cho phép bạn chỉ tải một tập con của bộ dữ liệu, dựa trên điều kiện về nhãn hoặc metadata. Điều này đặc biệt hữu ích nếu metadata ở định dạng Parquet, vì định dạng này cho phép lọc nhanh. Cũng nên sử dụng đối số này cùng với streaming=True, vì mặc định bộ dữ liệu sẽ được tải xuống hoàn toàn trước khi lọc.

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

Để biết thêm thông tin về việc tạo bộ dữ liệu VideoFolder của riêng bạn, hãy xem hướng dẫn Tạo bộ dữ liệu video.

WebDataset

Định dạng WebDataset dựa trên một thư mục chứa các tệp lưu trữ TAR và phù hợp cho các bộ dữ liệu video lớn. Do kích thước của chúng, WebDataset thường được tải ở chế độ streaming (sử dụng streaming=True).

Bạn có thể nạp một WebDataset như sau:

>>> from datasets import load_dataset

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

Lance

Lance là định dạng bảng lakehouse đa phương thức mã nguồn mở. Bảng Lance có thể lưu trữ bản địa không chỉ văn bản và giá trị vô hướng, mà còn cả các đối tượng nhị phân lớn (blobs) như hình ảnh, âm thanh và video cùng với dữ liệu bảng của bạn. Bên trong một bảng Lance, các blob lớn như video được lưu trữ dưới dạng byte kèm theo offset (xem hướng dẫn về blob để biết thêm chi tiết), nhờ đó việc quét và lọc metadata trở nên dễ dàng mà không cần tải các blob video nặng, và sau đó chỉ lấy các blob video cụ thể bạn cần theo yêu cầu.

Ngoài ra, vì Lance là một định dạng cột, bạn có thể chỉ chiếu và lọc các cột metadata mà bạn quan tâm (mà không cần tải các tệp video lớn), sau đó truy xuất một tập con nhỏ các dòng (bao gồm cả video) khi bạn sẵn sàng. Điều này giúp bạn giữ metadata và video ở một nơi, mà không cần một kho lưu trữ tệp riêng biệt hay một chỉ mục bên ngoài.

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

Trong ví dụ này, video được lưu trữ dạng gốc (dưới dạng byte đã mã hóa) trong bảng Lance, vì vậy bạn có thể ghi trực tiếp nó vào một tệp mp4 trên hệ thống tệp cục bộ mà không cần bước chuyển đổi bổ sung nào.

Để biết thêm chi tiết về việc làm việc với bộ dữ liệu Lance, hãy xem tài liệu Lance.

Giải mã video

Mặc định, video được giải mã tuần tự dưới dạng VideoDecoders của torchcodec khi bạn lặp qua một tập dữ liệu. Nó giải mã tuần tự metadata của các video và không đọc các khung hình video cho đến khi bạn truy cập chúng.

Tuy nhiên, có thể tăng tốc bộ dữ liệu đáng kể bằng cách giải mã đa luồng:

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

Bạn có thể bật đa luồng bằng cách sử dụng num_threads. Điều này đặc biệt hữu ích để tăng tốc độ truyền dữ liệu từ xa. Tuy nhiên, nó có thể chậm hơn so với num_threads=0 đối với dữ liệu cục bộ trên các ổ đĩa nhanh.

Nếu bạn không quan tâm đến các video được giải mã dưới dạng VideoDecoders của torchcodec và muốn truy cập đường dẫn/bytes thay vào đó, bạn có thể tắt giải mã:

>>> dataset = dataset.decode(False)

Lưu ý: IterableDataset.decode() hiện chỉ khả dụng cho các bộ dữ liệu dạng streaming.

Update on GitHub