Object for frame-based timecodes, using the video framerate to compute back and forth between frame number and seconds/timecode. A timecode is valid only if it complies with one of the following three types/formats: 1. Timecode as `str` in the form "HH:MM:SS[.nnn]" (`"01:23:45"` or
| 189 | |
| 190 | |
| 191 | class FrameTimecode: |
| 192 | """Object for frame-based timecodes, using the video framerate to compute back and |
| 193 | forth between frame number and seconds/timecode. |
| 194 | |
| 195 | A timecode is valid only if it complies with one of the following three types/formats: |
| 196 | 1. Timecode as `str` in the form "HH:MM:SS[.nnn]" (`"01:23:45"` or `"01:23:45.678"`) |
| 197 | 2. Number of seconds as `float`, or `str` in form "SSSS.nnnn" (`"45.678"`) |
| 198 | 3. Exact number of frames as `int`, or `str` in form NNNNN (`456` or `"456"`) |
| 199 | |
| 200 | Rate-related properties: |
| 201 | * :attr:`framerate` is a ``float`` (legacy / deprecated alias). |
| 202 | * :attr:`frame_rate` is a ``Fraction`` and is the canonical form. Both represent |
| 203 | the same rate. |
| 204 | * :attr:`time_base` equals ``1 / frame_rate`` for CFR sources. For VFR |
| 205 | (:class:`Timecode`-backed) instances, ``time_base`` is authoritative and |
| 206 | ``frame_rate`` is an approximation. |
| 207 | """ |
| 208 | |
| 209 | def __init__( |
| 210 | self, |
| 211 | timecode: "TimecodeLike", |
| 212 | fps: "float | FrameTimecode | Fraction | None" = None, |
| 213 | ): |
| 214 | """ |
| 215 | Arguments: |
| 216 | timecode: A frame number (`int`), number of seconds (`float`), timecode string in |
| 217 | the form `'HH:MM:SS'` or `'HH:MM:SS.nnn'`, or a `Timecode`. |
| 218 | fps: The framerate to use for distance between frames and to calculate frame numbers. |
| 219 | For a VFR video, this may just be the average framerate. |
| 220 | Raises: |
| 221 | TypeError: Thrown if either `timecode` or `fps` are unsupported types. |
| 222 | ValueError: Thrown when specifying a negative timecode or framerate. |
| 223 | """ |
| 224 | self._time: _FrameNumber | _Seconds | Timecode |
| 225 | """Internal time representation.""" |
| 226 | self._rate: Fraction | None = None |
| 227 | """Rate at which time passes between frames, measured in frames/sec.""" |
| 228 | |
| 229 | # Copy constructor. |
| 230 | if isinstance(timecode, FrameTimecode): |
| 231 | self._time = timecode._time |
| 232 | self._rate = timecode._rate if fps is None else self._ensure_fractional(fps) |
| 233 | return |
| 234 | |
| 235 | # Ensure args are consistent with API. |
| 236 | if fps is None: |
| 237 | raise TypeError("fps is a required argument.") |
| 238 | self._rate = self._ensure_fractional(fps) |
| 239 | |
| 240 | # Timecode with a time base. |
| 241 | if isinstance(timecode, Timecode): |
| 242 | self._time = timecode |
| 243 | return |
| 244 | |
| 245 | # Process the timecode value, storing it as an exact number of frames only if required. |
| 246 | if isinstance(timecode, str) and timecode.isdigit(): |
| 247 | timecode = int(timecode) |
| 248 |
no outgoing calls