Fix timeline operations failing when clips share a producer#1816
Fix timeline operations failing when clips share a producer#1816abcfy2 wants to merge 1 commit intomltframework:masterfrom
Conversation
Background
<chain id="tl_clip0" ...> <!-- one shared chain -->
<playlist id="playlist_6dcbc856">
<entry producer="tl_clip0" in="00:00:14.820" out="00:00:15.580" />
<entry producer="tl_clip0" in="00:00:16.260" out="00:00:18.020" />
<entry producer="tl_clip0" in="00:00:18.940" out="00:00:20.140" />
...3000+ entries all referencing the same tl_clip0
</playlist>This is fully valid MLT — both Kdenlive and However, this triggers two bugs in Shotcut: Bug 1: Wrong clip deletedSelect clip
Result after Delete:
Bug 2: Undo corruptionPress
Root causeShotcut identifies clips by producer UUID ( |
|
Shotcut does not try to support anything you can write in MLT XML, only what it writes. There is a reason it does not reuse producers that has to do with avformat producer internals especially with respect to audio. I am not certain we want to try to maintain this change since there is no good way to test it. What is the point of cli-anything when MLT already has a CLI and python bindings? |
|
Hi @ddennedy, Thanks for the feedback! Let me address your questions: About cli-anything-shotcut While MLT does have a CLI and Python bindings, the challenge is that not all valid MLT XML can be re-edited in Shotcut — unsupported MLT structures will typically just be recognized as a single media source rather than an editable project. That's the value I've recently been maintaining and improving both CLIs, fixing quite a few compatibility issues along the way. Through that work I've learned firsthand that you can't simply use the MLT CLI to create a project file that's fully editable in Shotcut or Kdenlive — there are specific conventions and properties these editors expect that raw MLT output doesn't include. About the fix itself I'd also point out that this change is actually a net simplification. The original code in About testing I understand the concern about testability. Unfortunately Shotcut doesn't have C++ unit tests, and the existing JS tests only cover EDL/chapters export. That said, the changes are well-isolated: the |
|
Ok, thanks, I appreciate your point about cli-anything creating editor-compatible projects. It is very good if AI can generate things that can be more easily edited with a tool instead of only trial-and-error adjustment prompts. Just like code generation! It is true that producer reuse can be quite helpful not only for internal efficiency but for user to more easily modify a single set of filters, for example. I think we will want to include it, and then add intelligence to not reuse for the rare, known problem situations. i will look into this PR soon after the release next week. Also planning to start adding unit tests next month. |
When multiple playlist entries reference the same producer (e.g. generated by external tools that reuse a single chain element), Shotcut's UUID-based clip identification breaks because all entries share the same producer UUID. This causes: - Delete/Lift removes the wrong clip (always the first match) - Undo restores the entire track as copies of the last clip Fix by: 1. removeSelection()/liftSelection(): use direct clip indices from the existing selection instead of the UUID round-trip. Sort descending by (trackIndex, clipIndex) to avoid index shift during ripple delete. 2. UndoHelper: use cut UUID (unique per playlist entry) instead of parent UUID (shared across entries) as the dictionary key, preventing state entries from overwriting each other. Also check parent UUID in m_xmlClips lookup to preserve the trim XML restore path for keyframes.
7ddd00c to
01d19d7
Compare



Summary
removeSelection()andliftSelection()went through a UUID round-trip (selectionUuids()→findClipByUuid()) that always returned the first matching clip instead of the selected one. Fixed by using direct clip indices from the existing selection, sorted in descending order to avoid index shift during ripple delete.UndoHelper::recordBeforeState()usedclip->parent()UUID as the dictionary key inm_state. When all entries share the same parent producer, all entries had the same UUID, causing state records to overwrite each other — only the last clip's info survived. Undo then restored the entire track as copies of the last clip. Fixed by using the cut UUID (unique per playlist entry) instead of the parent UUID.m_xmlClipslookup inrecordBeforeState()also checks the parent UUID to maintain compatibility with trim commands that register viastoreXmlForClip(parentUuid)underSkipXMLhint.Test plan