Why does self.frames = int(seconds * self._int_framerate) ?
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
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...
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]
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.