I have a weird problem related to fps/sync of frames.
Firstly, I have an input .mkv video in 30fps.
cap: cv2.VideoCapture = cv2.VideoCapture(example_video.mkv)
Then I break it into frames and work with them using while loop, simultaneously building up output video using edited frames (basically I analyze them with ML model and draw bounding boxes around found objects).
So on every iteration of the cycle, one frame being taken out of original video, being edited and put on top of other frames of output video
out_fps = 30
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output.mp4', fourcc, out_fps, (frame_width, frame_height))
while cap.isOpened():
success: bool
frame: cv2.typing.MatLike
success, frame = cap.read()
if success:
* analyzing and modifying frame *
out.write(frame)
else:
break
out.release()
However, my output video for some reason is always a bit longer than the original one, resulting in desync between video and audio tracks (I also add original audiotrack to output video later, so input and output video should have the exact same duration and this is crucial for me).
For example, my input video can be 41:42 minutes long, but output one will be 41:46, resulting in progressing audio desync, which gets worse with video duration, sometimes I will have ~12 hours long ones, resulting in multiple minutes desync.
get_video_duration("example_video.mkv") # selfmade function for returning
get_video_duration("output.mp4") # video duration in milliseconds
>>> 2502900
>>> 2506166
When i try to check their fps its stays exactly the same – at 30.0
get_video_fps("example_video.mkv")
get_video_fps("output.mp4")
>>> 30.0
>>> 30.0
Please, let me know if someone encountered (and potentially solved) similar problem. Thank you!
I’ve already tried a lot of workarounds, such as artificially changing output fps by a little (for example changing 30.0 to 30.0479616) to compensate this weird behaviour, and while it can reduce desync from 4 sec to like 0.2 sec it is still not ideal and does not work on bigger videos for some reason.
For example, 30.0479616 fps value will work on my 42 min long video, but for another video, lets say, 2 hours long, it won’t work, desync still will be there, just by another %diff and I cant afford to process every video 2 times to calculate this “offset” before rendering final version.