NVIDIA / NVIDIA/DALI

Load Videos from External Source

Open
#5,126 2 comments 0 reactions 1 assignee View on GitHub

@mzient is already working on this.

Since Oct 26, 2023.

question Video
Dominant language
C++
Stars
5.8k
Forks
678
Avg merge
3d 1h
Merged PRs (30d)
27

Description

Describe the question.

I have a json file describing the whole video retrieval dataset. Part of the json is listed below:

[
    {
        "video": "/data/14111B1211bJYB4F5841E4-43JBb12C31842F2aFB58a5E38aB3F-a1EB7JCY1E5C7.mp4",
        "caption": "A woman is reading a book."
    },
    {
        "video": "/data/14111B1211bJYBBEJ8A-4CYb23Y---5C2b715-a-B7Fa5J7Ea-CEBaCF-F-8YYBbbF.mp4",
        "caption": "Students are discussing with each other."
    },
]

I don't know how to load the dataset using the json file in DALI pipeline.

I implement an external source input iterator:

class VideoTextInputIterator(object):
    def __init__(self, metadata_path, batch_size, shuffle=False):
        self.batch_size = batch_size
        self.shuffle = shuffle

        with open(metadata_path) as f:
            self.data_list = json.load(f)
        if shuffle:
            random.shuffle(self.data_list)
        self.length = len(self.data_list)

    def __iter__(self):
        self.i = 0
        return self

    def __len__(self):
        return len(self.data_list)

    def __next__(self):
        # stop iteration
        if self.i >= self.length:
            self.__iter__()
            raise StopIteration

        batch_videos = []
        batch_captions = []

        # avoid iterator overflow
        process_size = min(self.batch_size, self.length - self.i)
        for _ in range(process_size):
            data = self.data_list[self.i]
            video = data["video"]  # video path
            caption = data["caption"]  # video caption
            batch_videos.append(video)
            batch_captions.append(caption)
            self.i += 1

        return batch_videos, batch_captions

    next = __next__
    len = __len__

Then I use it in a DALI pipeline:

@pipeline_def
def create_video_text_pipeline(metadata_path, shuffle):
    pipe = Pipeline.current()
    videos, labels = fn.external_source(
        source=VideoTextInputIterator(
            metadata_path=metadata_path,
            batch_size=pipe.batch_size,
            shuffle=shuffle,
        ),
        num_outputs=2,
        dtype=[types.STRING, types.STRING]
    )
    videos, labels = fn.readers.video(
        sequence_length=4,
        device="gpu",
        filenames=videos
        normalized=False,
        random_shuffle=True,
        image_type=types.RGB,
        name="Reader",
    )
    return videos, labels

I run the pipe and get an error:

pipe = create_video_text_pipeline(
    metadata_path="/path/to/json/meta.json",
    batch_size=8,
    device_id=0,
    num_threads=1,
)
pipe.build()
out = pipe.run()
TypeError: The argument `filenames` for operator `Video` should not be a `DataNode` but a str or list of str

I read the documentation over and over again and can't find the best solution.
Maybe I need some help. Thank you guys !! :)

Check for duplicates
  • I have searched the open bugs/issues and have found no duplicates for this bug report

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.