def __iter__(self) -> Iterator[Union[int, tuple[int, int, str]]]:
        """
        Iterate over video frames and yield key frames or indexes.

        Yields:
            Union[Tuple[int, int, str], int]: (frame index, frame timestamp, frame MD5) or frame index.
        """
        # Open containers for reading frames and checking movement on them
        with (
            closing(av.open(self.source_path, mode="r")) as reading_container,
            closing(av.open(self.source_path, mode="r")) as checking_container,
        ):
            reading_v_stream = self._get_video_stream(reading_container)
            checking_v_stream = self._get_video_stream(checking_container)
            prev_pts: Optional[int] = None
            prev_dts: Optional[int] = None
            index, key_frame_count = 0, 0

            for packet in reading_container.demux(reading_v_stream):
                for frame in packet.decode():
                    # Check PTS and DTS sequences for validity
                    if None not in {frame.pts, prev_pts} and frame.pts <= prev_pts:
                        raise InvalidVideoError("Detected non-increasing PTS sequence in the video")
                    if None not in {frame.dts, prev_dts} and frame.dts <= prev_dts:
                        raise InvalidVideoError("Detected non-increasing DTS sequence in the video")
                    prev_pts, prev_dts = frame.pts, frame.dts

                    if frame.key_frame:
                        key_frame_data = {
                            "pts": frame.pts,
                            "md5": md5_hash(frame),
                        }

                        # Check that it is possible to seek to this key frame using frame.pts
                        checking_container.seek(
                            offset=key_frame_data["pts"],
                            stream=checking_v_stream,
                        )
                        is_valid_key_frame = self.validate_key_frame(
                            checking_container,
                            checking_v_stream,
                            key_frame_data,
                        )

                        if is_valid_key_frame:
                            key_frame_count += 1
                            yield (index, key_frame_data["pts"], key_frame_data["md5"])
                        else:
                            yield index
                    else:
                        yield index

                    index += 1
                    key_frame_ratio = index // (key_frame_count or 1)

                    # Check if the number of key frames meets the upper bound
                    if key_frame_ratio >= self._upper_bound and not self._force:
                        raise InvalidVideoError(
                            "The number of keyframes is not enough for smooth iteration over the video"
                        )

            # Update frames number if not already set
            if not self._frames_number:
                self._frames_number = index

        Iterate over video frames and yield key frames or indexes.

        Yields:
            Union[Tuple[int, int, str], int]: (frame index, frame timestamp, frame MD5) or frame index.
        
utils/dataset_manifest/core.py