I wanted to use the timestamps from an MLT file as part of an ffmpeg command, but the resulting videos are incorrect. When compared to the videos as exported by Shotcut, some of the durations and start times are off by one frame.
OS: Windows 10 64-bit (Build 19043) Shotcut Version: 22.06.23 MLT Version: 7.8.0
The MLT file was saved with Shotcut 22.06.23.
My MLT file contains a <playlist> element that contains 8 entries from a single MKV file. My goal was to take the in and out attributes of each <entry> element and use them in an ffmpeg command to generate clips. For example:
-t in ffmpeg is a duration, but out in MLT is the time at the start of the last frame, whose duration depends on the frame rate. duration = out - in + 1 frame. You may not like that, but that is the way it has worked for over 15 years, and not going to change it now and break many things. Also, in MLT the in and out times are interpreted using the <profile> (Video Mode in Shotcut) frame rate, but in ffmpeg the times are interpreted based on the video file’s frame rate. How to resolve this is an exercise for you. You might consider to write a custom exporter to replace Export EDL to use with ffmpeg by modifying the file in Shotcut\share\shotcut\qml\export-edl\export-edl.js.
This is totally fine, and I can easily account for it. If this were my only problem, I’d see that all the durations were shifted by one frame, but that is not the case – only some are.
Also, in MLT the in and out times are interpreted using the <profile> (Video Mode in Shotcut) frame rate, but in ffmpeg the times are interpreted based on the video file’s frame rate.
The MLT framerate is 24000 / 1001 = 23.976023
The ffmpeg framerate is 33230 frames / 23:05.968 = 23.976022
The two are not different until the 6th decimal place, which is not enough to affect the video clip’s I’m trying to make. My latest timestamp is 20:54:638 = 1254.638s. Convert this to frames with 23.976023fps = 30081.22954frames. Convert this to seconds with 23.976022fps = 1254.638052s. Is there some sort of truncation/rounding I need to do obtain an integer frame count?
You might consider to write a custom exporter to replace Export EDL
I exported all my clips as an EDL file to see what the timestamps looked like. Using 1 frame = 0.0417s, I converted the frame portion of the timestamp into seconds and compared it to the MLT values. I also generated videos with ffmpeg, and the results are still incorrect but in a different way now.
The differences between the MLT and EDL time values would seem to indicate that export-edl.js is not handling the timestamps correctly, so it’s not likely to help me with my problem.
If you’re not sure where these discrepancies are coming from, could you point me to the place(s) in the repo where timestamps are generated and used for export? I took a quick look around, but I’m unfamiliar with the organization.
Always do time-based math as “number of frames since the beginning” rather than seconds. Always truncate the frame number to get an integer rather than rounding. At the very end of the frame-based math, the final frame can be converted to seconds to get the timestamp of that frame. Do not add a seconds-based timestamp to another seconds-based timestamp to calculate a new position. The precision loss in those timestamps will cause skew over time. Instead, convert both timestamps to frames, add the frames, then get the timestamp of the new frame position.