Yash Bavadiya

Week 8: Gradient Widget Merged, Speed Ramp Begins

This is a weekly update from my Google Summer of Code 2026 project with KDE, improving effect widgets in Kdenlive, a free and open source video editor.

Gradient widget merged

MR !911 went through one more round of review, Jean-Baptiste caught a small inconsistency in how the 32-stop limit was applied and fixed it directly (c2d7a3d2, "Use limit everywhere"). After that, the Gradient widget merged. Two of the three widgets from the proposal are now in master.

One known issue flagged during review: MLT's gradientmap filter doesn't currently support alpha in its gradients, that's a bug on MLT's side, not the widget. Jean-Baptiste merged anyway to make the 26.08 window, with a plan to either disable alpha or fix it upstream before the final 26.08.0 release.

Speed Ramp: starting the third widget

With Gradient shipped, moved on to Speed Ramp. My original proposal described free-draggable bezier handles on the remap timeline's connector lines. Investigation before writing any code turned up a real problem with that: MLT has no bezier keyframe type to serialize a time map into, only preset easing types (linear, smooth, cubic, exponential, and more, as suffix characters on keyframe positions).

Checked with Jean-Baptiste. Turns out free bezier handles in MLT had already been investigated a few years ago and found difficult to integrate. His suggestion: use the same keyframe type system Kdenlive already uses for effects like volume and brightness, letting users pick a type from MLT's existing list rather than dragging custom handles.

Finding the right pattern to reuse

Kdenlive already has a widget that draws real keyframe curves in a plain QWidget, KeyframeCurveEditor, used in the effect stack for other parameters. It samples MLT's interpolated value per pixel and draws the result, no QML involved. That became the reference pattern for adding a curve to the remap dialog (RemapView).

Before building on it, tested MLT directly to confirm non-linear keyframe types are actually honored during playback, not just valid syntax. They are, sampled values matched the exact easing formulas. One gotcha found along the way: the keyframe type suffix has to go on the segment's starting keyframe, not the ending one, otherwise it's silently treated as linear.

Implementation

Four commits, each built clean before the next:

Manually verified: linear playback is unchanged, curve shape follows the selected type, old projects load correctly as all-linear, undo/redo works through type changes, and types survive keyframe drags and clip resizes.

curve rendering with non-linear keyframe keyframe type selector

What's next

Speed Ramp branch is local, not yet pushed. Bringing results to Jean-Baptiste before pushing and opening an MR.