AcademySoftwareFoundation / AcademySoftwareFoundation/OpenTimelineIO
[BUG] from_seconds/to_seconds & from_frames/to_frames do not produce matching values
- Dominant language
- C++
- Stars
- 2k
- Forks
- 351
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 1
Description
# Required:
------------
[X] I believe this isn't a duplicate topic
[X] This report is not related to an adapter
For adapter related issues, please go to the appropriate repository - likely in
the [OpenTimelineIO github organization](https://github.com/OpenTimelineIO/).
For general questions and help please use the
[Academy Software Foundation slack](https://slack.aswf.io/),
[#opentimelineio](https://academysoftwarefdn.slack.com/messages/CMQ9J4BQC).
## Select One:
[ ] Build problem
[X] Incorrect Functionality or bug
[ ] New feature or functionality
## Description
Frames to Seconds conversion is not accurate on certain values at 25 FPS.
If I instance `RationalTime.from_frames` with a value of `29`, when I call `to_seconds()` it gives me `1.16`.
If I instance `RationalTime.from_seconds` with a value of `1.16`, when I call `to_frames()` it gives me `28`.
I believe this is due to the fact we always round down to nearest int rather than to closest int e.g the maths shows us it's just slightly below frame 29 and not at all close to frame 28:
```
>>> 1.16 * 25
28.999999999999996
```
This makes us unsure if we can trust OpenTimelineIO to always calculate correct values when converting between seconds/frames.
# Optional
-----------
## Environment
Operating System:
Python version if appropriate: Python 3.10.7
## Reproduction Steps
Tested on v0.14.0, v0.15.0 & v0.16.0.
Example snippet:
```python
>>> import opentimelineio as otio
>>> FRAME_NUM = 29
>>> RATE = 25
>>>
>>> rational_time = otio.opentime.from_frames(FRAME_NUM, RATE)
>>> seconds = rational_time.to_seconds()
>>> print(seconds)
1.16
>>>
>>> rational_time_from_sec = otio.opentime.from_seconds(seconds, RATE)
>>>
>>> print(rational_time)
RationalTime(29, 25)
>>> print(rational_time_from_sec)
RationalTime(29, 25)
>>> print(rational_time.to_frames())
29
>>> print(rational_time_from_sec.to_frames())
28
```
Contributor guide
Research direction
Start by reproducing the provided Python snippet using opentio.opentime.from_frames, from_seconds, RationalTime.to_seconds, and to_frames. Trace the conversion and rounding behavior, then add a regression test showing that the 29-frame, 25 FPS round trip preserves the frame value; done means the conversions produce matching values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100