Skip to content

Commit 8b555f6

Browse files
authored
Fix Motion Tracker keyframes not applying after save/reload (#1854)
* Fix Motion Tracker keyframes not applying after save/reload MotionTrackerModel::trackingData parsed each keyframe's time key with QString::toInt, which only accepts integer frame numbers ("5"). When a project is saved, Shotcut serializes animated properties (including the opencv.tracker `results`) in clock time format (00:00:00.167). After a save+reload, toInt then failed on every entry, trackingData returned an empty list, and "Load Keyframes from Motion Tracker" silently applied zero keyframes (the masked rect stayed static). Accept both frame-number and clock/timecode keys. The parsed frame value is not used downstream (only the rectangles are consumed by applyTracking and reset), so fall back to the running index when toInt fails. * Use time_to_frames to parse tracker keyframe times Responding to review feedback: rather than falling back to the running index when QString::toInt fails on a clock-time key, parse the keyframe time with Mlt::Consumer::time_to_frames. It converts both the clock form ("00:00:00.167") and the frame-number form ("5") to the correct frame using the project frame rate, so a project reloaded with clock-time results no longer yields an empty list and the keyframes apply.
1 parent 110f657 commit 8b555f6

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

src/models/motiontrackermodel.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,18 +264,22 @@ QList<MotionTrackerModel::TrackingItem> MotionTrackerModel::trackingData(const Q
264264
QList<TrackingItem> result;
265265
auto s = m_data.value(key, {}).trackingData;
266266
auto l = s.split(';');
267-
bool ok{false};
268267
Mlt::Properties props;
268+
auto consumer = MLT.consumer();
269269

270270
for (const auto &i : l) {
271271
auto pair = i.split("~=");
272272
if (pair.size() == 2) {
273-
auto frame = pair.at(0).toInt(&ok);
273+
// The keyframe time is serialized either as a frame number ("5") or
274+
// as a clock value ("00:00:00.167"), depending on the time format
275+
// MLT used when the project was written (animated properties are
276+
// saved as time so they adapt to a frame-rate change). time_to_frames()
277+
// parses both forms to the correct frame using the project frame rate.
278+
int frame = consumer ? consumer->time_to_frames(pair.at(0).toUtf8().constData())
279+
: pair.at(0).toInt();
274280
props.set("", pair.at(1).toLatin1().constData());
275281
auto rect = props.get_rect("");
276-
if (ok) {
277-
result << TrackingItem{frame, QRectF(rect.x, rect.y, rect.w, rect.h)};
278-
}
282+
result << TrackingItem{frame, QRectF(rect.x, rect.y, rect.w, rect.h)};
279283
}
280284
}
281285
return result;

0 commit comments

Comments
 (0)