Changing framerate 25->50 causes cutting length of the video clips

The root of the drift problem is that, by definition, “out” and “length” are not the same thing. If we have a clip that is 30 frames long and the project is 30fps (non-drop frame), then the length is 30 frames (“00:00:01.000”). However, the “out” point is 29 because we are “out” after the 29th frame (which is the 30th zero-based frame) and the timestamp “00:00:00.967” is the correct reference to the 29th frame (its start point). So, we get the “out” timestamp by doing 29 * 1000 / 30000 in this example. This cannot be solved with a regex copy.

The “out” and “length” values are not redundant because it is possible for a producer to set “in” and “out” points to trim a clip. To see this in action, start a new project, do File > Open Other > Color to put a transparent clip in the Source player, then set custom in and out points. Do not drag it onto the timeline nor add it to a playlist. Leave it in the Source player and save the project. Since there are no references from the playlist or timeline to provide in and out points, those trim points are placed directly on the transparent clip’s producer. Meanwhile, its length always remains four hours long.

If you tried to write your own video editor, you would discover exceedingly quickly that it is impossible to make a fully frame rate-agnostic project file. For the sake of round numbers, let’s take the 30fps NDF example above and scale it up to 60fps NDF:

"Out" of 30fps NDF = 29 * 1000 / 30000 = 0.967 sec
"Out" of 60fps NDF = 58 * 1000 / 60000 = 0.967 sec

We can’t double the frame number of the 30fps “out” point to get a 60fps “out” point because the 59th frame goes unaccounted and we drift again. Instead, we need to do math in frames and then convert to milliseconds:

Truncate("Number of frames in <length> property" * "Sec/Frame Original" * "Frames/Sec New" - 1) * "Sec/Frame New"

This basically says “get the timestamp of the last frame in the new frame rate”. Obviously, you would want to rearrange the formula in code to do all the divisions last for highest decimal accuracy. But for our straight-forward example:

Truncate(30 * 1000/30000 * 60000/1000 - 1) * 1000/60000 = "00:00:00.984"

Unless you enjoy doing this kind of math all day long, you’ll get more joy out of life using Shotcut than writing your own video editor from scratch. :rofl:

As you noted earlier, the “num/den” notation for frames per second is preferred to a decimal FPS to give more precision when converting non-integer frame rates. Also note that the “true” answer to the formula above was 0.983333333, but because we are a positive number, we multiply by 1000 and take the ceiling then divide back by 1000 to get milliseconds. If we were negative, we would take the floor. Never use rounding. When operating on a positive number, the ceiling is required because truncating to 0.983000000 would put us in territory owned by the 58th frame and we would drift again.

You could make the argument that the math is more complicated than necessary because the “out” value is a last-frame reference rather than a clip-length reference (last frame + 1). Perhaps the MLT format would be more agnostic if the MLT engine displayed every frame up to but not equal to the “out” value. And that would be true in that limited sense. But it also makes time calculation and frame lookups more complex in the engine when exporting and generating a live preview, so the conversion price has to be paid somewhere. Likewise, a project can never be fully agnostic because time values based on 30fps source footage are locked to precision of 1/30th of a second. As in, there is not an intuitive or sensible way for a user to select a value of time with more precision than that. So if the project suddenly changes to 60fps and more timescale resolution becomes available, and there are now two frames per 1/30th slice instead of one, what agnostic way would accurately choose the first or the second frame for each 1/30th slice? That would be an artistic decision on the part of the user, not something we can ask a machine to solve for us. Frames are what finally make an appearance on the screen, so timestamps will always have a hard-linked relationship to frame rate in even the most agnostic formats.