@@ -119,18 +119,13 @@ def __init__(
119119 self ._path_or_device : str | int = resolved
120120 self ._is_device = isinstance (self ._path_or_device , int )
121121
122- # Initialized in _open_capture:
123- self ._cap : cv2 .VideoCapture | None = (
124- None # Reference to underlying cv2.VideoCapture object.
125- )
126- self ._frame_rate : Fraction | None = None
127-
128122 # VideoCapture state
129123 self ._has_grabbed = False
130124 self ._max_decode_attempts = max_decode_attempts
131125 self ._decode_failures = 0
132126 self ._warning_displayed = False
133127
128+ # `_open_capture` populates `_cap` and `_frame_rate`.
134129 self ._open_capture (framerate )
135130
136131 #
@@ -145,7 +140,6 @@ def capture(self) -> cv2.VideoCapture:
145140 backing this object. Seeking or using the read/grab methods through this property are
146141 unsupported and will leave this object in an inconsistent state.
147142 """
148- assert self ._cap
149143 return self ._cap
150144
151145 #
@@ -157,7 +151,6 @@ def capture(self) -> cv2.VideoCapture:
157151
158152 @property
159153 def frame_rate (self ) -> Fraction :
160- assert self ._frame_rate
161154 return self ._frame_rate
162155
163156 @property
@@ -189,7 +182,6 @@ def is_seekable(self) -> bool:
189182 @property
190183 def frame_size (self ) -> tuple [int , int ]:
191184 """Size of each video frame in pixels as a tuple of (width, height)."""
192- assert self ._cap is not None
193185 return (
194186 math .trunc (self ._cap .get (cv2 .CAP_PROP_FRAME_WIDTH )),
195187 math .trunc (self ._cap .get (cv2 .CAP_PROP_FRAME_HEIGHT )),
@@ -200,13 +192,11 @@ def duration(self) -> FrameTimecode | None:
200192 """Duration of the stream as a FrameTimecode, or None if non terminating."""
201193 if self ._is_device :
202194 return None
203- assert self ._cap is not None
204195 return self .base_timecode + math .trunc (self ._cap .get (cv2 .CAP_PROP_FRAME_COUNT ))
205196
206197 @property
207198 def aspect_ratio (self ) -> float :
208199 """Display/pixel aspect ratio as a float (1.0 represents square pixels)."""
209- assert self ._cap is not None
210200 return _get_aspect_ratio (self ._cap )
211201
212202 @property
@@ -215,7 +205,6 @@ def timecode(self) -> Timecode:
215205 # *NOTE*: Although OpenCV has `CAP_PROP_PTS`, it doesn't seem to be reliable. For now, we
216206 # use `CAP_PROP_POS_MSEC` instead, converting to microseconds for sufficient precision to
217207 # avoid frame-boundary rounding errors at common framerates like 24000/1001.
218- assert self ._cap is not None
219208 ms = self ._cap .get (cv2 .CAP_PROP_POS_MSEC )
220209 time_base = Fraction (1 , 1000000 )
221210 return Timecode (pts = round (ms * 1000 ), time_base = time_base )
@@ -234,12 +223,10 @@ def position(self) -> FrameTimecode:
234223
235224 @property
236225 def position_ms (self ) -> float :
237- assert self ._cap is not None
238226 return self ._cap .get (cv2 .CAP_PROP_POS_MSEC )
239227
240228 @property
241229 def frame_number (self ) -> int :
242- assert self ._cap is not None
243230 return math .trunc (self ._cap .get (cv2 .CAP_PROP_POS_FRAMES ))
244231
245232 def seek (self , target : TimecodeLike ):
@@ -249,9 +236,6 @@ def seek(self, target: TimecodeLike):
249236 target = FrameTimecode (target , self .frame_rate )
250237 if target < 0 :
251238 raise ValueError ("Target seek position cannot be negative!" )
252- assert self ._cap is not None
253-
254- assert self ._frame_rate is not None
255239 target_secs = (self .base_timecode + target ).seconds
256240 self ._has_grabbed = False
257241 if target_secs > 0 :
@@ -281,13 +265,10 @@ def seek(self, target: TimecodeLike):
281265
282266 def reset (self ):
283267 """Close and re-open the VideoStream (should be equivalent to calling `seek(0)`)."""
284- assert self ._cap is not None
285- assert self ._frame_rate is not None
286268 self ._cap .release ()
287269 self ._open_capture (float (self ._frame_rate ))
288270
289271 def read (self , decode : bool = True ) -> np .ndarray | bool :
290- assert self ._cap is not None
291272 if not self ._cap .isOpened ():
292273 return False
293274 has_grabbed = self ._cap .grab ()
@@ -364,8 +345,8 @@ def _open_capture(self, framerate: float | None = None):
364345 if framerate < MAX_FPS_DELTA :
365346 raise FrameRateUnavailable ()
366347
367- self ._cap = cap
368- self ._frame_rate = framerate_to_fraction (framerate )
348+ self ._cap : cv2 . VideoCapture = cap
349+ self ._frame_rate : Fraction = framerate_to_fraction (framerate )
369350 self ._has_grabbed = False
370351 cap .set (cv2 .CAP_PROP_ORIENTATION_AUTO , 1.0 ) # https://github.com/opencv/opencv/issues/26795
371352
@@ -430,7 +411,6 @@ def capture(self) -> cv2.VideoCapture:
430411 backing this object. Using the read/grab methods through this property are unsupported and
431412 will leave this object in an inconsistent state.
432413 """
433- assert self ._cap
434414 return self ._cap
435415
436416 #
@@ -443,7 +423,6 @@ def capture(self) -> cv2.VideoCapture:
443423 @property
444424 def frame_rate (self ) -> Fraction :
445425 """Framerate in frames/sec."""
446- assert self ._frame_rate
447426 return self ._frame_rate
448427
449428 @property
0 commit comments