Changelog
Explore the recent changes made to CreativeEditor SDK.
Our release notes contain more details on features and changes.
Download the full changelog as a plain text file.
Recent Releases
Version v1.83.0 Changelog October 1, 2026
Breaking Changes
CMYK & Spot Colors
-
Engine: Improved CMYK colors with ICC-accurate conversion through the document CMYK profile instead of basic channel inversion. A key-only black and a rich black now render as different colors, as they print. This changes previews and raster exports. An export that keeps device CMYK is unchanged, because it writes ink values and converts nothing.
-
Engine: Improved tinted CMYK colors by scaling print ink values instead of blending the converted color toward white.
-
Engine: Fixed a spot color used as a gradient color stop, which now renders with its defined approximation. It previously rendered as magenta, the placeholder for an undefined spot color.
-
Engine: Fixed the tint of a spot color used as a drop shadow color, which rendering ignored.
-
Engine: Added the
scene/colorConversionModeproperty, which selects how a scene converts CMYK values for display. A new scene isManagedand converts through the document CMYK profile. A scene saved before this release loads asLegacyand keeps the previous CMYK channel-inversion conversion. Set the property toManagedto adopt the accurate CMYK conversion for an existing design. Spot colors use the corrected approximation and tint handling in both modes; a CMYK spot approximation follows the selected mode. -
Engine:
convertColorToColorSpacenow converts a CMYK color to sRGB through the document CMYK profile in aManagedscene, so it returns the same color the engine renders. The returned values differ from the previous channel inversion. ALegacyscene keeps the previous conversion. -
Engine:
convertColorToColorSpacenow fails withCOLOR.PROFILE_NOT_LOADEDwhen a conversion needs the CMYK profile and the profile is still loading. The call requests the profile; runupdate()until loading finishes before converting again. If no usable profile can be loaded, conversion reports a missing profile with the failed URI. Fix the profile setting before retrying. It previously returned an unmanaged color that a later call would not repeat. ALegacyscene needs no profile and never fails this way. -
Engine: Added
loadCMYKProfile, which waits for the document CMYK profile before tryingfallbackCMYKProfileUriwhen needed. Await it before dependent conversions and after changing profiles. CMYK fills, text, strokes, shadows, and effects keep an export waiting while the profile loads. If no usable profile can be read, the export completes with the unmanaged conversion and reports the failed URI once. -
Engine: In Managed scenes, sRGB colors and RGB-only spot colors now convert to CMYK through the document or fallback profile. Conversion can fail while the profile loads. Wait for
loadCMYKProfile()to complete before converting a color to CMYK. Profiles that only convert CMYK to RGB continue to use a simple formula.
Asset Placement, Drag & Drop
-
Engine (Android / Swift / Web / Node): Applying an asset now takes an optional placement. It puts the new block in a given parent, centered on a given point. Android: Added overloads of
applyAssetSourceAssetanddefaultApplyAssetthat take anAssetPlacement. Swift: Addedapply(sourceID:assetResult:placement:)anddefaultApplyAsset(assetResult:placement:), which take anAssetPlacement. Web / Node:engine.asset.applyandengine.asset.defaultApplyAssetnow take aplacementoption. -
Engine: Added a drag gesture that swaps two image fills. It is off by default. The
dragToSwapFills/enabledsetting turns it on. -
Engine/Web: The engine now handles drag & drop from outside the canvas. It outlines the block that would take the drop and runs the
asset.dropaction on release. By default the action replaces that block’s content, or adds the asset where it was released. Register your ownasset.dropto change it. -
Engine: The
page/highlightDropTargetoutline now follows the dragged element without a frame of delay, and marks the page the element lands on whenpage/reparentBlocksToSceneWhenOutOfPageis on. -
Engine/Web: While the swap gesture holds an image, a preview of the image follows the pointer. Escape cancels the swap.
-
Editor/Web: Users can now drag a library asset onto an image to replace it. A drop on a page adds the asset where it was released. A press and hold starts the same drag on a touch screen, and on a small screen the library closes to show the canvas. The
ly.img.dragAndDrop.assetfeature key turns it on, and the Design, Photo, Video, Advanced and Advanced Video editors have it on. -
Editor/Web: A configuration that lists its feature keys and predates this release does not list
ly.img.dragAndDrop.asset, so its library cards can no longer be dragged. Add the key, or declare the release the configuration was written for withsetEditorCompatibilityVersion. -
Editor/Web: A library drop no longer applies the asset to the selected block. To keep that behavior, register your own
asset.dropaction that applies the asset to the selection. -
Editor/Web: A drop runs the
asset.dropaction. Register your own withcesdk.actions.register('asset.drop', …)to handle drops from your own drag source. -
Editor/Web: A library drag no longer carries the
//ly.img.assetdata type. A custom drop target that read it no longer receives library drags. It now carries the asset source and the asset id under the typesASSET_SOURCE_TYPEandASSET_ID_TYPE, and the content kind undercontentKindType(kind), which@cesdk/engineexports. -
Editor/Web: Users can now swap two images. Press and hold an image, or hold Alt, then drag it onto another image. The
dragToSwapFills/enabledengine setting turns it on, and the Design, Photo, Video, Advanced and Advanced Video editors have it on. -
Editor/Web: Screen readers now announce the result of a drop.
Text Alignment
-
Engine: Text blocks and captions have a new alignment,
Justify. It widens the gaps between words to fill the block width. The last line of a paragraph keeps its natural width. An older engine opens a scene with justified text and shows it aligned likeAuto. -
Engine (Swift + Android): Swift:
HorizontalTextAlignmenthas a newjustifycase. The raw value ofautochanges from3to4. This fixes a crash when an app read the alignment of a text block set toAuto. Update aswitchthat lists every case. Android:HorizontalAlignmenthas a newJustifyvalue. Update awhenthat lists every value.
Timeline Customization
-
Editor/iOS: Added timeline customization. Pass a
Timeline.ConfigurationtoTimelineto configure the timeline instead of rebuilding it. -
Editor/iOS + Android: iOS:
Timelinenow renders its tracks alone: no header, and no “Add Clip” or “Add Audio” button. An integration that mountsTimeline— or the deprecatedDefaultTimelineComponent— without a configuration loses those three surfaces and keeps compiling, so add them back withheader(_:),addClipandaddAudio. An integration built on the video starter kit is unchanged, because the starter kit declares all three. Android: The timeline now renders its tracks alone by default: no header, and no “Add Clip” or “Add Audio” button. Add each surface throughheaderListBuilder,addClipButtonandaddAudioButton. The video starter kit declares all three, so its timeline is unchanged. -
Editor/iOS: Every built-in timeline item and add-content option now takes an
isEnabled, matching the canvas menu buttons.DefaultTimelineComponentis deprecated and renamed toTimeline, which is now both the component and the namespace for everything that customizes it. -
Editor/iOS: The timeline’s “Add Clip” and “Add Audio” buttons are now configurable. Choose which sources appear and in which order, relabel or re-icon them, replace what a built-in source does, hide one conditionally, or add your own with
Timeline.AddClipOption.custom(…). Add Clip offers the camera and the asset library by default, andTimeline.AddClipOption.photoRoll()adds the privacy-friendly photo picker. Add Audio offers music and voiceover. Both buttons also take atitleand aniconthat replace the button’s own label. -
Editor/iOS: The timeline header is now configurable. Set your own items leading, centered, or trailing with
header(_:)andTimeline.ItemGroup, or adjust the built-in header withmodifyHeader(_:)so later built-in items still reach your integration.addFirst(placement:_:)andaddLast(placement:_:)place an item at an edge without naming a neighbouring one.Timeline.Labels.timecode,Timeline.Buttons.playPause,Timeline.Buttons.loop,Timeline.Buttons.toggleExpandedandTimeline.Spacerbuild the built-in items.playPauseandlooptake anicon,timecodeandtoggleExpandeda wholelabel, and each button also takes anactionthat replaces what it does. -
Editor/iOS: The timeline height is now expressed in track rows instead of points. It grows to at most three tracks by default, or you can set a fixed number of tracks.
-
Editor/iOS: The timeline’s expanded state can now be driven by your own binding through
Timeline(context:configuration:isExpanded:).
Resource Loading
-
Engine:
forceLoadResourcesnow waits for fonts. Before, it could finish while a font was still loading. Text was then measured with a different font. -
Engine:
getStatenow reportsPendingaftersetFont, while the font loads. Before, it reportedReadytoo early. -
Engine:
forceLoadResourcesnow reports an error when a resource did not load. Before, it reported success. -
Migration guide: Migrating to v1.83 (iOS, Android) shows how to declare the timeline’s header and buttons.
Deprecations
All items below remain functional this release; migrate before they are removed.
Asset Sources
- Engine (Web + Node):
asset.canManageAssetsis deprecated. It reports whether a source declared the deprecatedcanManageAssetsflag, not whether assets can be added to or removed from that source. To control whether an upload button is offered, use thecanAddoption on an asset library entry instead.
Stroke Caps & Scene Duration
-
Engine:
setStrokeCapandgetStrokeCapare now deprecated in the C++ API, as they already were on Web, Android and iOS. UsesetStrokeStartCapandsetStrokeEndCapto set each end, andgetStrokeStartCapandgetStrokeEndCapto read them. -
Engine:
getTotalSceneDurationis now deprecated in the C++ API, as it already was on Web and Android. UsegetDurationwith a page block instead.
Navigation Bar Configuration
- Editor/Web: The
ui.elements.navigation.positionconfiguration option is deprecated. Usecesdk.ui.setNavigationBarPosition()instead.
New Features
Editor Configuration & Platform Support
-
Editor/Android: Add support for Android 17.
-
Editor/Web:
@cesdk/cesdk-jsnow exports theSceneDesignUnittype. -
Editor/Web:
cesdk.setEditorCompatibilityVersion('1.82.0')pins an editor configuration to the CE.SDK version it was written for, so listed behavior changes from later versions do not apply to it. Call it aftercesdk.resetEditor(), which clears any previous pin. The CE.SDK editor configurations and starter kits pin it for you; a configuration that does not pin gets the current release’s behavior.
Layers, Pages & Grouping
-
Editor/Web: Added keyboard shortcuts for the stacking order.
Cmd/Ctrl+]andCmd/Ctrl+[move the selection one step towards the front and the back;]and[move it all the way. They run the newselection.bringForward,selection.sendBackward,selection.bringToFrontandselection.sendToBackactions, which move every selected block and can be run directly withcesdk.actions.run('selection.bringToFront'). -
Editor/Web: Added a layer and page list, opened from a new button at the bottom of the dock. It shows the document’s pages above the layers of the page being worked on. A row selects its block, renames it in place, hides it, locks it, and opens a menu of the commands that apply to it. Holding Alt on the eye or the padlock leaves only that row shown or unlocked, and holding it again brings the rest back. Dragging a row reorders the block or moves it into a group or another page. Pressing the space under the rows or a section heading clears the selection. A selection made on the canvas scrolls its row into view. The design and advanced editor configurations declare the dock button as an
ly.img.assetLibrary.dockentry keyedly.img.layerListwhose click handler opens the panel; an integration with its own dock order adds the same entry, or opens the list by its panel id,//ly.img.panel/layers. -
Editor/Web: Every row of the layer and page list can show a thumbnail of its block, kept current as the block changes. Enabled with the
ly.img.layerList.thumbnailsfeature. -
Editor/Web: The list is gated by the
ly.img.layerListfeature and its childrenly.img.layerList.panel,.visibility,.lock,.reorder,.renameand.menu, so the panel and each row control can be turned off on its own. All are enabled by default. -
Editor/Web:
ly.img.layerList.pagesandly.img.layerList.layerschoose which lists the panel holds, and are both enabled by default.ly.img.layerList.combinedreplaces both with a single tree of every page and its layers, and is off by default. -
Editor/Web:
ly.img.layerList.canvasFollowscrolls the canvas to the block a row picks, and follows a page row only by default.cesdk.feature.set('ly.img.layerList.canvasFollow', true)follows every row;cesdk.feature.disable('ly.img.layerList.canvasFollow')follows none. -
Editor/Web: The menu on a layer or page row is driven by the Component Order APIs under the new
ly.img.layerList.menuUI area (cesdk.ui.setComponentOrder,getComponentOrder,insertOrderComponent,updateOrderComponent,removeOrderComponent). A page row and a layer row read their own order, selected withwhen: { rowKind: 'page' | 'layer' }. The built-in entries are registered as components (ly.img.layerList.menu.rename,.duplicate,.delete,.group,.ungroup,.bringToFront,.bringForward,.sendBackward,.sendToBack,.page.addAbove,.page.addBelow) and custom entries can be added withcesdk.ui.registerComponent. -
Editor/Web: A row’s padlock writes the engine’s own transform lock, so it is saved with the scene and applies on the canvas. A locked block, and a block inside a locked group, does not reorder by drag, by the row menu or by the bracket keys. It can still be selected, inspected and restyled.
-
Engine: A block that already belongs to a group can be grouped again, so a group can be made inside another group from a selection. A selection that spans two containers now moves every member into the new group.
isGroupablerefuses a block grouped together with a container it sits inside, which would make that container a child of itself, and it also refuses a scene, a page and an empty selection. -
Editor/Web: Added the
page.addaction. Override it to choose where a new page is inserted. -
Editor/Web: Added the
page.moveUpandpage.moveDownactions, which move the selected page.
Snapping & Image Source Sets
-
Engine: Added equal-distance snapping. A dragged block snaps to equal spacing with its siblings, and a badge shows the size of each gap. While the snap holds the block, the engine does not round its position to the pixel grid. It is off by default. Turn it on with the
features/equalDistanceSnappingEnabledsetting. -
Engine: Set
features/automaticSourceSetsEnabledto true and an image fill you add gets the smaller entries of its source set by itself, so the engine can draw a small image where the full one is not needed. A fill that comes from a loaded scene gets none, and a duplicate or an undo step keeps the entries it has. The smallest entry is 512 pixels on the long edge and the largest is your own image, so an image under 1024 pixels gets none and an export still uses the full resolution. An entry is a JPEG at quality 90 for an image without alpha and a PNG for one with it. The setting is off by default. The entries are transient resources that state thebufferscheme:saveToArchivecarries their bytes and needs nothing, whilesaveToStringneeds a persistence callback (on web and iOS) or the entries stored by hand first (on Android), or it reports the scheme and stops.
Print Setup, Exclusion Areas & Photobooks
-
Engine: A new
exclusionAreablock marks a region of a page that content must stay out of, for example a window on an envelope or a spine on a book cover. An exclusion area is left out of an export, or cut out of it with the newexclusionArea/punchOutproperty. The newexclusionArea/constrainsproperty says whether the exclusion area holds content out of itself while the user drags, nudges or resizes a block. It is off by default, so a new exclusion area marks a region and nothing more. Turn it on for a region the engine must hold content out of, an envelope window or a die cut. An exclusion area groups only with another exclusion area, so the marker cannot be welded to the artwork it marks. A scene that holds an exclusion area does not open in an earlier version of the engine. See Exclusion Areas. -
Engine: The new
findAllInExclusionAreasAPI returns every block that overlaps an exclusion area, see Exclusion Areas. -
Engine: Pages carry a safety inset, an inward distance from the page edge that marks where content must stay for print. Set it with the new
page/safetyEnabledandpage/safetyInset/left,/top,/right,/bottomproperties. Its guide appears while a drag, or a move or resize with the arrow keys, comes near it. Setpage/safetyRevealDuringTransformtofalseto draw the guide all the time. See Pages. -
Engine: The new export options
exportPdfWithCropMarksandexportPdfWithRegistrationMarksadd crop marks and registration marks to a PDF export, both off by default. See the Export to PDF guide. -
Editor/Web: Selecting an exclusion area now shows an Exclusion Area Settings panel with two toggles: whether the area holds other blocks out, and whether it cuts its region out of the export. Enable it with the new
ly.img.page.printMarks.exclusionAreafeature key. -
Editor/Web: Added a Photobook Editor starter kit that builds a print-ready photo book from a template: a layouts library per page format, auto-fill that matches each photo to the slot that crops it least, live design validation, a page-spread preview, and export to PDF/X-4 with a FOGRA39 output intent. Export runs in the browser by default and can offload rendering to the bundled Node server.
-
Editor/Web: Added a Print Setup panel in the document inspector. Bleed is now set per side, with a lock that links the sides, replacing the single document-wide value.
-
Editor/Web: The Print Setup panel adds crop and registration marks to PDF exports, with a configurable offset, length and weight. The offset and length are in the scene’s design unit, the weight in points. Exports via the export button or
cesdk.utils.export()include them; each print-mark option a caller passes overrides the panel for that one option.cesdk.export()andengine.block.export()are unchanged. -
Editor/Web: Added Feature API keys
'ly.img.page.printMarks.crop'and'ly.img.page.printMarks.registration', which control the printer’s marks in the Print Setup panel. Enabled in the advanced editor configuration, disabled elsewhere. Their parent key'ly.img.page.printMarks'turns both on at once. -
Editor/Web: Added Feature API key
'ly.img.page.bleedColor', which controls the bleed color row in the Print Setup panel. -
Editor/Web: New Safety Margin controls set an inward inset on each of the four sides, seeded at 10mm when first enabled. The document inspector sets the margin for every page, and selecting a page sets that page alone. Enable the controls with the new
ly.img.page.printMarks.safetyMarginfeature key, which is on in the design and advanced editor configurations.
CMYK Profiles & Imported JPEGs
-
Engine: Added
setCMYKProfileandsetCMYKProfileFromDatato use a document’s CMYK profile for previews and raster exports. You can also inspect or remove the profile and configure rendering intent and black point compensation. -
Engine: Imported JPEG fills can retain and render their source color space, ICC profile and decode ranges without changing the original image bytes.
-
Engine: Such a definition applies only while its image buffer holds the bytes it was read from. A write that changes those bytes switches the definition off, and writing them back switches it on again.
Text Backgrounds
-
Engine: Added
setTextBackgroundColorandgetTextBackgroundColors. They set and read the background color of a range of text. A fully transparent color removes the background. The run background is independent of the block background and draws on top of it. -
Engine: Added the text block properties
text/backgroundPadding/left,text/backgroundPadding/top,text/backgroundPadding/right,text/backgroundPadding/bottomandtext/backgroundCornerRadius. They set the size and the corners of the background of the text runs. Caption blocks get the same properties undercaption/, and a caption track keeps them in sync.
Timeline, Navigation & Crop Customization
-
Editor/iOS:
ForceCropMode.ifNeedednow takes a configurablethresholdthat sets the tolerated difference between the current dimensions and the preset, matching Android..ifNeededkeeps the previous behavior with a default threshold of0.0001. To tolerate a range of aspect ratios, use the midpoint of the range as the preset ratio and half of the range as the threshold. -
Editor/Android: Added timeline customization. Configure the timeline with
Timeline.rememberand pass it as thebottomPanelinstead of rebuilding it. -
Editor/Android: The timeline’s “Add Clip” and “Add Audio” buttons are now configurable through the new
addClipButtonandaddAudioButtonproperties ofTimeline. Both buttons and their menu entries are ordinary editor components, so they take the samevectorIcon,textString,enabledandvisibleproperties as a dock button. UseTimeline.Button.rememberAddClipandTimeline.Button.rememberAddAudioto choose and reorder the entries built byTimeline.AddClipOption.rememberCamera,rememberGallery,rememberLibrary,Timeline.AddAudioOption.rememberMusicandrememberVoiceover, or add your own source withTimeline.AddClipOption.rememberandTimeline.AddAudioOption.remember. Add Clip offers the camera and the asset library by default, Add Audio offers music and voiceover. Assignnullto remove a button, or provide your ownEditorComponentto replace it. A button with one remaining entry triggers it directly instead of opening a menu, and names that entry instead of showing the generic label. -
Editor/Android: The timeline header is now configurable through the new
headerListBuilderproperty ofTimeline. Place your own components at the start, center or end, or adjust the built-in header withTimeline.HeaderListBuilder.remember().modify { }so that header items added in a future release still reach your integration.Timeline.Label.rememberTimecode,Timeline.Button.rememberPlayPause,rememberLoopandrememberToggleExpandedbuild the built-in items. Removing every header item removes the player bar with it. -
Editor/Android: The timeline’s expanded state can now be driven by your own
MutableState<Boolean>through the newexpandedStateproperty ofTimeline. It sets the initial state and stays in sync as the user or your integration expands and collapses the timeline, because the expand/collapse toggle writes back to it. By default the editor owns the state, which starts expanded and survives configuration changes. -
Editor/Web: The navigation bar and the inspector bar can now be placed below the canvas with
cesdk.ui.setNavigationBarPosition('bottom')andcesdk.ui.setInspectorBarPosition('bottom'). Both default to'top'. Call them after the editor configuration plugin, becauseresetEditor()restores the default placement.
AI Prompts & Reference Images
-
Editor/Web: Added
builder.PromptInput()to render a prompt field in a registered panel. The field grows with its text, from three lines to ten, and carries no resize handle. Itsattachmentsoption adds a row of the images the prompt refers to. Each carries a remove button, beside a button that asks the panel for another one. Without that option the field renders alone. -
Plugins/Web: The prompt takes as many reference images as the model’s schema allows. An image property of type
arrayopensmaxItemsslots and receives a list, so a gateway model such as Seedream 4.5 takes ten images and FLUX.2 edit four. A string property, or an array whose schema names no limit, keeps one. -
Plugins/Web: Added the Create Image from Reference quick action to the canvas menu of a selected image. It opens the image generation panel on the provider that owns the action, with the image attached to the prompt beside any images already there, and is disabled once the prompt has no room left. Every image-to-image provider offers it, and the feature key
ly.img.plugin-ai-image-generation-web.quickAction.createImageturns it off.
Licensed Codecs
- Engine/Node: Added support for licensed codec packs downloaded from the licensing dashboard on Linux x86_64. Packs are automatically detected in
$HOME/.local/share/cesdk-codecs; setCESDK_LICENSED_CODEC_PACKto use a custom installation directory.
Improvements & Behavior Changes
Performance
-
Engine: A PDF export with
exportPdfWithHighCompatibilitydisabled no longer holds a decoded copy of an image abovemaxImageSizein the image cache. Such an export needs less memory. -
Engine/Web:
CreativeEngine.init()is faster, and no longer hangs when a browser’s video codec does not answer. -
Engine: Improved undo and redo performance in large scenes.
-
Engine: Improved emoji detection, text creation, shaping, and typing performance while reducing memory churn for long plain and wrapped text.
-
Engine: Improved scrolling performance.
-
Engine: An image is no longer decoded at full resolution to build a hit-test mask or to read its width and height. A scene with large photos now holds much less memory, and an export of it is faster.
Color Management & PDF Output
-
Engine: A PDF export now writes the
TrimBoxand theBleedBoxof every page that has a bleed margin (page/margin). TheMediaBoxalone does not say where a print shop cuts. TheTrimBoxis the page frame and theBleedBoxis the sheet around it. A page with no bleed gets no boxes, because its sheet is already the trim. A page whose bleed is not a rectangle gets no boxes either, because a PDF page box is a rectangle. That covers a page with a non-rectangular shape and a page usingpage/marginScale, whose cut line is a die line. No export changes size, and there is no new option to set. -
Engine: CMYK and YCCK JPEGs without embedded profiles now use the document CMYK profile in managed scenes. Set
scene/colorConversionModetoManagedto update an existing scene;Legacypreserves its previous appearance. Images with embedded profiles now have consistent colors in the editor and server-side renders.
Node Native Argument Validation
-
Engine/Node Native:
block.export,block.exportAudio,block.addImage,block.applyAnimationandscene.zoomToBlockreport an error for an argument of the wrong shape instead of acting on a coerced value.block.exportAudioaccepts only(block, options), the signature it declares and the one the web bindings accept; a positional mime type is no longer taken.editor.setSettingon anIntsetting requires a whole number instead of truncating one. -
Engine/Node Native:
block.exportchecks each option’s value, not only its type, and accepts the full option set the web bindings accept.pngCompressionLevelmust be 0-9, andjpegQuality,webpQualityandpdfImageQualitymust be above 0 and at most 1; the PDF and underlayer options are now declared, so a typo in one is reported instead of ignored.block.addImageacceptsAbsolute,PercentorAutoforsizeModeandpositionMode, and reports any other value. -
Engine/Node Native:
block.exportreports an error for anabortSignalinstead of ignoring it. This binding cannot stop a running export, so accepting the option would have let code written against the web bindings run without ever aborting.onProgressis now declared too, so a misspelled name is reported rather than dropped in silence.
Editor Layout, Labels & Configuration
-
Engine/Android: Explicitly declare API 34 as
minCompileSdkin AAR metadata. This preserves the existing consumer requirement when building with AGP 9. -
Editor/Web: An unnamed page now reads with its number — “Page 1”, “Page 2” — matching the title the canvas draws, and a video track and a caption track read “Track” and “Caption Track” where both previously read “Graphic”. This is the fallback name
cesdk.utils.generateBlockNamereturns, so it also shows in the inspector header and on a timeline clip. -
Editor/Web: The dock in the design and advanced editor configurations ends with a spacer that holds the new button at the bottom, so a dock entry appended with
position: 'end'lands below it. Passbefore: 'ly.img.spacer'to keep a button up with the libraries. -
Editor/Android: The timeline’s looping toggle moved from the center of the header to the end, next to the expand/collapse toggle. The play button now sits in the middle of the header.
-
Editor/Android: The timeline height is now expressed in track rows instead of pixels, through the new
heightproperty ofTimeline. It grows to at most three tracks by default withTimelineHeight.Dynamic, or you can set a fixed number of tracks withTimelineHeight.Fixed. -
Editor/Web: Removed the translation keys
input.bleedMargin.selectandproperty.bleedMargin. The panel labels the bleed withinput.bleedand its four side inputs withinput.sides.top,input.sides.right,input.sides.bottomandinput.sides.left. Override those instead. -
Editor/Web: Grid and safety margin controls now live in one “Grids & Guides” panel, opened from a row in the document and page inspectors.
-
Editor/Web: The navigation bar’s actions dropdown now has the accessible name and tooltip “Show more options”.
-
Editor/Web:
resetEditor()no longer switches the engine’s video captions off, so a video configuration no longer has to switch them back on. The caption UI stays gated by thely.img.video.captionfeature.
AI Generation Panels
-
Plugins/Web: The input tabs of the AI image and video generation panels name the conversion: “Text to Image” and “Image to Image”, or “Text to Video” and “Image to Video”. Override them with the
ly.img.plugin-ai-image-generation-web.fromText.labeland.fromImage.labelkeys, or the matching video keys. -
Plugins/Web: The input tabs no longer show an “Input” label, so the
ly.img.plugin-ai-generation-web.fromType.labelkey is no longer used. -
Plugins/Web: An AI generation panel now shows its reference image inside the prompt, rather than in a separate preview above it. An image selected on the canvas is offered in that row, outlined so it stands out on either theme, and attaches with one click. Selecting an image that is already attached highlights it.
-
Plugins/Web:
CommonProperties.ImageUrlnow renders the prompt as well as the image. A model whose schema has no image property keeps a prompt on its own. -
Plugins/Web: The Text and Image switch in an AI generation panel is now a pair of tabs, not a segmented control. The arrow keys move between them, which the segmented control did not support.
-
Plugins/Web: Quick actions gain the new prompt field: Combine Images, Create Variant, Edit Image, Remix Page with Prompt, Swap Background and Change Text To.
-
Editor/iOS: The image style thumbnails in the AI image generation plugin no longer draw a border.
License Diagnostics
- Engine: A license with a missing or wrong value now fails with
LICENSE.CLAIM_INVALID, which names the value, instead ofLICENSE.INVALID.
Bug Fixes
Engine
-
An archive no longer keeps a
buffer://URL for a resource it could not include. Such an archive pointed a block at a different file and crashed the engine when it was loaded.saveToArchivenow reportsSCENE.ARCHIVE_BUFFER_DATA_MISSING, and loading an archive that already holds one clears the reference. -
saveToArchivenow finishes when a referenced resource cannot be loaded. In the browser it returned a promise that never settled, so a download did nothing and gave no error. On the native engines it crashed the process. A missing image, an unreachable host, and an unloadable font in the settings all caused this. The archive keeps the original URI of such a resource. -
A malformed block id inside an array is refused as well, so
block.group([5.7, 8.7])reports an error rather than grouping the blocks those values round to. -
Combining blocks no longer shows a fill that the first block had hidden. The result now keeps the fill hidden, as it was.
-
A
data:URI now loads on every platform. Only the browser accepted one before, because it passes the URI to the host rather than fetching it, so a scene that loaded in a browser failed to load on Node, Android, iOS, macOS and Windows. -
block.getTypefaceanswers for a text block that was never given a typeface, on every binding. The engine bundles a default font but shipped no typeface declaring it, so the call reported that the default was not registered even though the font it names is present. -
block.getTextFontWeightsreports the weight the default font actually has. For a block with no typeface it previously answerednormalregardless — a weight the bundled default, which is Semi Bold, does not have. -
A
data:URI now loads when its base64 payload is split over several lines or holds spaces. Such a URI gave an error, or an image built from only part of the data. -
Undo, redo and applying a template no longer crash when the scene holds a page without a parent. Such a page is one that is not appended yet, or a duplicate made with
attachToParentset to false. Page carousel mode no longer crashes on such a page either. -
An image that is flipped both horizontally and vertically becomes axis-aligned again after a content-aware resize or a crop preset. The rotation could land just short of a full turn, which left the image mirrored and made the crop tool move the wrong edges.
-
The fill API now reports an unknown block as
BLOCK.UNKNOWNinstead ofBLOCK.FILL_MISSING. -
An image that was added or drawn while the canvas was zoomed out is no longer shown at that low resolution after zooming in. It is decoded again at the resolution the canvas needs.
-
Fixed a v4 license that failed to unlock the SDK when the license server added a field that the SDK does not read.
-
A locked block now holds what sits inside it. A child of a locked group or track cannot be dragged, nudged or resized on the canvas, and
alignHorizontally,alignVertically,distributeHorizontallyanddistributeVerticallyskip it, where before only the block’s own lock counted.isAlignableandisDistributablegive the same answer as those endpoints. Each block keeps its own flag, so unlocking a container leaves a child that was locked on its own still locked. The chain stops at the page and at the scene: a lock on either holds only the block that carries it.setTransformLockedandisTransformLockedare unchanged and still read and write a block’s own flag. -
Resizing a block no longer moves the opposite edge when the handle is dragged back to the start size or against a movement constraint.
-
A cropping resize that the page movement constraint or an exclusion area stops no longer keeps scaling the content. The frame held its edge while the image behind it grew with the pointer.
-
A scene export no longer takes its size from a hidden block. A block that is hidden, on its own or inside a group, now changes neither the pixel size nor the content of an exported scene. The exported pixel dimensions get smaller for a scene that holds a hidden block outside its pages. A page export keeps its size from the page, so it is not affected.
-
A scene export no longer takes its size from a block that stays out of the export. A block with
includedInExportset to false now changes neither the pixel size nor the content of an exported scene. A page export keeps its size from the page, so it is not affected. -
A source set now keeps every entry. Two files of the same width are two entries, and only the first one stayed before.
-
The engine now reads the size of a source set entry that states a width and height of
0. Such an entry gave the engine no way to tell a small file from a large one, so it could load a large file into a small block. -
Fixed SRT caption imports with non-ASCII UTF-8 text.
-
A text block on a path no longer draws its block background. The rectangle did not follow the curve. The setting stays, and the background draws again when the path is removed.
-
A video export of a page no longer hangs at the first frame when a block on another page is still loading. A block with an error on another page no longer cancels the export.
-
A video export of a page now draws only the blocks of that page, as an image export does. A block outside that page, for example on another page at the same place, no longer appears in the video.
-
A text getter no longer moves a running camera animation, and it costs 7× less while one runs. The text APIs still refresh the text before they read it, also when implicit updates are off.
-
Fixed a crash in
restoreBufferson macOS when the engine already held a buffer. The call now replaces the buffers as documented.
Engine (Web + Node)
-
A promise from
engine.actions.run()that is discarded while the run is still in flight atengine.dispose()no longer surfaces as an unhandled rejection. Awaiting it still rejects withEngine has been disposed. -
Web: A string with a lone UTF-16 surrogate, such as text cut in the middle of an emoji, no longer loses characters or breaks the scene. The engine stores U+FFFD in its place. A scene saved with such a string now loads again. A scene that an older release saved with such a string still fails to load. Node: A string with a lone UTF-16 surrogate no longer loses characters or breaks the scene. The engine stores U+FFFD in its place, as
@cesdk/node-nativedoes on Node.js and Deno.
Engine (Web + Node Native)
- Node Native: A method that returns a promise now rejects when an argument is invalid, instead of throwing before the promise is created. A caller who wrote
.catch()— which is what a promise-returning method invites — did not see the failure at all. Web: A method that returns a promise now rejects when an argument is invalid, instead of throwing before the promise is created. This affectsasset.findAssets, the twoaddLocalAssetSourceFromJSON*methods,block.loadFromURL,block.loadFromArchiveURL, the twoadd*FileURIToSourceSetmethods,scene.createFromImage,scene.createFromVideo, and the foureditorURI and font helpers.
Engine/Web
-
A negative block id, or one above
4294967295, now reports the same error as any other malformed id. Both used to surface an internal message about “an argument of type unsigned int”. -
A license error during initialization now rejects with its
EngineError. Before, it was aWasmLoadErrorthat reported missing assets. -
editor.getSettingandeditor.setSettingreport an unknown key as a proper engine error, carrying the same code, hint and documentation link every other engine error has. They previously threw a plainInvalid setting keyerror with none of that. The check now asks the engine instead of consulting a built-in list of keys, so a setting the engine supports is no longer refused because the list had not been updated for it.
Engine/Node
-
A block id that is not a whole number in
[0, 4294967295]is now refused. Such an id used to be converted rather than rejected, so it reached a different, existing block:getName(5.7)returned block 5’s name,getName(NaN)read block 0, and a setter wrote to the block it converted onto. -
A failed license request during
CreativeEngine.initno longer stops the Node process while the engine assets still load.
Engine/Node Native
-
actions.get(id)returns the function you registered instead of alwaysundefined, so a host can invoke a registered action synchronously by reference as it can on the web bindings. -
asset.fetchAssetnow reports an error for an asset source that does not implementfetchAsset. It previously terminated the whole Node process, which notry/catchcould prevent. -
editor.setSafeAreaInsetskeeps the value of every side you leave out. It previously reset an omitted side to zero. -
An asset reaches a source’s
applyAsset,applyAssetToBlockandapplyAssetPropertycallback without its empty optional fields, matching the web bindings. A callback that testedif (asset.credits)previously took that branch for an asset with no credits. -
block.setTextFontSizeandblock.getTextFontSizestreat theirunitoption the way the web bindings do. Both boundaries carry the scene’s own font-size unit, so a value already in that unit is passed through untouched. They converted to and from points instead, so on a Pixel scene at 300 dpisetTextFontSize(text, 54, { unit: 'Pixel' })stored 54 × 72 / 300, and every later read of the rawtext/fontSizevalue —block.getTextRunsamong them — was smaller than the web bindings’ by the same 4.17 factor. -
asset.canManageAssetsreports whether a source declared the deprecatedcanManageAssetsflag, matching the web bindings. It previously probed the engine and answered a different question — whether assets could be added to or removed from the source — so a source added withaddLocalSourcereportedtruewhere the web bindings reportfalse. -
block.combinereports an unknown boolean operation as the same engine error the web bindings report, naming every operation it accepts. It previously refused the call from a list kept in the binding, with an error carrying none of the usual code, hint or documentation link, and the list had to be updated by hand whenever the engine learned a new operation. -
CreativeEngine.initwith an invalid license now rejects with an error thattry/catchcan handle. Before, it stopped the Node process.
Engine/Android
-
Fixed a crash in
getAudioInfoFromVideofor a video with audio tracks. The call now returns theAudioTrackInfolist. -
Fixed a crash in
setCameraPreviewwhen themirroredStateflow changes after the first frame. The orientation update now runs on the engine thread. -
Video preview and export no longer fail with a decoder resource error for high-resolution videos, such as 4K phone recordings. A decoder that decodes slowly is no longer treated as stuck and rejected, and the low-latency decode preference no longer excludes hardware decoders that do not advertise the feature.
-
Fixed popping sounds when exporting videos with loud or overlapping audio.
-
Fixed audio being cut off at the end of video and audio exports.
Editor/Web
-
An action still running when the editor is disposed no longer logs an unhandled rejection.
-
An asset or asset source credit registered without a
urlnow shows its name in the asset info popover instead of the literal text “name”. -
A locked block no longer moves in the stacking order and no longer flips. Bring Forward, Send Backward and Flip in the canvas menu, and the Position controls in the inspector, now refuse it the way dragging it on the canvas already did.
-
A block inside a locked group counts as locked everywhere. It was possible to reorder, flip or align one, even though the group could not be moved.
-
The camera animation started by
scroll.toPageandscroll.toBlockno longer throwsCannot read properties of null (reading 'setPositionX')when the editor is disposed mid-animation. The animation now stops instead. -
ly.img.shape.optionsnow gates only the shape option controls it names — points, inner diameter, sides, corner radius and line width. The Replace Shape and Edit Path rows keep their own flags,ly.img.replace.shapeandly.img.shape.edit, so enabling one of those is enough to show it, in the inspector panel’s Shape section and in the inspector bar’s Shape button alike. Previously all three were hidden together. -
The text background controls are disabled for text on a path.
-
Fixed an issue where the measurement theme design tokens would not be parsed properly ended up breaking the layout of the asset library grid.
-
The video timeline no longer scrolls to a selected clip that is already visible. Selecting, dragging or trimming a clip no longer shifts it away from the pointer, and a long clip no longer snaps to its start. The timeline still scrolls to a clip that is selected while completely out of view.
-
As an Adopter, clicking a different placeholder after closing the replace panel opens the panel again. Before, it opened again only for the first placeholder that was selected.
-
The replace panel stays open while you move or resize the selected block on the canvas. Before, it closed when the drag started.
-
A library card dragged immediately after it is pressed now shows its thumbnail while it is dragged. It sometimes showed an empty box instead.
Editor/iOS + Android
- Fixed an issue where auto captions could not transcribe video recorded with the camera or added without the
videoblock kind.
Editor/iOS
- Fixed the “None” image style in the AI image generation plugin showing a blank box instead of an icon in the style selector and the style picker sheet.
Editor/Android
-
Fixed
InspectorBar.Button.rememberVoiceover()sharing its id withrememberMoveAsClip(). The button now usesInspectorBar.Button.Id.voiceover, so it can be addressed inInspectorBar.ListBuilder.modifyand no longer collides with the move-as-clip button. -
Fixed the timeline Play button not restarting playback from the beginning when the playhead is at the end and looping is off.
Editor/Flutter + RN
- Fixed an issue on iOS where closing the editor kept it in memory and kept playing video and audio until the editor was opened again.
Camera/iOS
- Fixed second-camera clips and photos appearing at the wrong time on the timeline when a session mixed single-camera and Dual Camera captures.
Plugins/Web
-
The Create Video quick action, now labelled Create Video from Reference, attaches the selected image to the video prompt beside any images already there, is disabled once the prompt has no room left, and opens the panel on the provider that owns the action. Before, the image was stored under the image provider’s id and never reached the video panel, and providers whose image property is not
image_urlsnever received it. -
A print-ready PDF export now finds its ICC profile in a bundled app.
Version v1.82.2 Changelog September 26, 2026
Breaking Changes
Non Breaking Changes
- Engine: A license with a missing or wrong value now fails with
LICENSE.CLAIM_INVALID, which names the value, instead ofLICENSE.INVALID. - Engine/Web: A license error during initialization now rejects with its
EngineError. Before, it was aWasmLoadErrorthat reported missing assets. - Engine/Node: A failed license request during
CreativeEngine.initno longer stops the Node process while the engine assets still load. - Engine/Node Native:
CreativeEngine.initwith an invalid license now rejects with an error thattry/catchcan handle. Before, it stopped the Node process.
Version v1.82.1 Changelog September 21, 2026
New Features
Licensed Codec Packs
- Engine/Node: Added support for licensed codec packs downloaded from the licensing dashboard on Linux x86_64. Packs are automatically detected in
$HOME/.local/share/cesdk-codecs; setCESDK_LICENSED_CODEC_PACKto use a custom installation directory.
Bug Fixes
Engine
- Undo, redo and applying a template no longer crash when the scene holds a page without a parent. Such a page is one that is not appended yet, or a duplicate made with
attachToParentset to false. Page carousel mode no longer crashes on such a page either. - A video export of a page no longer hangs at the first frame when a block on another page is still loading. A block with an error on another page no longer cancels the export.
- A video export of a page now draws only the blocks of that page, as an image export does. A block outside that page, for example on another page at the same place, no longer appears in the video.
Engine (Web + Node)
- A string with a lone UTF-16 surrogate, such as text cut in the middle of an emoji, no longer loses characters or breaks the scene. The engine stores U+FFFD in its place, as
@cesdk/node-nativedoes on Node.js and Deno. On Web, a scene saved with such a string now loads again. A scene that an older release saved with such a string still fails to load.
Version v1.75.2 Changelog September 15, 2026
Breaking Changes
Non Breaking Changes
- Engine/Web: Applied critical fixes to tracking and licensing in the Web and Node.js SDKs.
Version v1.76.2 Changelog September 14, 2026
Breaking Changes
Non Breaking Changes
- Engine/Web: Applied critical fixes to tracking and licensing in the Web and Node.js SDKs.
Version v1.82.0 Changelog September 10, 2026
Breaking Changes
-
Engine/Android:
BlockApi.exporttakes a new optionalprogressCallbackparameter afteroptions. Calls that passonPreExportoruriResolverpositionally must switch to named arguments. -
Editor/Web: Removed the
legacyNonResponsivePanelPositionfeature flag. Integrations that set it no longer force the wide layout. -
Editor/Web: The video timeline controls bar is now driven by the Component Order APIs under the new
ly.img.video.timeline.controls.barUI area (cesdk.ui.setComponentOrder,getComponentOrder,insertOrderComponent,updateOrderComponent,removeOrderComponent). The built-in controls are registered as components (ly.img.video.timeline.background,.split,.playbackInfo,.playPause,.loop,.zoom,.toggle) and custom components can be added viacesdk.ui.registerComponent. A newly.img.video.timeline.controls.barFeature API flag gates the whole bar (parallel toly.img.canvas.bar). Breaking: the SDK no longer ships a built-in order for this bar — without configuration the controls bar is empty and not rendered. Set the order explicitly to keep the previous controls, or pin the configuration below 1.82 withcesdk.setEditorCompatibilityVersion. The bar’s internal DOM also changed from a fixed three-column grid to a flat flex row driven byly.img.spacercomponents, so custom CSS targeting the old internal group containers no longer applies. To restore the previous controls:cesdk.ui.setComponentOrder({ in: 'ly.img.video.timeline.controls.bar' }, ['ly.img.video.timeline.background','ly.img.video.timeline.split','ly.img.spacer','ly.img.video.timeline.playbackInfo','ly.img.video.timeline.playPause','ly.img.video.timeline.loop','ly.img.spacer','ly.img.video.timeline.zoom','ly.img.video.timeline.toggle']);See the v1.82 migration guide and the starterkit-video-editor-ts-web / starterkit-advanced-video-editor-ts-web repositories (and the full starter kit upgrade) for more info.
-
Editor/Web: The clip ellipsis button on timeline clips can now be hidden through a dedicated Feature API flag,
ly.img.video.timeline.clip.menu. It is enabled by default —cesdk.feature.disable('ly.img.video.timeline.clip.menu')hides the button,cesdk.feature.enable(...)shows it again. The flag gates only the trigger; the clip context menu order set viacesdk.ui.setComponentOrder({ in: 'ly.img.video.clip.menu' }, ...)is unaffected. Breaking: integrators that maintain an explicit feature allowlist must addly.img.video.timeline.clip.menuto keep the button visible (see the v1.82 migration guide; the starter kits list it in theirfeatures.ts). -
Engine: A block that has only a preview image is no longer pending. It renders the preview, so an export finishes. Use
setStateto keep a block pending. -
Engine:
isCapabilitySupportednow answers for the codecs this build really has.hevcEncodeisfalseon Linux, Windows and Android, where the engine has no HEVC encoder. It wastruebefore. -
Engine/Node: Added
videoCodecto the video export options, withVideoCodec.H264andVideoCodec.HEVC. It defaults to H.264, so existing exports are unchanged. CheckisCapabilitySupported('hevcEncode')first: where the platform has no HEVC encoder, the export fails instead of falling back. -
Engine/Node: Fixed
enableHEVCbeing ignored. It is deprecated; usevideoCodec. -
Engine: Fixed missing picture on HEVC exports with audio.
-
Engine: Fixed an export that was refused leaving the encoder busy, which failed every later export.
-
Engine/Web:
VideoMimeTypeis'video/mp4'only.'video/quicktime'was in the type, but the engine has never written a QuickTime file and rejected it at run time. Use'video/mp4'. QuickTime stays valid for media you import. -
Engine/Swift: Removed
TransitionType.none. To remove a clip’s transition, destroy the block returned byengine.block.getTransition(_:)— destroying detaches it automatically. UseremoveTransition(_:)instead when you want to detach the transition but keep the block for reuse; it does not destroy the detached block. -
Renderer: The non-assetless Docker containers now only ship a single asset tree instead of shipping all asset versions in subtrees of
/opt/cesdk-renderer/assetslike before. This reduces image size and matches other platforms. If you need access to other asset versions, you can download them from the documentation pages for self-hosting your own assets for the matching CE.SDK version and bundle them in your own Docker image built on top of the assetless variant.
Non Breaking Changes
-
Editor/Android: Add automatic caption generation. The new
ly.img:plugin-auto-captionspackage adds a Generate Automatically action to the Add Captions sheet that transcribes the video’s speech into time-synced, styled captions. Register it with.then(::AutoCaptionsPlugin) { provider = GatewayTranscriptionProvider(apiKey = "sk_…") }to use ElevenLabs Scribe through the IMG.LY AI Gateway, or implementTranscriptionProviderto plug in any other speech-to-text service. Generation runs in a cancellable state and leaves the scene untouched when cancelled; captions land in a single undo step. Integrators who want to own the whole pipeline can replaceAutoCaptionsPlugin.captionsGenerationwith their ownCaptionsGeneratorand return their own SRT or VTT file — aproviderstays required either way. -
Editor/Android: Add caption editing to the video editor. Register the
captionsdock button to let users create captions manually, import SRT/VTT files, edit caption text and timing on a dedicated timeline lane, apply style presets, and fine-tune a selected caption from the caption inspector (Edit Captions, Style, Split, Format, Fill & Stroke, Text Background, Delete). While editing, an action bar above the keyboard merges, splits, adds, and deletes captions, and steps to the caption above or below; merging, adding, and deleting are also available by swiping a row. Return splits a caption at the cursor — or starts the next one at the end of the text — and Backspace at the start merges into the caption above, or deletes it when empty. Style presets and core styling — font, size, alignment, colors, and background — apply to every caption on the track. Captions are burned into the exported video by the engine. -
Editor/Flutter: Added Swift Package Manager support to the
imgly_editorplugin. Flutter 3.44 and later resolves the plugin via Swift Package Manager by default; CocoaPods keeps working on older Flutter versions. -
Camera/Flutter: Added Swift Package Manager support to the
imgly_cameraplugin. Flutter 3.44 and later resolves the plugin via Swift Package Manager by default; CocoaPods keeps working on older Flutter versions. -
Editor/Web: Added
builder.Tabs()to switch between views inside a panel. Only the selected tab builds its content, each tab takes an optional icon, tooltip andisActiveindicator, and the arrow keys, Home and End move between them. -
Editor/Web: The animations panel shows In, Loop and Out as tabs rather than stacked sections, each marked when that group has an animation applied. The inspector’s Design/Placeholder switch and the caption panel’s Content/Style switch use tabs too.
-
Editor/iOS: Add an
IMGLYEditorproduct to theIMGLYUI-swiftSwift package. You can now depend on the editor on its own — the product the Starter Kit guides tell you to add — instead of pulling the wholeIMGLYUIumbrella.import IMGLYEditorresolves against it directly. -
Editor/Web: Bounded numeric controls in the inspector now have a minus and a plus button inside the input. A press steps the value and stops at the control’s limits, holding a button repeats the step, and a whole press becomes one undo step. Typing a value still works. The buttons are not tab stops, because the field’s Up and Down arrow keys already step.
-
Editor/Web: These controls replace their slider with a stepper: letter spacing, line height and paragraph spacing; polygon sides, star points, star inner diameter, line width and corner radius; cutout smoothing; and text background corner radius.
-
Editor/Web: These controls keep their field and gain the buttons: stroke width, cutout offset, grid width and height, shadow distance and blur, and text background horizontal and vertical padding.
-
Editor/Web: The font size control gains the same buttons and keeps its preset list. The list now opens on a click on the field, or with
Alt+ArrowDown, and replaces the dropdown button beside it. -
Editor/Web: Added a
showStepperoption tobuilder.NumberInput()that renders the same decrement and increment buttons. -
Editor/Web: Added the translation keys
input.stepper.change,input.stepper.decrease,input.stepper.increase,input.stepper.decreaseValueandinput.stepper.increaseValue. The keysproperty.textBackground.horizontalPadding.descriptionandproperty.textBackground.verticalPadding.descriptionare gone, because the controls they described are steppers now and name their own buttons. -
Engine: Added the
pdfChunkSizeexport option, which sets the upper bound in bytes for a single chunk of PDF output. It matters most for a streamed export, where it is the memory the caller holds for one chunk: a larger value lowers the per-chunk overhead and raises that memory, a smaller value does the opposite. Leaving it unset keeps the engine default. A value outside the supported range is clamped into it rather than failing the export. -
Engine: Added per-page progress reporting to PDF export on Web, iOS, and Android, mirroring video export progress. See the Export to PDF guide.
-
Editor/Web: The export dialog now shows a progress bar instead of a spinner while a multi-page PDF exports.
-
Editor/React Native: Added opt-in Swift Package Manager support to
@imgly/editor-react-nativefor React Native’s experimental SPM mode (npx react-native spm, React Native 0.87 and later). CocoaPods currently remains the default integration path. -
Editor/React Native: Fixed a crash on iOS when an export result contained no artifact, scene, or thumbnail — the result now carries
nullfor the missing fields, matching Android. -
Camera/React Native: Added opt-in Swift Package Manager support to
@imgly/camera-react-nativefor React Native’s experimental SPM mode (npx react-native spm, React Native 0.87 and later). CocoaPods currently remains the default integration path. -
Camera/React Native: Fixed a crash on iOS when
openCamerareceived settings that could not be parsed — the call now rejects with error codeE_PARSINGinstead. -
Editor/Web: Added a
Gapcontrol to the document inspector that adjusts the spacing between the pages of a horizontally or vertically stacked scene, together with aGap Unitdropdown that chooses whether the value is measured inScreen Pixelsor inDesign Units.Screen Pixelsaffects the canvas preview only — it keeps the gap constant on screen at any zoom level, while exports always interpret the gap in design units. Switching the unit never rewrites the number, so the same value is reinterpreted rather than converted. Both controls are shown only while a horizontal or vertical stack layout is active and the stack holds at least two pages — a stack’s spacing sits between its children, so there is nothing for it to do on a single page. The value is limited to10000; the engine itself sets no upper bound, but a very large gap inScreen Pixelsstays that size at every zoom level and puts the next page out of reach. Both rows can be hidden with the newly.img.scene.layout.spacingfeature flag. -
Editor/Web: The scene layout buttons in the document inspector no longer reset the gap between pages. Previously, switching to a stacked layout — or clicking the already-active layout button — overwrote
stack/spacingwith a fixed35screen pixels, discarding any gap that had been set throughengine.block.setFloat(stack, 'stack/spacing', …). The current gap is now carried forward instead, including across a round trip through the free layout, and35is used only when no stack exists to read a gap from. Whether this is visible depends on how the scene was created: a scene created throughcesdk.actions.run('scene.create', …)with a page preset already starts at35, so it looked the same before and after, while a scene created without a page preset starts at48and previously dropped to35on the first layout click. Either way, a gap your integration set throughengine.block.setFloat(stack, 'stack/spacing', …)is no longer discarded. -
Editor/Web: Switching a scene to the free layout now stores the stack gap on the scene in the metadata keys
stackSpacing/spacingandstackSpacing/inScreenspace, so that selecting a stacked layout again restores it. Like the existingfreeLayout/position*keys written by the same code path, these are visible to integrations throughengine.block.findAllMetadata(scene)and are saved with the scene. -
Engine/iOS: Added two
BlockAPI.exportoverloads that deliver the exported PDF incrementally in bounded chunks instead of building the whole document in memory, so large multi-page documents such as photo books and magazines export without exhausting memory. One writes the bytes into a file as they are encoded, the other hands each chunk to a closure. Because the chunks are handed over synchronously, a slow destination throttles the encoder rather than buffering chunks in memory. -
Editor/iOS: Added the
exportToFileconfiguration helper, which fuses exporting and writing the result to a file into a single streamed pass so the full document is never held in memory. -
Editor/Web: Added a
timeline.setHeightaction to control the video timeline’s height. Callcesdk.actions.run('timeline.setHeight', { height: 320 })to give the timeline a fixed height,{ height: 'auto' }to restore the default content-hugging behaviour, or{ maxHeight: 400 }to cap how tall the auto-growing timeline may get. -
Editor/Web: Added a
timeline/transitionControlVisibilityeditor setting controlling the clip transition control on the video timeline. Setcesdk.engine.editor.setSetting('timeline/transitionControlVisibility', 'always')to keep the control shown, or'hover'(the default) to reveal it on hover/focus. -
Editor/Web: Added keyboard shortcuts for moving between editor regions:
F6/Shift+F6now also cycle through the timeline, the navigation bar, the dock, the canvas bars, and open panels.Alt+4— move focus to the timeline.Alt+5— move focus to the navigation bar.Alt+6— move focus to the dock.Alt+7/Alt+8— move focus to the canvas bar above / below the canvas.
-
Editor/Web: Improved keyboard and screen-reader accessibility of the video timeline and the editor chrome:
- Timeline clips are tab stops:
Enter/Spaceselects a clip (Shiftadds to the selection), and screen readers announce the clip’s name, duration, and selection state. - The playhead is an operable slider: arrow keys step,
Shift+Arrow,PageUp/PageDowntake larger steps,Home/Endjump to the start and end. Clicking it no longer moves keyboard focus. - The trim inspector, the trim handles, and the timeline resize handle can be operated with the arrow keys.
- Popover menus such as the clip context menu navigate with the arrow keys, and the clip context-menu button has an accessible name.
- The navigation bar, dock, canvas bars, inspector bar, and panels are exposed as ARIA landmarks.
- Panels no longer trap keyboard focus. A panel opened from a control moves focus into it and returns focus to that control or block when it closes.
- A collapsed timeline and hidden UI elements (an empty inspector bar, covered stacked panels) are skipped by keyboard navigation.
- Focus rings are no longer clipped by scrolling containers and no longer appear after pointer interactions.
- Timeline clips are tab stops:
-
Engine/Web, Engine/Node: The default typeface assets now ship as WOFF2 instead of TTF. The font files are about 66% smaller, so editors load fonts faster on slow connections. Scenes that reference the previous TTF files continue to work.
-
Engine/Web, Engine/Node: A PDF export that uses a WOFF2 font embeds the glyph outlines instead of the font program. This already applied to WOFF and variable fonts, and now also applies to the default typefaces. The rendered output and the text search stay the same.
-
Editor/Web: The cutout inspector panel now shows the Offset and Smoothing controls again.
-
Editor/Web: Fixed an issue where the highlighted option in dropdowns could scroll out of view while navigating with the Arrow Up and Arrow Down keys.
-
Engine: Cancelling a PDF export now stops it. Before, an export that was cancelled kept rendering every remaining page and only the result was dropped. On Web an
abortSignalstops the export, on iOS the cancellation of the enclosingTask, and on Android the cancellation of the coroutine. A cancelled export fails withENCODE.EXPORT_CANCELLED. -
Engine: The licensed codec concurrency limit now only applies when video or audio codecs are actually used. Image-only workloads no longer reserve a codec license slot, and a video operation fails with a clear error when all slots are in use.
-
Engine/Node Native: Engine creation no longer stops the JavaScript event loop while the license server activates an API key. This applies to the native bindings only.
-
Editor/Flutter: Fixed an issue where effects applied to paused videos were not immediately visible when using TextureView.
-
Editor/Web: A font size applies to the selected part of a text, whether stepped, typed or picked from the list.
-
Editor/iOS: A video picked from the photo roll now keeps its own duration instead of being added as a 5 second clip. The duration is read from the video when it is imported, so it also shows on the asset library tile.
-
Engine:
relocateResourcenow moves every reference to a resource, also the references that carry a URL fragment. A variable font keeps its weight after the move. -
Engine: A saved
.imglyarchive stays editable after you load it and move its resources. Before, the scene reported abufferURL and could not be saved. -
Editor/Web: Fixed an issue in Safari where edge artifacts on asset library cards remained visible on low pixel density displays, even without hovering.
-
Engine: Saving to a string with a resource callback no longer hangs, and no longer reports the resources of an earlier save.
-
Engine: Saving a scene that nothing has edited now gives the same bytes every time. Before, the blocks, the selection, the block metadata, the spot colours and the template variables were written in an internal order that moved on every load, so hashing a scene to detect a change, content-addressed storage and
ETagcaching all reported a change that had not happened. The saved content was never affected. -
Engine: Thin seams no longer appear on the canvas between opaque blocks that share a straight, axis-aligned edge.
-
Engine/Swift: Fixed
ExportOptions.webpQualitybeing ignored byexportWithColorMask. WebP exports with a color mask now use the given quality instead of the default. -
Engine/Swift: Deprecated
LicenseError.missing. An empty license key activates evaluation mode instead of failing, so this error is never thrown. Exhaustiveswitchstatements overLicenseErrorkeep compiling unchanged. -
Editor/Android: Fixed dragging a clip into a gap narrower than the clip on an overlay track moving that clip and its left-hand neighbour to the start of the timeline. The clip now lands right after its neighbour and pushes the following clips later.
-
Editor/iOS: Fixed dragging a clip into a gap narrower than the clip on an overlay track moving that clip and its left-hand neighbour to the start of the timeline. The clip now lands right after its neighbour and pushes the following clips later.
-
Engine/Web/Node:
editor.setURIResolver()andeditor.setURIResolverAsync()now remove the resolver when you give themnullorundefined. Before, the resolver stayed active. -
Engine: Exporting a still image of a block containing a video fill now waits for the frame at the current playback time to be decoded. Previously the export could return the previously decoded frame, so stills taken at different playback times (timeline scrubbing, thumbnail-at-time) could come back identical.
-
Editor/Web: Fixed an issue where the Animations control and the “Allow to Change Animations” placeholder option were enabled in design-based starterkits.
-
Engine/Linux: Improved compatibility with H.265 video files in the licensed codec pipeline.
-
Engine/Swift: Export results no longer copy the whole payload when they cross into Swift. This lowers the peak memory of image, PDF, video, audio and color mask exports by the size of one result.
-
Engine/Node: Export results no longer copy the whole payload when they cross into JavaScript, which lowers the peak memory of every export by the size of one result. Applies to
@cesdk/node-native. -
Engine: Fixed a video export result becoming invalid when a later export started. Keeping the data of one export while starting the next one now works.
-
Engine/Node: A PDF export no longer builds the whole document in memory. The engine writes it to a file in the temp directory while the export runs, so the peak no longer grows with the number of pages. Large multi-page documents such as photo books and magazines export without exhausting memory. The result of
exportis unchanged. -
Engine/Node: Platform capabilities are now detected while the engine starts. Before this, every capability reported unsupported, so features that ask for one, such as the staged export above, never ran.
-
Engine/Web: PDF exports via
engine.block.export()are now written to a temporary file (origin private file system) while the export runs, instead of being assembled in memory, on browsers that support it. Exporting a large document no longer holds the finished file in memory and the returnedBlobis backed by that file. Its content and type are unchanged. Browsers without support keep the previous behavior. The temporary file backs the returnedBlob, so it stays on disk after the export and is collected automatically. -
Engine/Android, Engine/Swift: PDF exports are now written to a temporary file while the export runs, instead of being assembled in memory. Exporting a large document no longer holds the finished file in memory. The exported bytes are unchanged. The temporary file is removed as soon as the export result is released.
-
Editor/Web: Softened the light theme’s hover fill (
--ubq-interactive-hover), which held the same colour as the input background. Buttons, asset cards, select options, checkboxes and the timeline clip seam all hover differently now. -
Editor/Web: Added the
--ubq-interactive-input-hovertheming token, the hover fill for elements sitting on an input background. -
Editor/iOS: Added UI support for transitions, including
SheetTypes.Transition,SheetType.transition(style:id:),InspectorBar.Button.transition(...), and timeline controls. -
Editor/iOS: Added animation and transition previews for a better editing experience.
-
Editor/Web:
cesdk.setEditorCompatibilityVersion('1.82.0')pins an editor configuration to the CE.SDK version it was written for, so listed behavior changes from later versions do not apply to it. Call it aftercesdk.resetEditor(), which clears any previous pin. The CE.SDK editor configurations and starter kits pin it for you; a configuration that does not pin gets the current release’s behavior. -
Editor/Web:
ly.img.shape.optionsnow gates only the shape option controls it names — points, inner diameter, sides, corner radius and line width. The Replace Shape and Edit Path rows keep their own flags,ly.img.replace.shapeandly.img.shape.edit, so enabling one of those is enough to show it, in the inspector panel’s Shape section and in the inspector bar’s Shape button alike. Previously all three were hidden together. -
Engine: An opaque
page/marginFillColornow covers the bleed content of a rectangular page at every zoom level. A thin line of the content stayed visible at the outer bleed edge before, and it appeared and disappeared as the canvas was zoomed or panned. -
Engine: Fixed engine stalling on end-to-end video exports.
-
Engine: Fixed re-exporting a page on the same engine producing a static clip.
-
Engine/Web, Engine/Node: The default typeface assets now ship as WOFF2 instead of TTF. The font files are about 66% smaller, so editors load fonts faster on slow connections. The typefaces, their names, and the directory layout do not change.
-
Engine/Web, Engine/Node: A scene that names a font file from an older asset version still works. The engine reads the current file name from the registered typeface source, and every published asset version keeps serving its own files. A scene that stores a font path resolved against the asset bundle you serve needs a one-time migration. The “To v1.82 (Fonts)” upgrade guide shows how to find and rewrite those paths.
-
Engine/Web, Engine/Node: A PDF export that uses a WOFF2 font embeds the glyph outlines instead of the font program. This already applied to WOFF and variable fonts, and now also applies to the default typefaces. The rendered output and the text search stay the same.
-
Renderer: A scene that names a font file from an older asset version now exports. The renderer registers the asset sources of its bundled asset tree, so the engine reads the current file name from them. Before, the export was cancelled with
FILE_FETCH_FAILED.
Version v1.81.1 Changelog August 26, 2026
Breaking Changes
Non Breaking Changes
- Engine/Swift: Revert the video export cancellation fix introduced in 1.81.0, which could crash the app when a video export was cancelled.
Version v1.81.0 Changelog August 24, 2026
Breaking Changes
- Engine/Android: Removed
TransitionType.None. To remove a transition, destroy the transition block returned byengine.block.getTransition(...).
Non Breaking Changes
- Engine/Android, Editor/Android: Added portable CE.SDK Android agent skills for documentation, explanations, and project scaffolding with Kotlin and Jetpack Compose.
- Editor/Android: Added UI support for transitions, including the
SheetType.Transitionsheet type,InspectorBar.Button.rememberTransition, and buttons in theTimeline. - Editor/Android: Added animation and transition previews for a better editing experience.
- Engine/Web/Android/iOS:
scene.saveToArchiveaccepts a compression option for the scene inside the archive. - Plugins/iOS: Add the
IMGLYPluginAutoCaptionsplugin for automatic caption generation in the video editor. RegisteringAutoCaptionsPluginadds a primary “Generate Automatically” action to the Add Captions sheet that transcribes the scene’s audible content and creates styled, time-synced captions. The built-inGatewayTranscriptionProviderruns the ElevenLabs Scribe v2 speech-to-text model through the IMG.LY AI Gateway using an IMG.LY API key; any other speech-to-text service can be integrated by implementingTranscriptionProvider. - Editor/iOS: Add
EditorConfiguration.Builder.captionsGeneration(_:)to back the Add Captions sheet’s “Generate Automatically” action with a custom caption generation callback. - Editor/iOS: Add caption editing to the video editor. Register the
Dock.Buttons.captions()dock button to let users create captions manually, import SRT/VTT files, edit caption text and timing on a dedicated timeline lane, apply style presets, and fine-tune a selected caption from the caption inspector (Edit Captions, Style, Split, Format, Fill & Stroke, Text Background, Delete). While editing, an action bar above the keyboard merges, splits, adds, and deletes captions, and steps to the caption above or below; merging, adding, and deleting are also available by swiping a row. Return splits a caption at the cursor — or starts the next one at the end of the text — and Backspace at the start merges into the caption above, or deletes it when empty. Style presets and core styling — font, size, alignment, colors, and background — apply to every caption on the track. Captions are burned into the exported video by the engine. - Engine/Swift, Editor/iOS: Added portable CE.SDK Swift agent skills for documentation, explanations, and project scaffolding across iOS, macOS, and Mac Catalyst.
- Editor/Web: Transitions can now be opened from the inspector bar and the inspector panel.
- Engine: Scenes and archives are now compressed with Zstd by default, making saved scenes far smaller and both saving and loading faster. Saved scene strings change shape: they carry a
UBQ2prefix instead ofUBQ1. Loading accepts either, so existing scenes keep working. - Editor/Android: Fixed the background removal plugin decoding the source image on the main thread, which blocked the UI and triggered a StrictMode
DiskReadViolation. - Editor/Android: Fixed the editor reading file modification times on the main thread when loading file-based images, which triggered a StrictMode
DiskReadViolation. - Camera/Android: Fixed the photo preview reading the captured file’s modification time on the main thread, which triggered a StrictMode
DiskReadViolation. - Engine/Android: HDR videos (HDR10/PQ and HLG) are now tone-mapped to SDR during decoding, fixing severely incorrect colors in preview and export. This uses the HDR-to-SDR tone-mapping request introduced in Android 12, and only takes effect where the device’s video decoder supports it — in practice recent Qualcomm/Snapdragon hardware decoders.
- Engine/Android: Fixed a StrictMode
LeakedClosableViolationcaused by the internal OkHttp cache when a network fetch returned an error response (e.g. HTTP 404). - Editor/Android: the Resize sheet no longer shows the Crop/Cover/Fit content fill mode picker, honoring
SheetType.Crop.Mode.ResizeAll.hasContentFillMode = falseand matching iOS - Editor/Android: Fixed
shareFileresolving the file’s content uri on the main thread, which triggered a StrictModeDiskReadViolationwhen sharing an exported file. The uri is now resolved on a background thread and any failure is surfaced via theerrorstate instead of being thrown. - Engine: Fixed
saveToArchiveleaving remote URLs in the saved scene instead of bundling the referenced bytes. - Engine: Fixed variable-font handling in scene and block archives.
- Engine: Fixed a crash in audio waveform thumbnail generation. The crash could happen once the last requested sample was delivered or when the audio block was destroyed from within the chunk callback.
- Engine: Scene files no longer store the
basePathsetting. AbasePathstored by an older version is ignored on load. - Editor/Flutter: Fixed an issue where effects applied to paused videos were not immediately visible when using TextureView.
- Engine/Web: Fixed
scene.getMode()throwing aTypeErrorinstead of returningnullwhen no scene exists. - Engine: A text or caption style preset no longer replaces the text of a block that already exists. A preset writes its own text only when it makes a new block.
- Engine: PDF export with
exportPdfWithHighCompatibility: falsenow embeds photos as their original JPEG data if possible, drastically reducing export time and file size of image-heavy documents such as photo books. - Engine: Added the
pdfImageQualityexport option. Values below the default of 1.0 encode rasterized images (e.g. with effects applied) as lossy JPEG instead of lossless. Rasterized content that keeps transparency stays lossless, because JPEG has no alpha channel. - Engine/Swift: Fixed cancelling a video export leaving the device encoding the whole video.
BlockApi.exportVideosuspended on the engine callback and ignored task cancellation, so dropping the returned stream reported the export as cancelled while the background export engine kept rendering and encoding every remaining frame, holding CPU, GPU and battery until it finished. Cancelling now stops the export and releases the background engine. - Camera/Android: Fixed the photo/video mode toggle ignoring taps in mixed capture mode. The selection indicator briefly moved to the tapped icon and then snapped back without switching the capture mode.
- Engine/Linux: Improved compatibility with H.265 video files in the licensed codec pipeline.
Version v1.80.0 Changelog August 13, 2026
Breaking Changes
- Engine/Android: The automatic default video bitrate now uses the shared resolution/framerate formula, typically producing smaller files for common 30/60 fps HD presets. To keep the previous behavior, pass an explicit bitrate matching the old formula, e.g.
ExportVideoOptions(videoBitrate = width * height * frameRate.toInt() / 4). - Renderer: The base system for the Renderer Docker container has been upgraded from Ubuntu 24.04 to Ubuntu 26.04 to include upstream security vulnerability fixes that were not backported to Ubuntu 24, if you are building a custom image layered on top of our image you might need to adjust your Dockerfile.
- Engine/Web: The default build-in
Space(play/pause) andS(split clip) key bindings were removed from the@cesdk/enginebuilt-in shortcut catalog. Thevideo.playPauseandselection.splitactions are unchanged and can still be bound viaengine.shortcuts.set().
Non Breaking Changes
- Engine: Audio blocks and video fills can now fade in and out. Use
setAudioFadeInandsetAudioFadeOut, or theplayback/fadeIn/*andplayback/fadeOut/*block properties. The easing defaults toLinearand a duration of 0 (the default) disables the fade. - Editor/iOS: The text on path sheet now uses the same two-step flow as the animations sheet. The sheet opens with the path selection list only, and the adjustment controls (path position, direction, and offset) moved to a detail page that opens by tapping the selected path again. The default detent of the sheet changed from medium to tiny to match the filter, effect, and blur sheets.
- Editor/Android: The text on path sheet now uses the same two-step flow as the animations sheet. The sheet opens with the path selection list only, and the adjustment controls (path position, direction, and offset) moved to a detail page that opens by tapping the selected path again.
- Engine: Text on a path now selects the text by default. Its selection frame, alignment and snapping follow the visible text bounds instead of the path’s bounding box; click the path to switch to path selection, click the text to switch back. Only corner handles show while text is selected, and hovering the other representation previews the frame a click would switch to.
- Engine:
getScreenSpaceBoundingBoxXYWHreturns the visible glyph bounds for a selected text-on-path block in text mode; unchanged for unselected blocks and for path selection. - Engine: The clickable area of text on a path is now one continuous band matching the drawn glyphs, fixing flickering hover and clicks landing in the curve’s empty interior.
- Engine: Uniformly scaling text on a path no longer makes the letters wiggle or slide along the curve.
- Engine: Corner-resizing any block with snap-to-grid active no longer lets the anchor corner drift by a sub-pixel amount.
- Engine: Scenes and archives now share one
.imglyfile format. The newloadAPI opens any scene or archive file — including existing.sceneand.zipfiles. The previous load methods keep working too. - Editor/Web: A single “Import” option replaces “Import Design” and “Import Archive”. Scenes and archives saved from the editor now download as
.imglyfiles. - Engine/Android: Fixed a native memory leak that leaked the full payload of every
ByteBufferthe engine returned to Kotlin. This affectedBlockApi.export,exportWithColorMask,exportVideoandsaveToArchive,SceneApi.saveToArchive,EditorApi.getResourceData(once per chunk) and the buffer APIs. The leaked memory was native heap, so it counted against the app’s memory budget but stayed invisible to the Java heap profiler. Returned buffers are now reclaimed by the garbage collector. - Engine/Android: Fixed a leak where every export left behind a live
HandlerThread, along with roughly 4.6 MiB of native heap that was only reclaimed once that thread exited. This affectedBlockApi.export,exportWithColorMaskandexportVideo. Apps that exported repeatedly, such as batch or preview flows, accumulated one thread per export until the process was killed. - Editor/Android:
LibraryContent.Sections withaddGroupedSubSectionswhose asset source reports no groups now fall back to a single flat section instead of rendering an empty section - Editor/Android: categories consisting of a single
LibraryContent.SectionwithaddGroupedSubSectionsnow render their grouped subsections instead of auto-expanding into a flat grid of the section’sexpandContent - Editor/Android: the header count of a
LibraryContent.SectionwithaddGroupedSubSectionsnow shows the total across all groups instead of the count of a single group - Editor/Android: Fixed a crash (
IndexOutOfBoundsException) that could occur while editing text. - Engine: Text selection and cursor positions are now clamped to the current text.
- Editor/Web: Fixed crop mode overwriting a user-configured
page/allowResizeInteractionsetting. The value is now restored to its previous state when leaving crop mode instead of always being forced tofalse. - Engine: Fixed
getDominantColors. This function no longer counts as an export event. - Editor/Flutter: Fixed an issue where effects applied to paused videos were not immediately visible when using TextureView.
- Editor/Web: Fixed the Animations section missing for groups in the advanced video editor. Selecting a group now shows its animation controls in the inspector panel, matching the standard video editor.
- Engine/Web: Added the missing
Mod+Ccopy andMod+Xcut default keyboard shortcuts and registered headlesscopy,cut, andpasteactions; the split shortcut is nowsinstead ofMod+X. - Engine: Fixed undo/redo restoring a stale camera position when the restored history snapshot.
- Engine: Fixed image blocks that showed the preview image instead of the current image when the block is small on screen. The preview image is now only shown while the current image loads.
- Editor/Web: Fixed an issue where the inspector panel was switching to text properties while a page title is being edited.
- Editor/iOS: Fixed the export “cancel” confirmation dialog appearing in inconsistent positions during video export. It now anchors consistently to the progress sheet’s dismiss button.
- Engine: Fixed a hang when disposing the engine while network requests were still in flight on Apple platforms.
- Engine: Fixed page thumbnails (for example in the editor’s page overview) appearing vertically stretched.
- Engine: Fixed PDF export silently returning a corrupted file instead of an error when the device runs out of memory while finalizing the document.
- Plugins/Web: Fixed PDF/X-4 output from
@imgly/plugin-print-ready-pdfs-webfailing preflight metadata checks. Document info and XMP metadata now carry identical creation/modification dates, creator, producer, and title; values inherited from the input PDF no longer override them; non-ASCII titles are written correctly; and the XMP metadata stream is no longer compressed. - Engine/Web: Fixed a crash when saving a scene to an archive that references a font which is not currently loaded, for example an unused typeface variant.
- Engine: Fixed right-to-left text overflowing the right edge of a fixed text frame for wrapped lines.
- Editor/Web: Opening a color picker no longer freezes on scenes with many images. The image colors palette now shows the images on the current page, reuses previous results, and refreshes them after document edits.
- Engine: The
videoBitratevideo export option now accepts two named modes in addition to an explicit number:'System'(default — Web and iOS defer to the platform encoder; Android and GStreamer use the shared formula) and'Auto'(a bounded default derived from the output resolution and framerate, e.g. 5 Mbps at 720p30, 8 Mbps at 1080p30, 40 Mbps at 4K30). On iOS useVideoBitrate.auto, on AndroidVideoBitrate.Auto. - Engine/Web: Pass
videoBitrate: 'Auto'to avoid video exports freezing with an out-of-memory error caused by the browser choosing a near-lossless bitrate (Safari reached ~300 Mbps). - Engine/Android: The automatic default video bitrate now uses the shared resolution/framerate formula, producing smaller default files than before.
- Plugins/Web: AI Gateway failures now show a localized, human-readable message instead of the raw HTTP status and JSON response body. Running out of credits, an expired token, a model that is not on your plan, a temporary outage, and an unreachable gateway each get their own message.
- Plugins/Web: A request that never reaches the AI Gateway — the browser is offline, the gateway is unreachable, or the response was blocked for missing CORS headers — now asks the user to check their connection instead of reporting a failed generation. It is thrown as a
GatewayErrorwithcode: 'network_error'. - Plugins/Web: A generation failure the gateway reports inside an open stream now uses the reason the gateway sent, so a rejected prompt or a provider rate limit no longer claims the AI service is temporarily unavailable.
- Plugins/Web: Fixed AI quick actions failing silently. A failed generation stopped the spinner without telling the user anything; it now shows the same error notification as the generation panel.
- Plugins/Web: Added
GatewayErrorandisGatewayErrorexports to@imgly/plugin-ai-generation-web. Gateway failures are thrown as aGatewayErrorcarryingcode,status,operation, andrequestId, so an error-handling middleware can branch on the failure reason — for example to show a “Manage credits” action forinsufficient_credits. - Plugins/Web: Fixed the
durationoption on a provider’soutput.notification.errorbeing ignored. - Editor/Web: Fixed missing German translations for the DPI and page settings labels, which previously fell back to English.
- Engine: Fixed a native crash that could occur when audio waveform generation reached the end of the audio file.
- Engine: Exporting a rotated block with
allowTextOverhangno longer crops the result. - Editor/Web: Fixed an issue where the typeface library panel did not populate
queryData.querywhen querying asset sources, so custom asset sources implementing search viaqueryData.queryreceived an empty string. The panel no longer adds alabelfilter predicate on top of the query, so each source’s own search matching fully decides the results. - Engine: Picking another text curve while the text baseline is open in vector edit mode no longer leaves the previous curve’s anchor handles and outline on the canvas. The edit session now re-reads the new baseline path instead of keeping the stale one.
- Engine: Text that exceeds the length of its path remains selectable by clicking its visible glyphs.
- Engine: Resizing a selected text path with its corner handles now preserves the path’s aspect ratio.
- Engine: Text on a path whose offset makes it wrap around the end of the curve is now selectable on both sides of the wrap, and its selection frame covers all of its glyphs.
- Engine: Exporting a text block that sits on a curve no longer crops the glyphs that reach outside of the curve. The exported area now covers all of the rendered text instead of just the curve.
- Editor/iOS: Fixed the video timeline occasionally freezing and losing one of the split halves when splitting a clip on the background track.
- Editor/iOS: Fixed the voiceover recording panel sometimes opening with its top edge clipped.
- Engine: Fixed undo/redo of a page addition or removal changing the canvas zoom.
Version v1.79.0 Changelog July 28, 2026
Breaking Changes
- Engine/Swift, Editor/iOS, Camera/iOS: Packages for Apple platforms are now built with Xcode 26.4.1 and Swift 6.3.1, which are the new minimum requirements for using them.
Non Breaking Changes
-
Editor/Web: Added the following new keyboard shortcuts:
F6/Shift+F6— cycle focus forward / backward through the main editor regions (canvas, inspector bar, canvas menu).Alt+1/Alt+2/Alt+3— move focus directly to the canvas, the inspector bar, or the canvas menu.Escape— dismiss the tooltip that is currently shown.
-
Engine: Added asset source faceting.
findAssetsaccepts afacetsrequest (property pathsgroups,tags, ormeta.<key>) and returns value distributions with counts over the matched set. Local asset sources compute these automatically; custom sources can return them from theirfindAssetscallback. -
Engine/Android: Added the structured
filterandfacetsparameters to asset queries and facet distributions on query results. -
Engine/Swift: Added the structured
filterandfacetsparameters to asset queries and facet distributions on query results. -
Editor/Web: The typeface library’s language filter now derives its options from typeface
meta.languagesvia asset facets, instead ofgroups. -
Editor/Web: Added the UI for clip-to-clip transitions. Add one between two adjacent clips on the timeline, choose a type from the library (cross fade, cross blur, wipe, push, slide, and more), tune its settings with a live canvas preview, and apply or remove transitions across a whole track at once.
-
Engine: Added clip-to-clip transitions — a new API (
createTransition,setTransition,removeTransition,getTransition,supportsTransition), exposed in the Web, Android, iOS, and Node.js bindings, with a catalog of transition types (none,cross-fade,cross-blur,cross-spin,cross-zoom,cross-warp,push,slide,stack,splice,diagonal-splice,fade,fade-to-white,fade-to-black,wipe,line-wipe,clock-wipe,color-wipe,gradient-fade,chop,two-stripes). Transitions overlap adjacent clips with a clamped duration, cross-fade audio automatically, and expose editable properties (duration, direction, color, slices, and amorphflag) via generic block setters; when morph is enabled, position, rotation, scale, and shape are interpolated between the outgoing and incoming clip. -
Editor/Web: Added keyboard shortcuts that mirror pointer/drag gestures on the canvas and the video timeline, so both can be driven from the keyboard for accessibility.
- Canvas transforms (selected block): nudge the crop area with the arrow keys, rotate with
Alt+arrows, and resize withMod+arrows (orMod+Alt+arrows to resize from the opposite edge). HoldShiftfor a larger step. - Video timeline (selected clip): move a clip earlier/later with the arrow keys, insert it into a gap while pushing later clips with
Mod+arrows, move it to the track above/below or to a new track withMod(+Shift)+ArrowUp/ArrowDown, and trim its in/out points withAlt(+Shift)+arrows. HoldShiftfor a larger step. - Playhead: skim frame-by-frame with
,/., jump further withShift+,/Shift+., and jump to the start/end withHome/End.
See the Keyboard shortcuts guide for the full list.
- Canvas transforms (selected block): nudge the crop area with the arrow keys, rotate with
-
Engine: Added the
text/useContextualAlternatesandcaption/useContextualAlternatesboolean properties to enable or disable the OpenType contextual alternates (calt) feature during text shaping. Contextual alternates remain enabled by default. Disabling them keeps a font’s context-dependent glyph substitutions (such as the connectedtswashes in Caveat) from being applied, so identical characters render with identical glyphs. -
Editor/Android: The asset library now refreshes automatically when a source’s contents change via
engine.asset.assetSourceContentsChanged(sourceId=_). Any open library showing that source re-queries and updates in place. -
Editor/Web: Fixed the Bold/Italic and Underline/Strikethrough toggles being unresponsive on caption blocks in the video editor. These controls now apply to the selected caption, matching their behavior for text blocks. The inspector bar’s font weight/style dropdown is now also available for captions.
-
Editor/Flutter: Fixed an issue where effects applied to paused videos were not immediately visible when using TextureView.
-
Editor/iOS: The “Could not create View for …” error messages shown when the Dock, Canvas Menu, Inspector Bar, Navigation Bar, or an editor component fails to build are now localizable (and ship with German translations), matching the rest of the editor UI. Previously they were hardcoded in English.
-
Editor/iOS: Fixed the sheet dismiss button rendering a doubled circle under iOS 26 Liquid Glass.
-
Engine/Node:
@cesdk/nodeno longer probes the browserlocalStorageglobal during initialization on Node.js. On Node 22.4+ the experimental Web Storage global is a getter thattypeofevaluates, which printed anExperimentalWarning(Node 22.x) or threwERR_INVALID_ARG_VALUE(Node 23+/24) when--localstorage-filewas not provided. Headless Node has no browser Web Storage, so the engine now short-circuits this feature detection there. Browser detection is unchanged. -
Editor/Web: Fixed the “Resize Page” panel rendering completely empty when no page preset sources are configured. The page size inputs are now always shown and only the preset library section is omitted.
-
Engine: Rendering a block with a broken fill, effect, or frame reference (e.g. from a corrupt scene file) now flags the block with an error state instead of crashing the render loop.
-
Engine: Loading blocks or templates whose serialization contains references to missing elements now removes those references and flags the affected blocks with an error state, instead of leaving the references pointing at unrelated blocks, which could corrupt rendering.
-
Engine: Added the block error code
BROKEN_BLOCK_REFERENCE, reported when a broken block reference is removed on load or encountered during rendering. -
Editor: Fixed snapping guides appearing for hidden blocks and pages.
-
Engine: Fixed a crash when rendering text whose font resource had been evicted under memory pressure, e.g. while generating page thumbnails for the page overview. Text now falls back to the default font while the evicted font reloads and switches back automatically once it is ready.
-
Editor/Web: Fixed timeline duration formatting to zero-pad single-digit minutes when hours are present (e.g.
2:01:51.7instead of2:1:51.7). -
Editor/Web: Fixed the typeface library panel collapsing an expanded typeface’s variants when a search was typed just before expanding it. Search mode now activates as you type instead of after the debounced query settles, so the list is no longer torn down under an in-progress interaction.
-
Engine: Loading a video whose codec is not supported (e.g. AV1 video or Opus audio in an MP4) now fails with a clear, actionable error naming the actual codec fourcc and the supported codecs to re-encode to, instead of a generic “OTI=0” message. The failure is surfaced as a distinct
VIDEO_CODEC_UNSUPPORTED/AUDIO_CODEC_UNSUPPORTEDerror code so it can be distinguished from a generic decode failure. -
Editor/Web: Fixed video clip thumbnails in the timeline sometimes not updating after replacing a video, and sometimes staying stuck on the loading indicator.
-
Engine: Per-character and per-word text animations that fade each glyph (Pan, Fade, Blur, Zoom, …) now play back smoothly on large text blocks, including curved text
-
Engine: Underlines and strikethroughs now animate together with the text during per-character and per-word in and out animations, instead of only appearing once the animation finishes
-
Editor/Web: Fixed published starter kit repositories shipping the editor configuration in a root-level folder outside
src/imgly. Thesrc/imglyfolder is now self-contained across all starter kits, so copying it into a project yields a complete, working integration as documented. -
Engine: Fixed a crash (
tried to use the Error of an object with a Result) when a video decoder reported an error, e.g. exporting a scene with an H.264 High 4:4:4 10-bit (yuv444p10le) video on the server-side renderer. Such exports now fail with a properVIDEO_DECODING_UNSUPPORTEDerror. -
Engine/Android: Fixed a crash when the text block being edited was destroyed, e.g. when exiting text editing with empty text.
-
Editor/iOS: Fixed sheet dismiss and close buttons sometimes requiring multiple taps to close on iOS 26.
-
Editor/Web: Fixed audio continuing to play when selecting another block while previewing a trim in the inspector bar.
-
Editor/Web: Fixed a crash (“Maximum update depth exceeded”) when selecting another block while the trim panel was open in the Advanced editor.
-
Editor/Android: Fixed timeline trimming setting clip durations slightly short of the dragged length, e.g. 4.9s instead of 5.0s.
-
Editor/Android: Fixed a crash (
UnsupportedOperationException) when a design block type that the editor UI does not support yet gets selected, for example a caption in a scene authored with the web editor. Such blocks stay selectable on the canvas, and the canvas menu and inspector bar now stay hidden for them instead of crashing the editor.