Common Tasks
Practical recipes for the most common integration work. All examples assume you already have a reference to the <rendley-video-editor> element and that you're running code inside an onReady listener (see Events & Methods).
const editor = document.getElementById("rendley");
editor.addEventListener("onReady", async () => {
const Engine = await editor.getEngine();
const SDK = await editor.getRendleySDK();
// ...your code here...
});Save a Project
Serialize the editor state to JSON and send it to your backend:
async function saveProject() {
if (!Engine.getInstance().isSafeToSerialize()) {
// Media still processing, either wait or skip this save.
return;
}
const state = Engine.getInstance().serialize();
await fetch("/api/projects/123", {
method: "PUT",
body: JSON.stringify(state),
});
}For a full autosave pattern (debounced, event-driven, with beforeunload beacon), see the Autosave pattern.
Load a Project
On a fresh page, wait for onReady and then deserialize into the Engine:
editor.addEventListener("onReady", async () => {
const Engine = await editor.getEngine();
const response = await fetch("/api/projects/123");
const state = await response.json();
await Engine.deserialize(state);
});The editor's UI re-renders automatically from SDK events, so the timeline, library tiles, and canvas preview all update without any extra calls.
Upload Media Programmatically
Drag-and-drop works out of the box, but you can also add files from code, for example, from a server-provided URL or a hidden file input:
const library = Engine.getInstance().getLibrary();
const mediaId = await library.addMedia("https://example.com/intro.mp4");The new media appears in the sidebar's Media tab immediately because the editor listens to the library:added SDK event.
Add a Clip to the Timeline
const timeline = Engine.getInstance().getTimeline();
const layer = timeline.createLayer();
const mediaId = await Engine.getInstance()
.getLibrary()
.addMedia("https://example.com/clip.mp4");
await layer.addClip({
mediaDataId: mediaId,
startTime: 0,
});Trigger an Export Programmatically
You don't have to wait for the user to click Export. Kick it off directly:
async function exportVideo() {
const result = await Engine.getInstance().export();
if (result?.blob) {
downloadBlob(result.blob, `video.${result.extension}`);
}
}The editor's built-in Export button uses the same method internally, so both paths fire the same onRenderSuccess / onRenderError events you've already attached to the element.
React to User Actions
Everything the user does in the editor flows through SDK events. Attach listeners to drive your own state:
const events = Engine.getInstance().events;
events.on("clip:added", ({ clipId }) => {
trackAnalytics("clip_added", { clipId });
});
events.on("library:added", ({ mediaDataId }) => {
// User uploaded a file
});
events.on("clip:style:updated", ({ clipId, property, value }) => {
// User moved, scaled, or restyled a clip
});See the full event catalog.
Change the Theme at Runtime
The theme attribute is mutable, set it from JavaScript to re-theme on the fly:
editor.setAttribute("theme", "light");
editor.setAttribute("highcontrast", "true");Valid values for theme: dark, light, system.
Add Custom Effects or Filters
The editor ships with a default effect and filter pack loaded from Rendley's CDN. To extend them, register extras through the Library after onReady:
await Engine.getInstance().getLibrary().addFilter({
id: "brand-lut",
name: "Brand LUT",
lutUrl: "https://cdn.yourdomain.com/luts/brand.png",
serializable: true,
});
await Engine.getInstance()
.getLibrary()
.addEffect({
id: "vignette",
name: "Vignette",
fragmentSrc: myVignetteShader,
properties: { uRadius: 0.5 },
serializable: true,
});Custom items appear alongside the built-ins in the user-facing UI.
Embed the Editor in a Modal
Web components keep their state across mounts, but the SDK destroys itself when the element leaves the DOM. To show the editor in a modal that repeatedly opens and closes, either:
- Keep the editor mounted and toggle CSS
display. - Recreate it each time, and re-apply any saved project through
Engine.deserialize.
Option 1 is faster. Option 2 gives you a clean slate every open.