Conversation

Dan-Flores

This PR enables the instantiation of a VideoDecoder without num_frames_from_content or num_frames_from_header in the metadata, to resolve issue #727. Without these variables, the VideoDecoder will calculate the number of frames using average_fps_from_header and duration_seconds_from_header.

Tests in test_decoders.py

  • The return value of _get_stream_json_metadata is mocked to ensure VideoDecoder is instantiated without num_frames_from_content or num_frames_from_header.
  • Various get_frame... methods are tested on this decoder.

Tests in test_metadata.py

  • test_calculate_num_frames_using_fps_and_duration instantiates VideoStreamMetadata without num_frames_from_content or num_frames_from_header, and checks that various values of average_fps and duration_seconds result in the correct number of frames.

  • In test_num_frames_fallback, the test where both num_frames_from_content and num_frames_from_header are None is no longer valid. A similar test case is added in test_calculate_num_frames_using_fps_and_duration.

@facebook-github-botfacebook--bot added the CLA SignedThis label is managed by the Meta Open Source bot.label Jun 18, 2025
@@ -129,8 +129,15 @@ def num_frames(self) -> Optional[int]:
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the doc string, we should also say what we do if num_frames is missing from all of the metadata.

elif (
self.average_fps_from_header is not None
and self.duration_seconds_from_header is not None
):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just went down an interesting rabbit-hole of asking "Should we instead use the average_fps property?" And the answer is no! :) If self.average_fps_from_header is None, then self.average_fps actually calls this property, self.num_frames and we'd (I think) hit infinite recursion. I do wonder if there is a way for us to be more systematic about this, where we could more centrally define the logic of under what circumstances we use which metadata.

all_frames = decoder.get_frames_played_in_range(
decoder.metadata.begin_stream_seconds, decoder.metadata.end_stream_seconds
)
assert_frames_equal(all_frames.data, decoder[:])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add a simple assert len(decoder) == CORRECT_VALUE?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had initially approved, but it looks like the tests are failing on Mac - let's make sure we're using the right tolerances there.

@scotts

Thank you! Also, this is only half of #727. We also want to be able to handle if num_frames is present but duration is not. This half, though, is definitely the more valuable side, as core operations in the Python VideoDecoder depend on num_frames.

Sign up for free to join this conversation on . Already have an account? Sign in to comment
CLA SignedThis label is managed by the Meta Open Source bot.
None yet

Successfully merging this pull request may close these issues.