Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why does self.frames = int(seconds * self._int_framerate) ? #48

Open
cheng-chi opened this issue Aug 4, 2023 · 3 comments
Open

Why does self.frames = int(seconds * self._int_framerate) ? #48

cheng-chi opened this issue Aug 4, 2023 · 3 comments

Comments

@cheng-chi
Copy link

Hi Erkan,
Thank you so much for maintaining this convenient timecode package on pip! I'm a Robotics PhD student at Columbia university. My current project requires syncing multiple GoPros using their timecode with a global clock.
After my discucsion with GoPro Lab's maintainer, and my experiments, I believe that the conversion of Timecode from and to float seconds is incorrect.
Let's take 29.97Hz video for example, each frame takes 1/29.97 seconds. Therefore, to convert seconds into frames, we should:

self.frames = int(seconds * float(self.framerate))

Same goes to converting number of frames into seconds:

float(self.frames) / float(self.framerate)

The symptom of this error is that the 29.97Hz drop frame timecode is lexically faster than 30Hz timecode, while in reality, the drop frame operations should make the two timecodes roughly align:

t = 5000
tc = Timecode(framerate='29.97', start_seconds=t)
print(tc, ' 29.97Hz')
# 01:23:24;29  29.97Hz

tc = Timecode(framerate='29.97', frames=round(t*29.97))
print(tc, ' 29.97Hz')
# 01:23:19;29  29.97Hz

tc = Timecode(framerate='30', frames=round(t*30))
print(tc, ' 30Hz')
# 01:23:19:29  30Hz
@eoyilmaz
Copy link
Owner

eoyilmaz commented Jan 1, 2024

Hi @cheng-chi

Whenever somebody disputes about the calculation that I do in this library, I like to use DaVinci Resolve as a calculator to see if I'm doing it correctly , so here are my tests results:

1- I put a 5000 seconds clip (Solid Color) in a 29.97 FPS Drop Frame timeline that starts at 00:00:00;00, the clip ends at 01:23:24;29
2- I put a 5000 seconds clip (Solid Color) in a 30 FPS None Drop Frame timeline that starts at 00:00:00:00, the clip ends at 01:23:19:29
3- I then used Timecode library to see if it is doing it correctly:

>>> from timecode import Timecode
>>> tc1 = Timecode("29.97", start_seconds=5000)
>>> tc2 = Timecode(30, start_seconds=5000)
>>> tc1
01:23:24;29
>>> tc2
01:23:19:29

Exactly matching the DaVinci Resolve result.

Here you can try yourself: Timelines.zip

Coming to your example where you are setting the number of frames in two different timelines with two different frame rates and drop frame schema to two different numbers (149850 and 150000 respectively) to get the same timecode, I'm not sure what is the best way to explain this difference, and I understand your intuation, requsting the same duration in two different timelines should always return the same timecode even if the frame numbers are different, but I guess it is not working in this way when drop frames are getting involved in to the mix...

@eoyilmaz
Copy link
Owner

eoyilmaz commented Jan 1, 2024

Here is a nice explanation why the same requested duration in 29.97 FPS and 30 FPS result in two different "wall-clock" times: https://en.wikipedia.org/wiki/SMPTE_timecode

The altered frame rate meant that an "hour of timecode" at a nominal frame rate of 29.97 frame/s was longer than an hour of wall-clock time by 3.6 seconds (for 29.97 non-drop timecode of 01:00:00:00 drop-frame timecode is 01:00:03;18 and for non-drop 00:59:56:12 drop-frame is 01:00:00;00), leading to an error of almost a minute and a half over a day.[2]

@eoyilmaz
Copy link
Owner

eoyilmaz commented Jan 1, 2024

Maybe your assumption here:

Let's take 29.97Hz video for example, each frame takes 1/29.97 seconds

is the cullprit, as the frames are actually 1/30 seconds but over a certain time or every now and then we drop some frames to have a mean value of close to 1/29.97 seconds per frame duration... This is explained in the aformentioned wikipedia page:

Drop-frame timecode drops 18 of 18,000 frame numbers, equivalent to 1/1000, achieving 30 × 0.999 = 29.97 frame/s.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants