Convert a framerate value to an exact rational Fraction. Detects NTSC-derived framerates of the form ``N * 1000/1001`` (e.g. 23.976 -> 24000/1001, 29.97 -> 30000/1001, 47.952 -> 48000/1001) for any positive integer ``N`` and returns their exact rational representation. Whole-number fram
(fps: "FrameRate")
| 124 | |
| 125 | |
| 126 | def framerate_to_fraction(fps: "FrameRate") -> Fraction: |
| 127 | """Convert a framerate value to an exact rational Fraction. |
| 128 | |
| 129 | Detects NTSC-derived framerates of the form ``N * 1000/1001`` (e.g. 23.976 -> 24000/1001, |
| 130 | 29.97 -> 30000/1001, 47.952 -> 48000/1001) for any positive integer ``N`` and returns |
| 131 | their exact rational representation. Whole-number framerates are returned as |
| 132 | ``Fraction(N, 1)``. Other values fall back to ``limit_denominator(10000)`` for a clean |
| 133 | rational approximation. ``Fraction`` inputs are returned directly without conversion. |
| 134 | """ |
| 135 | if fps <= MAX_FPS_DELTA: |
| 136 | raise ValueError("Framerate must be positive and greater than zero.") |
| 137 | if isinstance(fps, Fraction): |
| 138 | return fps |
| 139 | if fps == int(fps): |
| 140 | return Fraction(int(fps), 1) |
| 141 | # Invert fps = N * 1000/1001 to recover N, then verify within tolerance. |
| 142 | base = round(fps * 1001 / 1000) |
| 143 | if base > 0 and abs(base * 1000 / 1001 - fps) < _NTSC_DETECTION_TOLERANCE: |
| 144 | return Fraction(base * 1000, 1001) |
| 145 | return Fraction(fps).limit_denominator(10000) |
| 146 | |
| 147 | |
| 148 | class Interpolation(Enum): |
no outgoing calls