<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Video Editor – IMG.LY Blog</title><description>Posts tagged Video Editor on the IMG.LY blog.</description><link>https://img.ly/blog/tag/video-editor/</link><language>en-us</language><image><url>https://img.ly/apple-touch-icon.png</url><title>Video Editor – IMG.LY Blog</title><link>https://img.ly/blog/tag/video-editor/</link></image><atom:link href="https://img.ly/blog/tag/video-editor/rss.xml" rel="self" type="application/rss+xml"/><generator>Astro</generator><lastBuildDate>Fri, 12 Jun 2026 10:11:02 GMT</lastBuildDate><ttl>60</ttl><item><title>Building a CapCut-Like Video Editor with CE.SDK and AI</title><link>https://img.ly/blog/capcut-like-video-editor-web-react/</link><guid isPermaLink="true">https://img.ly/blog/capcut-like-video-editor-web-react/</guid><description>How to built a browser-based video editor with a dark CapCut-inspired UI, multi-track timeline, and AI-powered content generation... in under 200 lines of code.</description><pubDate>Thu, 26 Feb 2026 22:50:34 GMT</pubDate><content:encoded>&lt;h3 id=&quot;build-this-with-ai-in-minutes&quot;&gt;&lt;strong&gt;Build this with AI in minutes&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This tutorial is a great way to understand how CE.SDK works under the hood. But if you just want to get to the result, you can build this entire editor using &lt;a href=&quot;https://img.ly/docs/cesdk/react/get-started/agent-skills-f7g8h9/&quot;&gt;IMG.LY Agent Skills&lt;/a&gt;, no manual setup required.&lt;/p&gt;
&lt;p&gt;Install the skills, then run:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/cesdk:build Build a CapCut-like video editor with a dark theme, multi-track timeline, AI video/image/audio generation, background removal, and MP4 export.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Want to understand a specific concept in depth? Use &lt;code&gt;/cesdk:explain&lt;/code&gt; — for example:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/cesdk:explain How does the video timeline and block hierarchy work?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;CapCut has set the standard for accessible video editing. Its dark UI, intuitive timeline, and AI-powered features make it feel like a professional tool that anyone can use. But what if you could build something similar embedded directly in your own web application in minutes? Yes, minutes!&lt;/p&gt;
&lt;p&gt;In this tutorial, we’ll walk through how we built a CapCut-like video editor using &lt;a href=&quot;https://img.ly&quot;&gt;IMG.LY’s CreativeEditor SDK (CE.SDK)&lt;/a&gt; for React. The finished editor includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;multi-track timeline&lt;/strong&gt; for video, audio, text, and captions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trim, split, and join&lt;/strong&gt; operations on video clips&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;CapCut-inspired dark theme&lt;/strong&gt; built with CSS custom properties&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI video generation&lt;/strong&gt; (text-to-video, image-to-video) via Minimax, Kling, and Pixverse&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI image generation&lt;/strong&gt; (text-to-image, image editing) via RecraftV3, IdeogramV3, and GPT Image&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI audio generation&lt;/strong&gt; (text-to-speech, sound effects) via ElevenLabs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI text generation&lt;/strong&gt; (copywriting, translation) via Anthropic Claude&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Background removal&lt;/strong&gt; — client-side, powered by WebAssembly/WebGPU&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MP4 export&lt;/strong&gt; directly from the browser&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The entire editor is a single React component with roughly 180 lines of JavaScript and 100 lines of CSS.&lt;/p&gt;
&lt;h2 id=&quot;architecture-overview&quot;&gt;Architecture Overview&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;App architecture&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2000px) 2000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2000&quot; height=&quot;1969&quot; src=&quot;https://img.ly/_astro/Gemini_Generated_Image_6celpb6celpb6cel_1EicqM.webp&quot; srcset=&quot;/_astro/Gemini_Generated_Image_6celpb6celpb6cel_15nkQs.webp 640w, /_astro/Gemini_Generated_Image_6celpb6celpb6cel_Z1oAwlQ.webp 750w, /_astro/Gemini_Generated_Image_6celpb6celpb6cel_ZxUCR2.webp 828w, /_astro/Gemini_Generated_Image_6celpb6celpb6cel_Z1W608K.webp 1080w, /_astro/Gemini_Generated_Image_6celpb6celpb6cel_s3NdH.webp 1280w, /_astro/Gemini_Generated_Image_6celpb6celpb6cel_2u4DRy.webp 1668w, /_astro/Gemini_Generated_Image_6celpb6celpb6cel_1EicqM.webp 2000w&quot;&gt;&lt;/p&gt;
&lt;p&gt;CE.SDK has two main layers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CreativeEngine:&lt;/strong&gt; The headless core that manages scenes, blocks, assets, and rendering. It handles the video timeline, playback, and export entirely client-side.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CreativeEditor UI:&lt;/strong&gt; A pre-built, customizable UI layer that wraps the engine with a dock, inspector, timeline, canvas, and navigation bar.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Plugins extend both layers. The &lt;code&gt;AiApps&lt;/code&gt; plugin, for example, registers AI providers with the engine and injects UI components (dock buttons, canvas menu items, generation panels) into the editor.&lt;/p&gt;
&lt;h2 id=&quot;step-1-project-setup&quot;&gt;Step 1: Project Setup&lt;/h2&gt;
&lt;p&gt;We scaffolded a React project with Vite and installed CE.SDK alongside the AI plugin packages:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; vite@latest&lt;/span&gt;&lt;span&gt; capcut-like-editor&lt;/span&gt;&lt;span&gt; --&lt;/span&gt;&lt;span&gt; --template&lt;/span&gt;&lt;span&gt; react&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; capcut-like-editor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Core SDK&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @cesdk/cesdk-js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# AI plugins&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @imgly/plugin-ai-apps-web&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @imgly/plugin-ai-video-generation-web&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @imgly/plugin-ai-image-generation-web&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @imgly/plugin-ai-audio-generation-web&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @imgly/plugin-ai-text-generation-web&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Background removal (runs locally via WASM/WebGPU)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @imgly/plugin-background-removal-web&lt;/span&gt;&lt;span&gt; onnxruntime-web@1.21.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;why-so-many-packages&quot;&gt;Why so many packages?&lt;/h3&gt;
&lt;p&gt;CE.SDK follows a modular plugin architecture. Each AI capability is a separate package with its own provider modules. This means you only bundle what you use if you don’t need audio generation, don’t install &lt;code&gt;@imgly/plugin-ai-audio-generation-web&lt;/code&gt;. The &lt;code&gt;@imgly/plugin-ai-apps-web&lt;/code&gt; package is the unifying layer that brings them all together into a single dock panel.&lt;/p&gt;
&lt;h2 id=&quot;step-2-the-react-component&quot;&gt;Step 2: The React Component&lt;/h2&gt;
&lt;p&gt;CE.SDK provides a first-class React wrapper via &lt;code&gt;@cesdk/cesdk-js/react&lt;/code&gt;. The &lt;code&gt;&amp;#x3C;CreativeEditor&gt;&lt;/code&gt; component handles mounting, initialization, and cleanup:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditor &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@cesdk/cesdk-js/react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // license: &apos;YOUR_CESDK_LICENSE_KEY&apos;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;cesdk&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // All setup happens here — theme, assets, plugins, UI customization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; VideoEditor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;&lt;/span&gt;&lt;span&gt;CreativeEditor&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{config} &lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{init} &lt;/span&gt;&lt;span&gt;width&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;100vw&quot;&lt;/span&gt;&lt;span&gt; height&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;100vh&quot;&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;config&lt;/code&gt; object is passed to the engine at creation time. The &lt;code&gt;init&lt;/code&gt; callback fires once the &lt;code&gt;cesdk&lt;/code&gt; instance is ready — this is where all our customization lives.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pitfall: Silent init errors.&lt;/strong&gt; The &lt;code&gt;&amp;#x3C;CreativeEditor&gt;&lt;/code&gt; component swallows errors thrown inside &lt;code&gt;init&lt;/code&gt;. If something fails, the editor loads but appears broken with no console output. Always wrap &lt;code&gt;init&lt;/code&gt; in a &lt;code&gt;try/catch&lt;/code&gt;:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;step-3-creating-the-video-scene&quot;&gt;Step 3: Creating the Video Scene&lt;/h2&gt;
&lt;p&gt;A video editor needs three things at startup: asset sources, a video scene, and a timeline.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Load built-in asset libraries (stickers, shapes, filters, typefaces, etc.)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; cesdk.&lt;/span&gt;&lt;span&gt;addDefaultAssetSources&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Load demo content (sample videos, images, audio) + enable upload slots&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; cesdk.&lt;/span&gt;&lt;span&gt;addDemoAssetSources&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  sceneMode: &lt;/span&gt;&lt;span&gt;&apos;Video&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  withUploadAssetSources: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Create a video scene with timeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; cesdk.&lt;/span&gt;&lt;span&gt;createVideoScene&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;createVideoScene()&lt;/code&gt; sets up the scene hierarchy that powers the timeline:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Scene&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; └── Page (represents the video canvas — 1920x1080 by default)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ├── Track (video track — holds video clips in sequence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ├── Track (overlay track — text, stickers, images)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ├── CaptionTrack (subtitles synced to playback)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      └── Audio (background music, voiceover, sound effects)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each element on the timeline is a &lt;strong&gt;block&lt;/strong&gt; with timing properties: &lt;code&gt;timeOffset&lt;/code&gt; (when it appears) and &lt;code&gt;duration&lt;/code&gt; (how long it plays). The engine handles rendering each frame, compositing layers, and synchronizing audio.&lt;/p&gt;
&lt;h3 id=&quot;browser-support&quot;&gt;Browser support&lt;/h3&gt;
&lt;p&gt;Video editing relies on modern web codecs (WebCodecs API), which are available in Chromium-based browsers (Chrome, Edge, Brave). Safari and Firefox support is limited.&lt;/p&gt;
&lt;h2 id=&quot;step-4-the-capcut-dark-theme&quot;&gt;Step 4: The CapCut Dark Theme&lt;/h2&gt;
&lt;p&gt;CapCut’s visual identity is defined by its deep charcoal backgrounds, teal accent colors, and subtle elevation layers. CE.SDK’s theming system maps perfectly to this through CSS custom properties.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-base-theme&quot;&gt;Setting the base theme&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cesdk.ui.&lt;/span&gt;&lt;span&gt;setTheme&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;dark&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This activates CE.SDK’s built-in dark theme. But we want to go further — we need CapCut’s specific color palette.&lt;/p&gt;
&lt;h3 id=&quot;custom-css-overrides&quot;&gt;Custom CSS overrides&lt;/h3&gt;
&lt;p&gt;CE.SDK scopes all its UI under &lt;code&gt;.ubq-public&lt;/code&gt; with &lt;code&gt;data-ubq-theme&lt;/code&gt; and &lt;code&gt;data-ubq-scale&lt;/code&gt; attributes. We override the CSS custom properties to inject our palette:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;.ubq-public&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;data-ubq-theme&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;dark&apos;&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;data-ubq-scale&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;normal&apos;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;.ubq-public&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;data-ubq-theme&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;dark&apos;&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;data-ubq-scale&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;modern&apos;&lt;/span&gt;&lt;span&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  /* Deep charcoal backgrounds — darker than CE.SDK&apos;s default dark */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-canvas&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;220&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-elevation-1&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;220&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-elevation-2&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;220&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-elevation-3&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;220&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  /* High-contrast white text */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-foreground-default&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsla&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0.92&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-foreground-light&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsla&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0.55&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  /* CapCut&apos;s signature teal/cyan accent */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-interactive-accent-default&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;190&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;85&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;48&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-interactive-accent-hover&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;190&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;85&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-interactive-accent-pressed&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;190&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;85&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  /* Subtle borders — barely visible, like CapCut */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  --ubq-border-default&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;hsla&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0.08&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;!important&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key design decisions:&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;Why&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--ubq-canvas&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;hsl(220, 15%, 8%)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Near-black with a slight blue tint — matches CapCut’s canvas area&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--ubq-elevation-1/2/3&lt;/code&gt;&lt;/td&gt;&lt;td&gt;12% → 15% → 18% lightness&lt;/td&gt;&lt;td&gt;Subtle elevation steps create depth without harsh contrast&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--ubq-interactive-accent-*&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;hsl(190, 85%, 48%)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;CapCut’s teal — used for buttons, selections, and progress bars&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;--ubq-border-default&lt;/code&gt;&lt;/td&gt;&lt;td&gt;8% opacity white&lt;/td&gt;&lt;td&gt;Nearly invisible borders that only appear on close inspection&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;responsive-scale&quot;&gt;Responsive scale&lt;/h3&gt;
&lt;p&gt;We also configure responsive scaling so the editor adapts to touch devices:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cesdk.ui.&lt;/span&gt;&lt;span&gt;setScale&lt;/span&gt;&lt;span&gt;(({ &lt;/span&gt;&lt;span&gt;containerWidth&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;isTouch&lt;/span&gt;&lt;span&gt; }) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; ((containerWidth &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; containerWidth &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; 768&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; isTouch) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; &apos;large&apos;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;// Bigger touch targets on small/touch screens&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; &apos;normal&apos;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;// Standard desktop sizing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;step-5-ai-plugin-integration&quot;&gt;Step 5: AI Plugin Integration&lt;/h2&gt;
&lt;p&gt;This is where the editor transforms from a basic video tool into something that feels like CapCut’s AI-powered experience. CE.SDK’s plugin system lets us add all AI capabilities through a single unified &lt;code&gt;AiApps&lt;/code&gt; plugin.&lt;/p&gt;
&lt;h3 id=&quot;the-unified-aiapps-approach&quot;&gt;The unified AiApps approach&lt;/h3&gt;
&lt;p&gt;Instead of registering each AI plugin separately, &lt;code&gt;@imgly/plugin-ai-apps-web&lt;/code&gt; provides a single entry point:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; AiApps &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/plugin-ai-apps-web&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; FalAiVideo &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/plugin-ai-video-generation-web/fal-ai&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; FalAiImage &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/plugin-ai-image-generation-web/fal-ai&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; OpenAiImage &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/plugin-ai-image-generation-web/open-ai&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Elevenlabs &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/plugin-ai-audio-generation-web/elevenlabs&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Anthropic &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/plugin-ai-text-generation-web/anthropic&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; cesdk.&lt;/span&gt;&lt;span&gt;addPlugin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  AiApps&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    dryRun: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;// Simulate for development — no API calls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    providers: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      text2text: Anthropic.&lt;/span&gt;&lt;span&gt;AnthropicProvider&lt;/span&gt;&lt;span&gt;({ proxyUrl: &lt;/span&gt;&lt;span&gt;PROXY_URL&lt;/span&gt;&lt;span&gt; }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      text2image: [FalAiImage.&lt;/span&gt;&lt;span&gt;RecraftV3&lt;/span&gt;&lt;span&gt;({ proxyUrl }) &lt;/span&gt;&lt;span&gt;/* ... */&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      image2image: [FalAiImage.&lt;/span&gt;&lt;span&gt;GeminiFlashEdit&lt;/span&gt;&lt;span&gt;({ proxyUrl }) &lt;/span&gt;&lt;span&gt;/* ... */&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      text2video: [FalAiVideo.&lt;/span&gt;&lt;span&gt;MinimaxVideo01Live&lt;/span&gt;&lt;span&gt;({ proxyUrl }) &lt;/span&gt;&lt;span&gt;/* ... */&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      image2video: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        FalAiVideo.&lt;/span&gt;&lt;span&gt;MinimaxVideo01LiveImageToVideo&lt;/span&gt;&lt;span&gt;({ proxyUrl }) &lt;/span&gt;&lt;span&gt;/* ... */&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      text2speech: Elevenlabs.&lt;/span&gt;&lt;span&gt;ElevenMultilingualV2&lt;/span&gt;&lt;span&gt;({ proxyUrl }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      text2sound: Elevenlabs.&lt;/span&gt;&lt;span&gt;ElevenSoundEffects&lt;/span&gt;&lt;span&gt;({ proxyUrl }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;provider-categories-explained&quot;&gt;Provider categories explained&lt;/h3&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Category&lt;/th&gt;&lt;th&gt;What it does&lt;/th&gt;&lt;th&gt;Models we configured&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;text2text&lt;/code&gt;&lt;/td&gt;&lt;td&gt;AI copywriting — improve text, translate, change tone&lt;/td&gt;&lt;td&gt;Anthropic Claude&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;text2image&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Generate images from text prompts&lt;/td&gt;&lt;td&gt;RecraftV3, IdeogramV3, GPT Image&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;image2image&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Transform existing images with AI&lt;/td&gt;&lt;td&gt;Gemini Flash Edit, GPT Image&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;text2video&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Generate video clips from text descriptions&lt;/td&gt;&lt;td&gt;Minimax Video, Kling Video, Pixverse&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;image2video&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Animate a static image into video&lt;/td&gt;&lt;td&gt;Minimax Video, Kling Video&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;text2speech&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Convert text to spoken audio with voice selection&lt;/td&gt;&lt;td&gt;ElevenLabs Multilingual V2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;text2sound&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Generate sound effects from text&lt;/td&gt;&lt;td&gt;ElevenLabs Sound Effects&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;When multiple providers are configured in an array (like &lt;code&gt;text2image&lt;/code&gt;), the UI automatically shows a provider/model selection dropdown so users can choose which AI model to use.&lt;/p&gt;
&lt;h3 id=&quot;the-proxy-server-requirement&quot;&gt;The proxy server requirement&lt;/h3&gt;
&lt;p&gt;Every provider takes a &lt;code&gt;proxyUrl&lt;/code&gt; parameter. This is critical for production:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Browser  →  Your Proxy Server  →  AI Provider (fal.ai, ElevenLabs, etc.)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                ↑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          Injects API keys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          server-side&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your API keys should never be in client-side code. The proxy server receives requests from CE.SDK, attaches your API key, and forwards to the AI provider. During development, &lt;code&gt;dryRun: true&lt;/code&gt; simulates generation without any API calls.&lt;/p&gt;
&lt;h3 id=&quot;background-removal&quot;&gt;Background removal&lt;/h3&gt;
&lt;p&gt;Background removal is a separate plugin because it runs entirely client-side — no proxy needed:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; BackgroundRemovalPlugin &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/plugin-background-removal-web&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; cesdk.&lt;/span&gt;&lt;span&gt;addPlugin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  BackgroundRemovalPlugin&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ui: { locations: [&lt;/span&gt;&lt;span&gt;&apos;canvasMenu&apos;&lt;/span&gt;&lt;span&gt;] },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This uses ONNX Runtime (WebAssembly + WebGPU) to run an AI segmentation model directly in the browser. The first run downloads ~40MB of model weights, which are then cached. Select any image on the canvas and click “Remove Background” in the context menu.&lt;/p&gt;
&lt;h2 id=&quot;step-6-ui-customization-with-the-component-order-api&quot;&gt;Step 6: UI Customization with the Component Order API&lt;/h2&gt;
&lt;p&gt;CE.SDK’s UI is built from five customizable areas: &lt;strong&gt;Dock&lt;/strong&gt;, &lt;strong&gt;Inspector Bar&lt;/strong&gt;, &lt;strong&gt;Canvas Menu&lt;/strong&gt;, &lt;strong&gt;Navigation Bar&lt;/strong&gt;, and &lt;strong&gt;Canvas Bar&lt;/strong&gt;. The Component Order API lets us insert, remove, and reorder components in each area.&lt;/p&gt;
&lt;h3 id=&quot;adding-the-ai-button-to-the-dock&quot;&gt;Adding the AI button to the dock&lt;/h3&gt;
&lt;p&gt;We want the AI Apps button to be the first thing users see in the dock:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cesdk.ui.&lt;/span&gt;&lt;span&gt;insertOrderComponent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  { in: &lt;/span&gt;&lt;span&gt;&apos;ly.img.dock&apos;&lt;/span&gt;&lt;span&gt;, position: &lt;/span&gt;&lt;span&gt;&apos;start&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &apos;ly.img.ai.apps.dock&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;insertOrderComponent&lt;/code&gt; takes a location specifier and the component(s) to insert. &lt;code&gt;position: &apos;start&apos;&lt;/code&gt; puts it at the top of the dock. Alternative positions include &lt;code&gt;&apos;end&apos;&lt;/code&gt;, a numeric index, or relative placement with &lt;code&gt;before&lt;/code&gt;/&lt;code&gt;after&lt;/code&gt; matchers.&lt;/p&gt;
&lt;h3 id=&quot;ai-options-in-the-canvas-context-menu&quot;&gt;AI options in the canvas context menu&lt;/h3&gt;
&lt;p&gt;When a user selects a text or image block and right-clicks, we want AI options available:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cesdk.ui.&lt;/span&gt;&lt;span&gt;insertOrderComponent&lt;/span&gt;&lt;span&gt;({ in: &lt;/span&gt;&lt;span&gt;&apos;ly.img.canvas.menu&apos;&lt;/span&gt;&lt;span&gt;, position: &lt;/span&gt;&lt;span&gt;&apos;start&apos;&lt;/span&gt;&lt;span&gt; }, [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &apos;ly.img.ai.text.canvasMenu&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &apos;ly.img.ai.image.canvasMenu&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Passing an array inserts multiple components at once.&lt;/p&gt;
&lt;h3 id=&quot;custom-export-button-in-the-navigation-bar&quot;&gt;Custom export button in the navigation bar&lt;/h3&gt;
&lt;p&gt;We add an Export button with a real click handler that triggers MP4 export:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cesdk.ui.&lt;/span&gt;&lt;span&gt;insertOrderComponent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  { in: &lt;/span&gt;&lt;span&gt;&apos;ly.img.navigation.bar&apos;&lt;/span&gt;&lt;span&gt;, position: &lt;/span&gt;&lt;span&gt;&apos;end&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span&gt;&apos;ly.img.action.navigationBar&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    key: &lt;/span&gt;&lt;span&gt;&apos;export&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    label: &lt;/span&gt;&lt;span&gt;&apos;Export&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    icon: &lt;/span&gt;&lt;span&gt;&apos;@imgly/Download&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    onClick&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; engine&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; cesdk.engine;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; page&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;findByType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;page&apos;&lt;/span&gt;&lt;span&gt;)[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (page) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const&lt;/span&gt;&lt;span&gt; blob&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;exportVideo&lt;/span&gt;&lt;span&gt;(page, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          mimeType: &lt;/span&gt;&lt;span&gt;&apos;video/mp4&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const&lt;/span&gt;&lt;span&gt; url&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; URL&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createObjectURL&lt;/span&gt;&lt;span&gt;(blob);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; document.&lt;/span&gt;&lt;span&gt;createElement&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;a&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        a.href &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; url;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        a.download &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;video.mp4&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        a.&lt;/span&gt;&lt;span&gt;click&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        URL&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;revokeObjectURL&lt;/span&gt;&lt;span&gt;(url);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;exportVideo&lt;/code&gt; method renders every frame of the timeline — compositing video tracks, overlays, text, captions, and audio — into an MP4 blob entirely in the browser.&lt;/p&gt;
&lt;h2 id=&quot;step-7-wiring-generated-audio-into-the-asset-library&quot;&gt;Step 7: Wiring Generated Audio into the Asset Library&lt;/h2&gt;
&lt;p&gt;AI-generated audio (speech and sound effects) is stored in provider-specific history sources. To make this audio browsable alongside regular audio assets, we inject the history source into the audio asset library entry:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; audioEntry&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; cesdk.ui.&lt;/span&gt;&lt;span&gt;getAssetLibraryEntry&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;ly.img.audio&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (audioEntry &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; existingSourceIds&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Array.&lt;/span&gt;&lt;span&gt;isArray&lt;/span&gt;&lt;span&gt;(audioEntry.sourceIds)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ?&lt;/span&gt;&lt;span&gt; audioEntry.sourceIds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    :&lt;/span&gt;&lt;span&gt; audioEntry.&lt;/span&gt;&lt;span&gt;sourceIds&lt;/span&gt;&lt;span&gt;({});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  cesdk.ui.&lt;/span&gt;&lt;span&gt;updateAssetLibraryEntry&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;ly.img.audio&apos;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    sourceIds: [&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;existingSourceIds, &lt;/span&gt;&lt;span&gt;&apos;ly.img.ai.audio-generation.history&apos;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when users open the Audio panel in the dock, they’ll see their AI-generated audio alongside the sample library.&lt;/p&gt;
&lt;h2 id=&quot;step-8-custom-labels-with-i18n&quot;&gt;Step 8: Custom Labels with i18n&lt;/h2&gt;
&lt;p&gt;CE.SDK’s i18n system lets us customize any UI string. We used it to make the AI prompt fields more inviting:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cesdk.i18n.&lt;/span&gt;&lt;span&gt;setTranslations&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  en: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &apos;ly.img.plugin-ai-video-generation-web.fal-ai/minimax/video-01-live.property.prompt&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &apos;Describe your video...&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &apos;ly.img.plugin-ai-image-generation-web.fal-ai/recraft-v3.property.prompt&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &apos;Describe your image...&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Translation keys follow the pattern &lt;code&gt;{plugin-id}.{provider-id}.property.{field}&lt;/code&gt;. You can also add multi-language support by including keys for &lt;code&gt;de&lt;/code&gt;, &lt;code&gt;fr&lt;/code&gt;, &lt;code&gt;es&lt;/code&gt;, etc.&lt;/p&gt;
&lt;h2 id=&quot;the-complete-file-structure&quot;&gt;The Complete File Structure&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;capcut-like-editor/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── src/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── App.jsx              # Root — imports VideoEditor + theme CSS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── VideoEditor.jsx      # The entire editor (single component, ~180 lines)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── capcut-theme.css     # CapCut dark theme overrides (~100 lines)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── index.css            # Global reset (margin/padding/overflow)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── main.jsx             # React entry point&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── index.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── package.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── vite.config.js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it. The entire CapCut-like editor is three files: one React component, one CSS file, and a thin App wrapper.&lt;/p&gt;
&lt;h2 id=&quot;what-we-get-out-of-the-box&quot;&gt;What We Get Out of the Box&lt;/h2&gt;
&lt;p&gt;Because CE.SDK’s video UI is pre-built, we didn’t write any code for these features — they come from &lt;code&gt;createVideoScene()&lt;/code&gt; and the default UI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-track timeline&lt;/strong&gt; with drag-to-reorder, drag-to-resize&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trim and split&lt;/strong&gt; — drag clip edges or use the split tool&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Join and arrange&lt;/strong&gt; — drag clips between tracks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transform&lt;/strong&gt; — crop, flip, rotate via the inspector&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Playback controls&lt;/strong&gt; — play, pause, seek, scrub&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Text overlays&lt;/strong&gt; — add styled text with the text tool&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stickers and graphics&lt;/strong&gt; — from the asset library&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filters and effects&lt;/strong&gt; — LUT-based color grading&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Undo/redo&lt;/strong&gt; — full history stack&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zoom and pan&lt;/strong&gt; — standard canvas navigation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The AI plugins add their own UI components (dock buttons, generation panels, context menu items) through the plugin system. We just positioned them where we wanted.&lt;/p&gt;
&lt;h2 id=&quot;going-to-production&quot;&gt;Going to Production&lt;/h2&gt;
&lt;p&gt;To take this from a prototype to production, you need three things:&lt;/p&gt;
&lt;h3 id=&quot;1-license-key&quot;&gt;1. License key&lt;/h3&gt;
&lt;p&gt;Get a free trial key at &lt;a href=&quot;https://img.ly/forms/contact-sales&quot;&gt;https://img.ly/forms/contact-sales&lt;/a&gt; and set it in the config (yes, if you want to ship to production you’ll have to talk to our lovely colleagues in sales):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  license: &lt;/span&gt;&lt;span&gt;&apos;YOUR_CESDK_LICENSE_KEY&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-proxy-server&quot;&gt;2. Proxy server&lt;/h3&gt;
&lt;p&gt;Set up a server that forwards AI requests with your API keys:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; PROXY_URL&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;https://your-server.com/api/ai-proxy&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See the &lt;a href=&quot;https://img.ly/docs/cesdk/react/user-interface/ai-integration/proxy-server-61f901/&quot;&gt;CE.SDK Proxy Server guide&lt;/a&gt; for Express.js and other server examples.&lt;/p&gt;
&lt;h3 id=&quot;3-disable-dry-run&quot;&gt;3. Disable dry run&lt;/h3&gt;
&lt;p&gt;Remove &lt;code&gt;dryRun: true&lt;/code&gt; from the AiApps configuration to enable real AI generation.&lt;/p&gt;
&lt;h2 id=&quot;key-takeaways&quot;&gt;Key Takeaways&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CE.SDK does the heavy lifting.&lt;/strong&gt; The timeline, playback, rendering, and export are all handled by the engine. We wrote zero video processing code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The plugin system is powerful.&lt;/strong&gt; Six AI capabilities were added with a single &lt;code&gt;addPlugin(AiApps({ ... }))&lt;/code&gt; call. Background removal was one more call.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CSS custom properties make theming painless.&lt;/strong&gt; We matched CapCut’s aesthetic by overriding ~25 CSS variables. No forking, no patching.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Component Order API is the customization backbone.&lt;/strong&gt; &lt;code&gt;insertOrderComponent&lt;/code&gt; with position-based placement is the cleanest pattern for adding UI elements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wrap &lt;code&gt;init&lt;/code&gt; in try/catch.&lt;/strong&gt; CE.SDK’s &lt;code&gt;&amp;#x3C;CreativeEditor&gt;&lt;/code&gt; swallows errors silently. This is the single most important debugging tip.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin your package versions.&lt;/strong&gt; All &lt;code&gt;@imgly/*&lt;/code&gt; plugins must match the &lt;code&gt;@cesdk/cesdk-js&lt;/code&gt; version exactly. A version mismatch (like 1.68 vs 1.69) will cause peer dependency conflicts.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/react/prebuilt-solutions/video-editor-9e533a/&quot;&gt;CE.SDK Video Editor Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/react/user-interface/ai-integration/integrate-8e906c/&quot;&gt;AI Integration Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/react/user-interface/appearance/theming-4b0938/&quot;&gt;Theming Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/react/user-interface/customization/quick-start/reorder-components-f6g7h8/&quot;&gt;Rearrange Buttons (Component Order API)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;Video Editor Web Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/imgly/cesdk-web-examples&quot;&gt;GitHub Examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><dc:creator>Jan</dc:creator><media:content url="https://blog.img.ly/2026/02/blogcover.png" medium="image"/><category>React</category><category>Video Editor</category><category>CE.SDK</category></item><item><title>Best Video SDKs for Mobile Applications: A Comprehensive Comparison for Developers</title><link>https://img.ly/blog/best-video-sdks-for-mobile-applications-a-comprehensive-comparison-for-developers/</link><guid isPermaLink="true">https://img.ly/blog/best-video-sdks-for-mobile-applications-a-comprehensive-comparison-for-developers/</guid><description>Choosing the right video SDK for your mobile app is crucial. In this guide, we compare the top options in 2025: IMG.LY, Banuba, Meishe, BytePlus, FFmpeg, and GStreamer, to highlight their strengths, limitations, and ideal use cases so you can confidently pick the best fit for your product.</description><pubDate>Tue, 02 Dec 2025 14:54:37 GMT</pubDate><content:encoded>&lt;p&gt;If you’re building a mobile app that needs video editing capabilities, you’re facing a tough decision: should you integrate a commercial SDK, work with open-source tools, or try to build something yourself?&lt;/p&gt;
&lt;p&gt;Video editing on mobile isn’t just hard, it’s complex in ways that surprise even experienced developers. You’re dealing with device fragmentation, battery constraints, memory management, and user expectations shaped by apps like TikTok and CapCut. And unlike web apps, mobile video editing requires native performance optimization to feel responsive.&lt;/p&gt;
&lt;p&gt;In this article, we’ll compare the most popular &lt;strong&gt;video SDK options for mobile applications&lt;/strong&gt;: &lt;strong&gt;IMG.LY, Banuba, Meishe, BytePlus, FFmpeg, and GStreamer&lt;/strong&gt; and show you how they stack up across features, platforms, integration complexity, and pricing. We’ll be honest about where each solution shines and where you’ll hit roadblocks.&lt;/p&gt;
&lt;p&gt;We’ll also dig into what it actually takes to build with each option: difficulty of integration, performance considerations, and what happens when you need to scale beyond a prototype.&lt;/p&gt;
&lt;h2 id=&quot;the-challenge-building-video-editing-into-mobile-apps&quot;&gt;The Challenge: Building Video Editing Into Mobile Apps&lt;/h2&gt;
&lt;p&gt;Before diving into specific SDKs, let’s talk about why video editing on mobile is uniquely challenging.&lt;/p&gt;
&lt;h3 id=&quot;processing-power-vs-battery-life&quot;&gt;Processing Power vs Battery Life&lt;/h3&gt;
&lt;p&gt;Video processing is resource-intensive. Every frame you manipulate — trimming, filtering, compositing, exporting — requires significant CPU and GPU work. On mobile devices, this creates a constant tension between delivering fast performance and not draining your user’s battery in minutes.&lt;br&gt;
Approximately 60% of battery usage in media apps comes from data transmission and processing. If you’re not careful with how you handle encoding, memory management, and background processes, your app will get uninstalled fast.&lt;/p&gt;
&lt;h3 id=&quot;device-fragmentation&quot;&gt;Device Fragmentation&lt;/h3&gt;
&lt;p&gt;Unlike web apps where you can control the environment, mobile apps run on thousands of device configurations. An iPhone 15 Pro handles 4K video editing effortlessly; a three-year-old Android phone might struggle with 1080p. You need to account for different chipsets, GPU capabilities, screen sizes, and OS versions — all while maintaining consistent UX.&lt;/p&gt;
&lt;h3 id=&quot;user-expectations-are-higher-than-ever&quot;&gt;User Expectations Are Higher Than Ever&lt;/h3&gt;
&lt;p&gt;Users expect mobile video editors to feel as responsive as native camera apps. They want real-time preview, smooth timeline scrubbing, instant filter application, and fast exports. Anything that feels sluggish or unpolished gets compared unfavorably to TikTok, Instagram, or CapCut — apps with massive engineering teams and years of optimization work.&lt;/p&gt;
&lt;p&gt;Building this level of polish from scratch is a multi-month (or multi-year) undertaking. That’s why most teams reach for an SDK.&lt;/p&gt;
&lt;h2 id=&quot;understanding-video-sdk-options&quot;&gt;Understanding Video SDK Options&lt;/h2&gt;
&lt;p&gt;The video SDK landscape breaks down into three broad categories:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Commercial SDKs&lt;/strong&gt; (IMG.LY Banuba, Meishe, BytePlus) provide pre-built editors with UI components, effects libraries, and dedicated support. They’re designed to integrate quickly but come with licensing costs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open-source frameworks&lt;/strong&gt; (FFmpeg, GStreamer) give you powerful processing engines but no UI, no templates, and no hand-holding. You’ll need to build everything user-facing yourself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hybrid approaches&lt;/strong&gt; combine open-source processing with custom UI development, giving you flexibility at the cost of significant engineering time.&lt;/p&gt;
&lt;p&gt;When evaluating options, consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Do you need a user-facing editor or just backend processing?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How important is cross-platform consistency?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What’s your timeline and team size?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What happens when you need to scale or add new features?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let’s break down each solution.&lt;/p&gt;
&lt;h2 id=&quot;1-imgly-cesdk-the-complete-solution&quot;&gt;1. IMG.LY CE.SDK (The Complete Solution)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;IMG.LY CreativeEditor SDK&lt;/strong&gt; is an enterprise-grade video editing solution built for teams that need production-ready editing features, cross-platform consistency, and automation — without spending months building and maintaining a custom solution.&lt;/p&gt;
&lt;p&gt;Unlike processing libraries (FFmpeg, GStreamer) or social-first SDKs (Banuba, BytePlus), IMG.LY provides both interactive editing and server-side automation in one platform. You can embed the SDK for user-facing editing and use the same engine for headless creative automation on your backend.&lt;/p&gt;
&lt;h3 id=&quot;core-capabilities&quot;&gt;Core Capabilities&lt;/h3&gt;
&lt;p&gt;IMG.LY delivers a complete video editing platform with timeline-based editing, design tools, and AI features:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Timeline-Based Editing:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Arrange videos on multi-track timelines&lt;/li&gt;
&lt;li&gt;Trim, crop, and adjust duration&lt;/li&gt;
&lt;li&gt;Merge videos and create collages&lt;/li&gt;
&lt;li&gt;Audio overlay and mixing&lt;/li&gt;
&lt;li&gt;Layer management and compositing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Creative Tools:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;60+ filters and effects&lt;/li&gt;
&lt;li&gt;Adjustments (brightness, contrast, saturation, exposure)&lt;/li&gt;
&lt;li&gt;Text design with custom fonts and styles&lt;/li&gt;
&lt;li&gt;Dynamic stickers and overlays&lt;/li&gt;
&lt;li&gt;Frames with multiple blend modes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Template System:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Design templates with text variables and placeholders&lt;/li&gt;
&lt;li&gt;Lockable elements for brand consistency&lt;/li&gt;
&lt;li&gt;Automated variation generation&lt;/li&gt;
&lt;li&gt;Server-side rendering for mass personalization&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;AI &amp;#x26; Automation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Native AI features: video generation, captions, voiceovers, thumbnails&lt;/li&gt;
&lt;li&gt;Model-agnostic plugin system (integrate any AI model or API)&lt;/li&gt;
&lt;li&gt;Background removal and style transfer&lt;/li&gt;
&lt;li&gt;Smart filters and enhancements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Customization Framework:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Headless API for completely custom interfaces&lt;/li&gt;
&lt;li&gt;Theming to match your brand&lt;/li&gt;
&lt;li&gt;Toolbar configuration and element positioning&lt;/li&gt;
&lt;li&gt;Multi-language localization&lt;/li&gt;
&lt;li&gt;External asset library integration (Getty Images, Soundstripe)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;platform-support&quot;&gt;Platform Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Web:&lt;/strong&gt; JavaScript, React, Angular, Vue.js, Svelte, Next.js&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile:&lt;/strong&gt; Android (Kotlin/Java), iOS (Swift), React Native, Flutter&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Desktop:&lt;/strong&gt; macOS, Mac Catalyst, Electron&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server:&lt;/strong&gt; Node.js for backend automation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;technical-architecture&quot;&gt;Technical Architecture&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Client-side encoding&lt;/strong&gt; means fast editing operations run directly on devices without requiring backend infrastructure. This cuts bandwidth, reduces upload times for users, and eliminates server costs for standard editing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Server-side rendering&lt;/strong&gt; enables creative automation at scale — design templates once, generate thousands of variations programmatically from any data source with 100% consistent rendering.&lt;/p&gt;
&lt;h3 id=&quot;ideal-use-cases&quot;&gt;Ideal Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Social media creation:&lt;/strong&gt; In-app video recording with dual-camera support, advanced audio overlays, and real-time effects&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Template-based workflows:&lt;/strong&gt; Automate video creation for marketing materials, product videos, social media ads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise automation:&lt;/strong&gt; Server-side rendering for high-volume ad generation, creative pipelines, mass personalization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E-commerce:&lt;/strong&gt; Product video creation, user-generated content, personalized demos&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SaaS platforms:&lt;/strong&gt; In-app video editing for user-generated content, brand-controlled templates&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;real-customer-examples&quot;&gt;Real Customer Examples&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Social Media &amp;#x26; Content Creation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mobile apps use IMG.LY SDK for in-app video recording with dual-camera support, allowing creators to capture picture-in-picture content directly&lt;/li&gt;
&lt;li&gt;Advanced audio overlay features enable users to mix music tracks, voiceovers, and original audio in real-time&lt;/li&gt;
&lt;li&gt;Real-time effects and filters provide instant creative feedback during recording and editing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Template-Based Video Production:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Marketing teams design video templates once and generate thousands of personalized variations programmatically using server-side rendering&lt;/li&gt;
&lt;li&gt;E-commerce platforms automate product video creation by mapping product data to video templates, producing consistent branded content at scale&lt;/li&gt;
&lt;li&gt;Brand teams create locked templates with variable elements, ensuring on-brand output while allowing distributed teams to customize messaging&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Enterprise Creative Automation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ad platforms use CE.SDK’s Node.js capabilities for high-volume programmatic video generation, creating thousands of ad variations from single templates&lt;/li&gt;
&lt;li&gt;DAM systems integrate IMG.LY for in-workflow video editing, allowing teams to make quick adjustments without leaving their asset management platform&lt;/li&gt;
&lt;li&gt;Publishing platforms automate social media content by rendering video templates with dynamic data feeds, producing daily content without manual editing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;500+ million creations per month&lt;/strong&gt; powered by IMG.LY’s video editing and automation infrastructure across 600+ customers&lt;/p&gt;
&lt;h3 id=&quot;limitations&quot;&gt;Limitations&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Paid solution.&lt;/strong&gt; Unlike open-source frameworks, CE.SDK requires an enterprise license. This makes it less accessible for hobby projects or very early-stage prototypes, but the investment pays off in reduced development time, ongoing support, and scalability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enterprise-focused.&lt;/strong&gt; The SDK is built for teams that need reliability, support, and scale. If you’re building a quick prototype or low-traffic app, open-source tools might be more cost-effective initially (though you’ll pay in engineering time).&lt;/p&gt;
&lt;h3 id=&quot;pricing--licensing&quot;&gt;Pricing / Licensing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Custom enterprise licensing&lt;/strong&gt; based on platform, features, and usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dedicated support&lt;/strong&gt; included: onboarding, SLAs, regular updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration time:&lt;/strong&gt; Most teams have a working editor in hours, not weeks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;who-its-for&quot;&gt;Who It’s For&lt;/h3&gt;
&lt;p&gt;Businesses that need a &lt;strong&gt;complete, production-ready video editing solution&lt;/strong&gt; with cross-platform support, automation capabilities, enterprise scalability, and ongoing support. Teams that want to ship faster and focus on their unique product features rather than rebuilding video editing infrastructure.&lt;/p&gt;
&lt;h3 id=&quot;why-imgly-sdk-stands-out&quot;&gt;Why IMG.LY SDK Stands Out&lt;/h3&gt;
&lt;p&gt;While other SDKs focus on either interactive editing (Banuba, BytePlus) or backend processing (FFmpeg, GStreamer), &lt;strong&gt;IMG.LY is the only solution that combines:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cross-platform video editing (Web, iOS, Android, React Native, Flutter, Node.js)&lt;/li&gt;
&lt;li&gt;Polished editor UI with complete customization options&lt;/li&gt;
&lt;li&gt;Template system with server-side automation&lt;/li&gt;
&lt;li&gt;AI-powered creative features&lt;/li&gt;
&lt;li&gt;Dual-purpose architecture (client-side editing + server-side rendering)&lt;/li&gt;
&lt;li&gt;Enterprise-grade scalability and dedicated support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re evaluating other SDKs, ask yourself: &lt;strong&gt;how much engineering time will you spend building, maintaining, and scaling a custom solution?&lt;/strong&gt; Our SDK eliminates that overhead so your team can focus on what makes your product unique.&lt;/p&gt;
&lt;h2 id=&quot;2-meishe-sdk&quot;&gt;2. Meishe SDK&lt;/h2&gt;
&lt;p&gt;Meishe is a Chinese video editing SDK provider with a comprehensive suite covering video editing, beauty filters, short video creation, and audio processing. They’re particularly strong in the Asian market and have been adopted by major platforms like Bilibili, OPPO, Xiaomi, and Himalaya.&lt;/p&gt;
&lt;h3 id=&quot;core-capabilities-1&quot;&gt;Core Capabilities&lt;/h3&gt;
&lt;p&gt;Meishe offers film and television-level processing capabilities with a focus on high-quality output:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video Editing Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time preview through LiveWindow (preview effects during editing without pre-processing)&lt;/li&gt;
&lt;li&gt;Support for multiple file formats with input up to 4K&lt;/li&gt;
&lt;li&gt;Video output up to 1080P with configurable quality levels (1080P, 720P, 480P)&lt;/li&gt;
&lt;li&gt;Unlimited audio track editing with multi-segment support&lt;/li&gt;
&lt;li&gt;Transition effects between clips with customization options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Creative Tools:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time skin beautification with adjustable parameters&lt;/li&gt;
&lt;li&gt;Animation stickers with customizable properties&lt;/li&gt;
&lt;li&gt;Special effects filters&lt;/li&gt;
&lt;li&gt;Full-link HDR support&lt;/li&gt;
&lt;li&gt;Professional video/audio editing with free function combination&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Technical Details:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;4K shooting capability&lt;/li&gt;
&lt;li&gt;Real-time special effects processing&lt;/li&gt;
&lt;li&gt;Full-link HDR processing&lt;/li&gt;
&lt;li&gt;Professional-grade video and audio editing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;platform-support-1&quot;&gt;Platform Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Native:&lt;/strong&gt; iOS, Android&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-Platform:&lt;/strong&gt; Flutter (with unified display across platforms)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ideal-use-cases-1&quot;&gt;Ideal Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Enterprise applications requiring 4K video support&lt;/li&gt;
&lt;li&gt;Professional video editing apps&lt;/li&gt;
&lt;li&gt;Social media platforms (especially in Asian markets)&lt;/li&gt;
&lt;li&gt;Streaming and content creation apps&lt;/li&gt;
&lt;li&gt;Apps requiring HDR video processing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limitations-1&quot;&gt;Limitations&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Documentation primarily in Chinese.&lt;/strong&gt; While Meishe has English documentation, many resources and examples are primarily available in Chinese, which can create barriers for Western development teams.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Less Western market presence.&lt;/strong&gt; Most case studies and customer examples are from Chinese companies, which can make it harder to assess fit for Western markets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Customization complexity.&lt;/strong&gt; Getting deep customization may require more direct engagement with Meishe’s team compared to more self-service SDKs.&lt;/p&gt;
&lt;h3 id=&quot;pricing--licensing-1&quot;&gt;Pricing / Licensing&lt;/h3&gt;
&lt;p&gt;Pricing information is not publicly available — you’ll need to contact Meishe directly for quotes. This is common for enterprise-focused SDKs but can slow down evaluation.&lt;/p&gt;
&lt;h3 id=&quot;who-its-for-1&quot;&gt;Who It’s For&lt;/h3&gt;
&lt;p&gt;Development teams (especially in Asian markets) building professional-grade video editing apps that need 4K support, HDR processing, and advanced real-time capabilities.&lt;/p&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly&quot;&gt;How it compares to IMG.LY&lt;/h3&gt;
&lt;p&gt;Meishe offers strong professional-grade video processing with 4K and HDR support, particularly well-suited for Asian markets. IMG.LY provides similar 4K capabilities but adds cross-platform consistency (including web and server), template-driven automation, and a more developer-friendly integration experience for global teams. Meishe’s documentation is primarily in Chinese, while IMG.LY offers comprehensive English documentation and Western market support. If you’re building for Asian markets with HDR requirements, Meishe is a strong choice. For global deployment with automation needs, IMG.LY’s unified platform across client and server offers broader flexibility.&lt;/p&gt;
&lt;h2 id=&quot;3-byteplus-video-editor-sdk&quot;&gt;3. BytePlus Video Editor SDK&lt;/h2&gt;
&lt;p&gt;BytePlus Video Editor SDK comes from ByteDance (the company behind TikTok and CapCut). It’s designed to replicate the short-form, social-first editing experience that made those platforms successful, giving app developers similar workflows and effects libraries.&lt;/p&gt;
&lt;h3 id=&quot;core-capabilities-2&quot;&gt;Core Capabilities&lt;/h3&gt;
&lt;p&gt;BytePlus provides three main feature sets built around social media video creation:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Camera Feature:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time video capture and recording&lt;/li&gt;
&lt;li&gt;4K video recording on any mobile device&lt;/li&gt;
&lt;li&gt;Live filters and live beauty filters during capture&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Preview Editor Feature:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Video editing and composition tools&lt;/li&gt;
&lt;li&gt;More than 80,000 effects and filters&lt;/li&gt;
&lt;li&gt;AR stickers and visual enhancements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Track Editor Feature:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Advanced multi-track timeline editing&lt;/li&gt;
&lt;li&gt;Speed change effects&lt;/li&gt;
&lt;li&gt;Transitions and audio features&lt;/li&gt;
&lt;li&gt;Multi-layer composition&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Export Options:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for 540p, 720p, 1080p, 4K resolutions&lt;/li&gt;
&lt;li&gt;Frame rates: 25fps, 30fps, 50fps, 60fps&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;platform-support-2&quot;&gt;Platform Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Native:&lt;/strong&gt; iOS (Cocoapods, SPM, Objective-C, SwiftUI), Android (Gradle, Java, Jetpack Compose)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-Platform:&lt;/strong&gt; React Native, Flutter&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Magic Template SDK:&lt;/strong&gt; Available for both platforms&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ideal-use-cases-2&quot;&gt;Ideal Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Social media apps focused on user-generated content&lt;/li&gt;
&lt;li&gt;Short-form video platforms&lt;/li&gt;
&lt;li&gt;Apps that want TikTok-like editing workflows&lt;/li&gt;
&lt;li&gt;Content creation tools with extensive effects libraries&lt;/li&gt;
&lt;li&gt;Apps requiring machine learning-powered visual enhancements&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limitations-2&quot;&gt;Limitations&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Effects and beauty features are separate.&lt;/strong&gt; The standard and lite versions of the SDK don’t include Camera props, filters, and beauty effects — you need to purchase those separately, which can complicate pricing and integration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Customization beyond theming is limited.&lt;/strong&gt; While you can match the SDK to your brand through theming, deeper UI customization requires more effort compared to headless SDKs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Annual licensing only.&lt;/strong&gt; The SDK operates on an annual subscription basis, which may not work for all business models or early-stage products.&lt;/p&gt;
&lt;h3 id=&quot;pricing--licensing-2&quot;&gt;Pricing / Licensing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Annual subscription:&lt;/strong&gt; License valid for 1 year covering both iOS and Android&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contact sales&lt;/strong&gt; for pricing details&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration time:&lt;/strong&gt; Estimated 2 weeks per platform (iOS &amp;#x26; Android) for one developer&lt;/li&gt;
&lt;li&gt;Customization may extend integration timeline&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;who-its-for-2&quot;&gt;Who It’s For&lt;/h3&gt;
&lt;p&gt;Teams building social media-style video apps that want to replicate TikTok’s editing experience, especially if you need access to a massive effects library and ByteDance’s proven video editing architecture.&lt;/p&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-1&quot;&gt;How it compares to IMG.LY&lt;/h3&gt;
&lt;p&gt;BytePlus brings TikTok’s proven social video editing architecture with 80,000+ effects and filters, making it ideal for replicating short-form social experiences. IMG.LY takes a different approach: instead of a massive pre-built effects library, it focuses on customization, templates, and automation. BytePlus excels at client-side social video creation with extensive effects; IMG.LY excels at template-driven workflows, server-side automation, and cross-platform consistency (including web and Node.js). If you want TikTok-like effects out of the box, BytePlus delivers. If you need creative automation, programmatic content generation, or want to build custom workflows with full control over the editing experience, IMG.LY offers more flexibility and a dual-purpose architecture.&lt;/p&gt;
&lt;h2 id=&quot;4-banuba-video-editor-sdk&quot;&gt;4. Banuba Video Editor SDK&lt;/h2&gt;
&lt;p&gt;Banuba is a commercial video editing SDK focused on social media apps, with a strong emphasis on AR effects and beauty filters. It’s designed for teams building TikTok-like experiences or apps where user-generated video content is central to the product.&lt;/p&gt;
&lt;h3 id=&quot;core-capabilities-3&quot;&gt;Core Capabilities&lt;/h3&gt;
&lt;p&gt;Banuba provides a full-featured video editor with AI-powered tools and creative effects:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video Editing Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Picture-in-picture for multi-video layouts&lt;/li&gt;
&lt;li&gt;AI-powered clipping that detects important segments&lt;/li&gt;
&lt;li&gt;Customizable templates with replaceable elements&lt;/li&gt;
&lt;li&gt;Trimming, merging, and timeline-based editing&lt;/li&gt;
&lt;li&gt;AI-generated captions (English, Mandarin, Spanish, Portuguese)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Creative Tools:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Face AR masks with morphing effects and animated backgrounds&lt;/li&gt;
&lt;li&gt;Video and transition effects (including “Rave” and “Cathode Flash”)&lt;/li&gt;
&lt;li&gt;Audio editing with recording and mixing&lt;/li&gt;
&lt;li&gt;Text and GIF overlays&lt;/li&gt;
&lt;li&gt;Beauty effects (skin smoothing, teeth whitening)&lt;/li&gt;
&lt;li&gt;Voice-change effects (Elf, Robot, Squirrel, Giant, Echo, Baritone)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Technical Details:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI algorithms work offline — all processing happens on the device&lt;/li&gt;
&lt;li&gt;No user content transmitted to servers&lt;/li&gt;
&lt;li&gt;Requires OpenGL ES 3.0 minimum (3.1 for GPU-accelerated neural networks)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;platform-support-3&quot;&gt;Platform Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Native:&lt;/strong&gt; iOS 15.0+, Android 6.0+&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-Platform:&lt;/strong&gt; React Native, Flutter, NativeScript&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ideal-use-cases-3&quot;&gt;Ideal Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Social media applications with AR filters&lt;/li&gt;
&lt;li&gt;Photo/video editing apps for content creators&lt;/li&gt;
&lt;li&gt;E-commerce platforms with video demos&lt;/li&gt;
&lt;li&gt;Lifestyle and educational apps&lt;/li&gt;
&lt;li&gt;Short-form video content creation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limitations-3&quot;&gt;Limitations&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pricing complexity.&lt;/strong&gt; Banuba’s pricing is custom and depends on platform, features, custom development, and payment terms. You’ll need to contact sales for accurate quotes, which can slow down evaluation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AR licensing.&lt;/strong&gt; Face AR features are optional and may require separate licensing, adding complexity to your commercial agreement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Heavy focus on AR.&lt;/strong&gt; If you don’t need beauty filters or AR masks, you’re paying for features you won’t use.&lt;/p&gt;
&lt;h3 id=&quot;pricing--licensing-3&quot;&gt;Pricing / Licensing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free trial:&lt;/strong&gt; 14 days with all features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commercial:&lt;/strong&gt; Custom pricing based on platform, features, and usage&lt;/li&gt;
&lt;li&gt;Priced per platform per month&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;who-its-for-3&quot;&gt;Who It’s For&lt;/h3&gt;
&lt;p&gt;Teams building social media apps or content creation tools that need AR effects, beauty filters, and TikTok-like creative features out of the box.&lt;/p&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-2&quot;&gt;How it compares to IMG.LY&lt;/h3&gt;
&lt;p&gt;Banuba excels at AR effects and beauty filters for social media apps, while IMG.LY focuses on template-based workflows and cross-platform automation. If you need face masks and beauty effects, Banuba is purpose-built for that. But if you need server-side rendering, creative automation, or want the same editing engine across web, mobile, and backend, IMG.LY provides broader platform coverage and a dual-purpose architecture. Banuba is optimized for client-side social video creation; IMG.LY handles both interactive editing and programmatic content generation at scale.&lt;/p&gt;
&lt;h2 id=&quot;5-ffmpeg-via-ffmpegkit&quot;&gt;5. FFmpeg (via FFmpegKit)&lt;/h2&gt;
&lt;p&gt;FFmpeg is the industry-standard open-source tool for video processing. It’s not a video SDK in the traditional sense — it’s a command-line tool and set of libraries that handle encoding, decoding, transcoding, filtering, and nearly every video operation imaginable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FFmpegKit&lt;/strong&gt; is a wrapper that makes FFmpeg accessible on mobile platforms (Android, iOS, React Native, Flutter) through platform-specific APIs. It’s the primary way developers integrate FFmpeg into mobile apps.&lt;/p&gt;
&lt;h3 id=&quot;core-capabilities-4&quot;&gt;Core Capabilities&lt;/h3&gt;
&lt;p&gt;FFmpeg handles the entire video processing pipeline:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video Operations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encoding and decoding (every codec imaginable)&lt;/li&gt;
&lt;li&gt;Format conversion (MP4, MOV, AVI, MKV, WebM, etc.)&lt;/li&gt;
&lt;li&gt;Trimming, cutting, merging, splitting&lt;/li&gt;
&lt;li&gt;Filtering and effects&lt;/li&gt;
&lt;li&gt;Subtitle burning&lt;/li&gt;
&lt;li&gt;Video stabilization&lt;/li&gt;
&lt;li&gt;Audio extraction and mixing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Technical Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Command-line interface (via wrapper APIs)&lt;/li&gt;
&lt;li&gt;Support for hardware acceleration&lt;/li&gt;
&lt;li&gt;Concurrent command execution&lt;/li&gt;
&lt;li&gt;Extensive codec library&lt;/li&gt;
&lt;li&gt;Professional-grade output quality&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;platform-support-4&quot;&gt;Platform Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Native:&lt;/strong&gt; Android (Java API), iOS (Objective-C API), Linux (C++ API), macOS, tvOS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-Platform:&lt;/strong&gt; Flutter (Dart API), React Native (JavaScript API with TypeScript definitions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eight prebuilt packages:&lt;/strong&gt; Distributed via Maven Central, CocoaPods, pub, npm&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ideal-use-cases-4&quot;&gt;Ideal Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Backend video processing and transcoding&lt;/li&gt;
&lt;li&gt;Format conversion at scale&lt;/li&gt;
&lt;li&gt;Apps that need specific codec support&lt;/li&gt;
&lt;li&gt;Video compression and optimization&lt;/li&gt;
&lt;li&gt;Building custom video processing pipelines&lt;/li&gt;
&lt;li&gt;Server-side automation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limitations-4&quot;&gt;Limitations&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;No UI whatsoever.&lt;/strong&gt; FFmpeg is a processing engine. If you want users to interact with video — timelines, filters, previews — you’ll need to build the entire interface yourself from scratch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Steep learning curve.&lt;/strong&gt; FFmpeg’s command-line syntax is powerful but complex. Even simple tasks require understanding flags, options, and codec parameters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GPL licensing complexity.&lt;/strong&gt; While FFmpegKit itself is LGPL v3.0, including GPL-licensed libraries makes the entire bundle GPL v3.0, which has implications for commercial apps.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FFmpegKit has been officially retired.&lt;/strong&gt; As of June 2025, FFmpegKit is no longer maintained. Community-maintained forks exist, but official support is ending.&lt;/p&gt;
&lt;h3 id=&quot;pricing--licensing-4&quot;&gt;Pricing / Licensing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free and open-source:&lt;/strong&gt; LGPL v3.0 for FFmpegKit library&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPL v3.0&lt;/strong&gt; when GPL-licensed libraries are included&lt;/li&gt;
&lt;li&gt;Licensing depends on which codecs and libraries you bundle&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;who-its-for-4&quot;&gt;Who It’s For&lt;/h3&gt;
&lt;p&gt;Developers who need powerful backend video processing, format conversion, or transcoding — and are willing to build all user-facing features themselves. Not suitable for teams that need a ready-to-use editor.&lt;/p&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-3&quot;&gt;How it compares to IMG.LY&lt;/h3&gt;
&lt;p&gt;FFmpeg is a processing engine, not an editing SDK. It handles transcoding, format conversion, and video manipulation via command-line operations — but provides no UI, no templates, and no interactive editing components. IMG.LY includes a production-ready editor, template system, and user-facing tools out of the box, while also supporting server-side automation through Node.js. If you only need backend processing and are building all UI yourself, FFmpeg (via community forks) can work. If you need both interactive editing and automation, IMG.LY eliminates months of development by providing both in one platform. IMG.LY also avoids GPL licensing complications and the uncertainty of using a retired library with community forks.&lt;/p&gt;
&lt;h2 id=&quot;6-gstreamer-with-gstreamer-editing-services&quot;&gt;6. GStreamer (with GStreamer Editing Services)&lt;/h2&gt;
&lt;p&gt;GStreamer is a mature open-source multimedia framework used across Linux, Android, iOS, Windows, and macOS. It’s designed for building media applications — streaming, playback, recording, and non-linear editing — with a plugin-based architecture that makes it extremely flexible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GStreamer Editing Services (GES)&lt;/strong&gt; is a higher-level library built on top of GStreamer to simplify video editing application development. It was originally funded by Nokia for mobile video editing (“video editing in your pocket”).&lt;/p&gt;
&lt;h3 id=&quot;core-capabilities-5&quot;&gt;Core Capabilities&lt;/h3&gt;
&lt;p&gt;GStreamer provides the foundation for building multimedia applications:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Audio and video playback, recording, streaming&lt;/li&gt;
&lt;li&gt;Non-linear editing capabilities via GES&lt;/li&gt;
&lt;li&gt;Extensive plugin library (encoders, decoders, filters)&lt;/li&gt;
&lt;li&gt;Hardware acceleration support&lt;/li&gt;
&lt;li&gt;Low-latency streaming (RTSP, WebRTC)&lt;/li&gt;
&lt;li&gt;Support for diverse codecs and formats&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;GStreamer Editing Services:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High-level API for creating editing applications&lt;/li&gt;
&lt;li&gt;Timeline-based editing&lt;/li&gt;
&lt;li&gt;Transition effects&lt;/li&gt;
&lt;li&gt;Audio mixing&lt;/li&gt;
&lt;li&gt;Asset management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Performance Optimizations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Offloading work to specialized hardware (DSPs, GPUs)&lt;/li&gt;
&lt;li&gt;Low power consumption for embedded processors&lt;/li&gt;
&lt;li&gt;Support for ARM, MIPS, SPARC architectures&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;platform-support-5&quot;&gt;Platform Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cross-Platform:&lt;/strong&gt; Linux, Android, iOS, Windows, macOS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language Bindings:&lt;/strong&gt; C++ (primary), Python, Java, JavaScript&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile:&lt;/strong&gt; Official SDK binaries for Android and iOS&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ideal-use-cases-5&quot;&gt;Ideal Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Custom video editing apps requiring deep control&lt;/li&gt;
&lt;li&gt;Streaming applications (RTSP, WebRTC)&lt;/li&gt;
&lt;li&gt;Media players and recording apps&lt;/li&gt;
&lt;li&gt;Research and academic projects&lt;/li&gt;
&lt;li&gt;Embedded systems and IoT devices&lt;/li&gt;
&lt;li&gt;Apps requiring specialized codec support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limitations-5&quot;&gt;Limitations&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Steep learning curve.&lt;/strong&gt; GStreamer’s plugin-based architecture is powerful but complex. Understanding pipelines, bins, and element linking takes time even for experienced developers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No pre-built UI.&lt;/strong&gt; GES provides editing APIs, but you’ll need to build the entire interface yourself. This means designing timelines, playback controls, effect panels, export dialogs — everything.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limited mobile-specific examples.&lt;/strong&gt; While GStreamer officially supports iOS and Android, production-ready mobile editing examples are scarce. You’ll be pioneering integration patterns yourself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integration complexity.&lt;/strong&gt; Getting GStreamer running on mobile requires compiling binaries, managing dependencies, and debugging platform-specific issues. This isn’t a “drop in and go” integration.&lt;/p&gt;
&lt;h3 id=&quot;pricing--licensing-5&quot;&gt;Pricing / Licensing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free and open-source:&lt;/strong&gt; LGPL license&lt;/li&gt;
&lt;li&gt;GStreamer Editing Services included in main distribution&lt;/li&gt;
&lt;li&gt;No commercial support by default, but third-party companies (like Fluendo) offer commercial support and custom development&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;who-its-for-5&quot;&gt;Who It’s For&lt;/h3&gt;
&lt;p&gt;Teams with strong multimedia engineering expertise who need deep control over video processing and are willing to build everything from the ground up. Not suitable for teams that need fast time-to-market or lack video processing experience.&lt;/p&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-4&quot;&gt;How it compares to IMG.LY&lt;/h3&gt;
&lt;p&gt;GStreamer provides powerful low-level control over multimedia processing through its plugin-based architecture, making it ideal for specialized use cases like streaming, embedded systems, or custom pipelines. IMG.LY provides a higher-level, production-ready solution with UI components, templates, and automation built in. GStreamer requires significant expertise and months of development to build user-facing features; IMG.LY offers a working editor in hours with customization options that don’t require multimedia engineering expertise. If you need deep control over codecs, streaming protocols, or embedded deployment, GStreamer’s flexibility is unmatched. If you need to ship a production-ready video editor quickly with cross-platform support and automation capabilities, IMG.LY eliminates the complexity and provides enterprise support.&lt;/p&gt;
&lt;h2 id=&quot;comparison-table-video-sdks-for-mobile-applications&quot;&gt;Comparison Table: Video SDKs for Mobile Applications&lt;/h2&gt;












































































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Feature / SDK&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Banuba&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Meishe&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;BytePlus&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;FFmpeg&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;GStreamer&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;IMG.LY SDK&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Platform Support&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;iOS 15+, Android 6+, React Native, Flutter, NativeScript&lt;/td&gt;&lt;td&gt;iOS, Android, Flutter&lt;/td&gt;&lt;td&gt;iOS, Android, React Native, Flutter&lt;/td&gt;&lt;td&gt;Android, iOS, React Native, Flutter, Linux, macOS&lt;/td&gt;&lt;td&gt;Linux, Android, iOS, Windows, macOS&lt;/td&gt;&lt;td&gt;Web, iOS, Android, React Native, Flutter, Desktop, Node.js&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;UI Included&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Pre-built editor&lt;/td&gt;&lt;td&gt;✅ Pre-built editor&lt;/td&gt;&lt;td&gt;✅ Pre-built editor&lt;/td&gt;&lt;td&gt;❌ Processing only&lt;/td&gt;&lt;td&gt;❌ GES provides APIs only&lt;/td&gt;&lt;td&gt;✅ Production-ready editor + Headless API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Timeline Editing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Yes&lt;/td&gt;&lt;td&gt;✅ Yes&lt;/td&gt;&lt;td&gt;✅ Multi-track&lt;/td&gt;&lt;td&gt;❌ Command-line only&lt;/td&gt;&lt;td&gt;✅ Via GES&lt;/td&gt;&lt;td&gt;✅ Advanced multi-track&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;AR / Beauty Filters&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Strong focus&lt;/td&gt;&lt;td&gt;✅ Real-time beauty&lt;/td&gt;&lt;td&gt;✅ 80,000+ effects&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;✅ Filters + extensible AI plugins&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Customizable&lt;/td&gt;&lt;td&gt;⚠️ Limited info&lt;/td&gt;&lt;td&gt;✅ Magic Templates&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;✅ Advanced template system with variables&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Server-Side Automation&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;❌ No&lt;/td&gt;&lt;td&gt;❌ No&lt;/td&gt;&lt;td&gt;❌ No&lt;/td&gt;&lt;td&gt;✅ CLI-based&lt;/td&gt;&lt;td&gt;✅ Possible but complex&lt;/td&gt;&lt;td&gt;✅ Native support (same engine)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;AI Features&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ AI clipping, captions&lt;/td&gt;&lt;td&gt;⚠️ Limited info&lt;/td&gt;&lt;td&gt;✅ ML-powered effects&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;✅ Native AI + model-agnostic plugins&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;4K Support&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Yes&lt;/td&gt;&lt;td&gt;✅ Up to 4K input&lt;/td&gt;&lt;td&gt;✅ 4K recording&lt;/td&gt;&lt;td&gt;✅ Yes&lt;/td&gt;&lt;td&gt;✅ Yes&lt;/td&gt;&lt;td&gt;✅ Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Customization Level&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;⚠️ UI/UX + optional API&lt;/td&gt;&lt;td&gt;⚠️ Requires team engagement&lt;/td&gt;&lt;td&gt;⚠️ Theming primarily&lt;/td&gt;&lt;td&gt;✅ Complete control&lt;/td&gt;&lt;td&gt;✅ Complete control&lt;/td&gt;&lt;td&gt;✅ Headless API + theming + UI config&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Integration Complexity&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;⚠️ Moderate (GitHub samples)&lt;/td&gt;&lt;td&gt;⚠️ Moderate&lt;/td&gt;&lt;td&gt;⚠️ Moderate (~2 weeks)&lt;/td&gt;&lt;td&gt;⚠️ Complex (retired library)&lt;/td&gt;&lt;td&gt;⚠️ Very complex&lt;/td&gt;&lt;td&gt;✅ Simple (hours to integrate)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ English, developer portal&lt;/td&gt;&lt;td&gt;⚠️ Primarily Chinese&lt;/td&gt;&lt;td&gt;✅ English, comprehensive&lt;/td&gt;&lt;td&gt;✅ Extensive community docs&lt;/td&gt;&lt;td&gt;✅ Extensive but complex&lt;/td&gt;&lt;td&gt;✅ Comprehensive with samples&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Licensing / Pricing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Custom (free 14-day trial)&lt;/td&gt;&lt;td&gt;Contact for quote&lt;/td&gt;&lt;td&gt;Annual subscription&lt;/td&gt;&lt;td&gt;Free, LGPL/GPL&lt;/td&gt;&lt;td&gt;Free, LGPL&lt;/td&gt;&lt;td&gt;Enterprise license&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Enterprise Support&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;⚠️ Custom agreements&lt;/td&gt;&lt;td&gt;⚠️ Direct engagement&lt;/td&gt;&lt;td&gt;⚠️ ByteDance support&lt;/td&gt;&lt;td&gt;❌ Community only&lt;/td&gt;&lt;td&gt;⚠️ Third-party (Fluendo)&lt;/td&gt;&lt;td&gt;✅ Dedicated support + SLAs&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Social media apps with AR focus&lt;/td&gt;&lt;td&gt;Professional apps in Asian markets&lt;/td&gt;&lt;td&gt;TikTok-like social video apps&lt;/td&gt;&lt;td&gt;Backend processing / transcoding&lt;/td&gt;&lt;td&gt;Custom multimedia apps&lt;/td&gt;&lt;td&gt;Cross-platform editing + automation at scale&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;making-your-decision-which-video-sdk-is-right-for-you&quot;&gt;Making Your Decision: Which Video SDK Is Right for You?&lt;/h2&gt;
&lt;p&gt;Here’s the honest breakdown based on your use case:&lt;/p&gt;
&lt;h3 id=&quot;choose-banuba-if&quot;&gt;Choose &lt;strong&gt;Banuba&lt;/strong&gt; if:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You’re building a social media app and AR effects are central to your product&lt;/li&gt;
&lt;li&gt;You need beauty filters, face masks, and creative effects out of the box&lt;/li&gt;
&lt;li&gt;Your primary audience expects TikTok-style creative tools&lt;/li&gt;
&lt;li&gt;You’re comfortable with custom pricing and optional feature licensing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;choose-meishe-if&quot;&gt;Choose &lt;strong&gt;Meishe&lt;/strong&gt; if:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You’re targeting Asian markets where Meishe has strong adoption&lt;/li&gt;
&lt;li&gt;You need professional-grade 4K and HDR video processing&lt;/li&gt;
&lt;li&gt;Real-time preview and film-quality output are critical&lt;/li&gt;
&lt;li&gt;You have access to Chinese documentation resources or engineering support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;choose-byteplus-if&quot;&gt;Choose &lt;strong&gt;BytePlus&lt;/strong&gt; if:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You want to replicate TikTok/CapCut’s editing experience&lt;/li&gt;
&lt;li&gt;You need access to 80,000+ effects and filters&lt;/li&gt;
&lt;li&gt;Machine learning-powered visual enhancements are important&lt;/li&gt;
&lt;li&gt;You’re comfortable with annual licensing and want ByteDance’s proven architecture&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;choose-ffmpeg-if&quot;&gt;Choose &lt;strong&gt;FFmpeg&lt;/strong&gt; if:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You need backend video processing, transcoding, or format conversion&lt;/li&gt;
&lt;li&gt;You’re building automation pipelines, not user-facing editors&lt;/li&gt;
&lt;li&gt;You have strong video engineering expertise&lt;/li&gt;
&lt;li&gt;You’re okay with command-line complexity and building all UI yourself&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be aware:&lt;/strong&gt; FFmpegKit is officially retired; plan for community forks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;choose-gstreamer-if&quot;&gt;Choose &lt;strong&gt;GStreamer&lt;/strong&gt; if:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You need deep control over multimedia processing&lt;/li&gt;
&lt;li&gt;You’re building custom streaming, playback, or editing applications&lt;/li&gt;
&lt;li&gt;You have strong multimedia engineering expertise&lt;/li&gt;
&lt;li&gt;You’re willing to invest significant time in integration and UI development&lt;/li&gt;
&lt;li&gt;You need specialized codec support or embedded system deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;choose-imgly-cesdk-if&quot;&gt;Choose &lt;strong&gt;IMG.LY CE.SDK&lt;/strong&gt; if:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You need both interactive editing and server-side automation&lt;/li&gt;
&lt;li&gt;Cross-platform consistency is critical (Web, iOS, Android, React Native, Flutter)&lt;/li&gt;
&lt;li&gt;You want a production-ready editor that integrates in hours, not months&lt;/li&gt;
&lt;li&gt;Template-based workflows and creative automation are important&lt;/li&gt;
&lt;li&gt;You need enterprise support, SLAs, and ongoing updates&lt;/li&gt;
&lt;li&gt;Your team wants to focus on product features, not rebuilding video editing infrastructure&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;build-vs-buy-whats-the-real-cost&quot;&gt;Build vs Buy: What’s the Real Cost?&lt;/h2&gt;
&lt;p&gt;Let’s be honest about the engineering investment required:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Building on FFmpeg or GStreamer:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Months&lt;/strong&gt; to build a basic timeline editor with preview&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ongoing maintenance&lt;/strong&gt; for device compatibility, codec updates, performance optimization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No UI components&lt;/strong&gt; — you’re building everything from scratch&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scaling challenges&lt;/strong&gt; when you need templates, automation, or new features&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Commercial SDKs (Banuba, Meishe, BytePlus):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Days to weeks&lt;/strong&gt; for basic integration&lt;/li&gt;
&lt;li&gt;Pre-built UI and effects libraries&lt;/li&gt;
&lt;li&gt;Dedicated support for troubleshooting&lt;/li&gt;
&lt;li&gt;Licensing costs vary; evaluate based on your revenue model&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;IMG.LY SDK:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hours&lt;/strong&gt; to integrate a working editor&lt;/li&gt;
&lt;li&gt;Production-ready UI with full customization&lt;/li&gt;
&lt;li&gt;Dual-purpose: client-side editing + server-side automation&lt;/li&gt;
&lt;li&gt;Template system and AI features included&lt;/li&gt;
&lt;li&gt;Enterprise support and regular updates&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ask yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What’s your timeline?&lt;/strong&gt; If you need to ship in weeks, open-source frameworks won’t get you there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What’s your team’s expertise?&lt;/strong&gt; Video processing is complex; building from scratch requires specialized knowledge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What happens when you scale?&lt;/strong&gt; Adding templates, automation, or AI features to a custom-built solution takes months of additional work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commercial SDKs cost money upfront but save significant engineering time. Open-source tools are “free” but expensive in development hours and opportunity cost.&lt;/p&gt;
&lt;h2 id=&quot;conclusion-the-right-sdk-depends-on-your-goals&quot;&gt;Conclusion: The Right SDK Depends on Your Goals&lt;/h2&gt;
&lt;p&gt;There’s no one-size-fits-all answer, but here’s the summary:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FFmpeg and GStreamer&lt;/strong&gt; are powerful processing engines for developers who need backend automation or custom pipelines. They give you complete control but require significant expertise and offer no user-facing components. Great for transcoding, format conversion, and specialized workflows — not for building interactive editors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Banuba, Meishe, and BytePlus&lt;/strong&gt; are excellent for social media apps that need AR effects, beauty filters, and TikTok-style editing. They provide pre-built editors with extensive effects libraries, but customization beyond theming can be limited, and they’re focused primarily on client-side editing (no server automation).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IMG.LY CE.SDK&lt;/strong&gt; is the only solution that combines production-ready interactive editing with server-side creative automation. We provide cross-platform consistency, a complete template system, AI features, and enterprise support — all in one platform. Where other SDKs require you to choose between editing and automation, we give you both.&lt;/p&gt;
&lt;p&gt;If you’re building an app where video editing is a core feature (not a side project), and you need to ship fast without compromising on quality or scalability, our SDK eliminates months of development work and ongoing maintenance headaches.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The real question isn’t “which SDK is cheapest?”&lt;/strong&gt; It’s &lt;strong&gt;“how much engineering time will we spend building, maintaining, and scaling a custom solution — and what could we build instead if we had that time back?”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ready to see what IMG.LY SDK can do? &lt;a href=&quot;https://img.ly/showcases/cesdk&quot;&gt;Explore our demos&lt;/a&gt; or &lt;a href=&quot;https://img.ly/forms/contact-sales&quot;&gt;get in touch&lt;/a&gt; to discuss your project.&lt;/p&gt;</content:encoded><dc:creator>Klaudia</dc:creator><media:content url="https://blog.img.ly/2025/12/best-video-mobile-editor-sdk.jpg" medium="image"/><category>Video Editor</category><category>Mobile App Development</category><category>Insights</category></item><item><title>Best Open Source Video Editor SDKs: 2026 Roundup</title><link>https://img.ly/blog/best-open-source-video-editor-sdks-2025-roundup/</link><guid isPermaLink="true">https://img.ly/blog/best-open-source-video-editor-sdks-2025-roundup/</guid><description>Looking for the best open source video editor SDKs? Read this blog to get a comparison of the top solutions: FFmpeg, MoviePy, OpenShot Library, GStreamer, Remotion, and a commercial alternative: IMG.LY CE.SDK. </description><pubDate>Mon, 10 Nov 2025 11:13:59 GMT</pubDate><content:encoded>&lt;p&gt;If you’ve ever tried building a video editing feature from scratch, you know how quickly things can get complicated. Codecs, pipelines, formats, integrations, and performance tuning all come into play. &lt;/p&gt;
&lt;p&gt;That’s why developers often turn to open-source SDKs that make video processing more accessible and flexible.&lt;/p&gt;
&lt;p&gt;In this guide, we’ll break down some of the most widely used open-source video SDKs, focusing on how easy these tools are to build with, their use cases, and who they’re best for. We’ll also look at where open-source flexibility meets its limits, and how commercial SDKs like IMG.LY can save you time and complexity when building production-ready video products.&lt;/p&gt;
&lt;h2 id=&quot;1-ffmpeg&quot;&gt;&lt;strong&gt;1. FFmpeg&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Let’s start the comparison with one of the most popular open source video editor SDKs. FFmpeg is a command-line multimedia framework that powers much of the modern video ecosystem. It supports everything from transcoding to advanced automation, making it one of the most widely adopted open-source solutions for video processing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; FFmpeg includes transcoding, filtering, cropping, resizing, overlaying, color grading, audio processing, and format conversion. Its flexibility comes from its powerful command-line interface, allowing developers to script nearly any video transformation task.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platforms:&lt;/strong&gt; The tool offers broad cross-platform compatibility, running natively on Windows, macOS, and Linux. Its portability allows it to integrate into a wide range of development environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building difficulty &amp;#x26; potential roadblocks:&lt;/strong&gt; FFmpeg is quite difficult to learn and implement for beginners. It requires strong knowledge of scripting, codecs, and CLI-based workflows. Due to its steep learning curve, debugging complex filter chains can be time-consuming, and integrating it into GUI-based environments is also challenging. Developers must also navigate potential H.264 commercial licensing restrictions while using this tool.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt; FFmpeg is best suited for server-side batch processing, video pipelines, and automated transcoding. While it excels in backend automation, it lacks an interactive editor UI or cross-platform embedding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proofing, support &amp;#x26; pricing:&lt;/strong&gt; FFmpeg is a mature and stable project used across many industries for years, although its innovation is slow. Most developers using the tool rely on community forums and documentation for troubleshooting and setup help. It’s completely free and open-source, but encoding with certain codecs like H.264 may still require a separate commercial license.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; This video editor SDK is ideal for developers handling large-scale backend video processing or transcoding tasks. It’s powerful and reliable, but not beginner-friendly or suited for products needing a visual editing interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;comparison-to-imgly&quot;&gt;&lt;strong&gt;Comparison to IMG.LY&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;FFmpeg is purely backend and lacks an interactive editor or cross-platform embedding capabilities. However, it performs exceptionally well in large-scale automation pipelines, where speed, reliability, and format support are critical. IMG.LY CE.SDK, by contrast, gives you a fully embeddable video editor, UI components, and automation workflows in a unified SDK. All without the complexity of manual scripting. &lt;/p&gt;
&lt;p&gt;Check out why &lt;a href=&quot;https://img.ly/ffmpeg-js-alternative&quot;&gt;IMG.LY is a great alternative to FFmpeg&lt;/a&gt; here. &lt;/p&gt;
&lt;h2 id=&quot;2-moviepy&quot;&gt;&lt;strong&gt;2. MoviePy&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The next open source video editor on the list is MoviePy. It’s a Python library for programmatic video editing. It allows developers to edit video through code, making it particularly useful for automated workflows or content prototyping. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; It supports cutting, compositing, adding text overlays, transitions, and visual effects. Developers can use Python scripts to build video sequences and automate rendering.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platforms:&lt;/strong&gt; MoviePy works across all major platforms that support Python. It runs in standard Python environments without requiring extra setup, which makes it accessible for most developers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building difficulty &amp;#x26; potential roadblocks:&lt;/strong&gt; MoviePy is easier to use than FFmpeg, but still requires scripting. It’s suitable for Python developers for prototyping, but it can struggle with performance when handling large video files. Developers often face challenges with dependency management and the absence of a real-time UI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; This tool is best for automated content generation, research, and rapid prototyping of video workflows. It’s ideal for proof-of-concept projects where scripting flexibility matters more than performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proofing, support &amp;#x26; pricing:&lt;/strong&gt; MoviePy is actively maintained by its niche community of developers. While it serves a smaller user base compared to larger frameworks, its reliability and accessibility make it a consistent choice for Python-based video projects. You can find support through community documentation that explains most functions clearly. It’s free and open-source, which makes it especially appealing for experimentation, research, and smaller-scale automation setups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who its for:&lt;/strong&gt; MoviePy is a great choice if you’re a Python developer wanting automation or experimental workflows. However, it’s not ideal for production-scale or interactive use cases due to performance limits and the absence of a UI. &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;comparison-to-imgly-1&quot;&gt;&lt;strong&gt;Comparison to IMG.LY&lt;/strong&gt; &lt;/h3&gt;
&lt;p&gt;MoviePy is designed for scripting and backend automation. It works best for creating short automated clips or experimental workflows where developers want full control through Python code. &lt;/p&gt;
&lt;p&gt;IMG.LY CE.SDK goes beyond backend scripting by offering ready-to-embed editors, automation APIs, and full multi-platform support for web and mobile. This makes it a more complete choice if your team needs both automation and interactive editing within products.  &lt;/p&gt;
&lt;h2 id=&quot;3-openshot-library--mlt-framework&quot;&gt;&lt;strong&gt;3. OpenShot Library / MLT Framework&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The OpenShot Library, built on the MLT Framework, is a C++/Python library for video compositing and timeline editing. It powers the OpenShot video editor and can be integrated into custom desktop applications.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; It provides timeline editing, transitions, effects, and audio mixing. Developers can implement advanced video composition features similar to traditional desktop editors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platforms:&lt;/strong&gt; The library is cross-platform, working reliably across major desktop operating systems, including Windows, macOS, and Linux. It can be integrated into various environments, which makes it useful if you’re building desktop editors or applications that require timeline-based video editing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building difficulty &amp;#x26; potential roadblocks:&lt;/strong&gt; The integration complexity is medium-high, as the API can be unstable, and managing dependencies can be difficult. Developers may also encounter documentation gaps, making it challenging to set up and maintain. Integrating the library into a GUI is not straightforward, and limited server-side automation means it is less suited for scalable or cloud-based workflows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; OpenShot Library is suitable for you if you’re looking to build desktop-based editors, experimental timeline tools, or custom video composition applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proofing, support &amp;#x26; pricing:&lt;/strong&gt; The framework is actively maintained and works well for desktop video editing applications. However, it is not designed for server-side automation or large-scale deployment. The support is community-driven, so the updates and fixes depend on volunteer contributions, which can affect long-term reliability for enterprise use. The framework is free and open-source, making it accessible to anyone looking to experiment or build lightweight video editing tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who its for:&lt;/strong&gt; OpenShot/MLT fits developers building desktop-focused editors who need timeline control but can manage API and dependency challenges. It’s less practical for cloud or mobile workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;comparison-to-imgly-2&quot;&gt;&lt;strong&gt;Comparison to IMG.LY&lt;/strong&gt; &lt;/h3&gt;
&lt;p&gt;While OpenShot/MLT excels in desktop-based timeline editing, it is better suited for applications that prioritize local processing and desktop workflows. &lt;/p&gt;
&lt;p&gt;IMG.LY CE.SDK, on the other hand, offers embedded, cross-platform editors with built-in automation, making it a more versatile choice for SaaS and enterprise environments that need scalability, faster integration, and an intuitive editing experience for end users.&lt;/p&gt;
&lt;h2 id=&quot;4-gstreamer&quot;&gt;&lt;strong&gt;4. GStreamer&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;GStreamer is a multimedia framework for building video and audio pipelines. It’s a foundational tool in many streaming and broadcast systems and allows developers to create complex pipelines for capturing, processing, and outputting media in real time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; This open source video editor supports real-time processing, filters, and complex pipelines for media processing and streaming. Developers can construct customized processing chains for advanced workflows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platforms:&lt;/strong&gt; GStreamer is cross-platform, supporting multiple programming languages with bindings for C, Python, Java, and Rust. You can run it on Windows, macOS, and Linux, and integrate it into both desktop and server environments. This makes it flexible for building diverse media workflows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building difficulty &amp;#x26; potential roadblocks:&lt;/strong&gt; Building with GStreamer is complex. It requires deep knowledge of pipelines and plugins, and debugging can be time-intensive. UI integration adds another layer of difficulty.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; Despite its building difficulty, developers use GStreamer for real-time video streaming, server-side processing, and for broadcast applications requiring precise control over data flow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proofing, support &amp;#x26; pricing:&lt;/strong&gt; GStreamer is mature and widely used in the media industry. It continues to be a reliable choice for building streaming and broadcast systems, but it requires significant development expertise to configure and maintain. Developers often rely on community resources for support, though some commercial assistance is available. It’s free and open-source, which makes it accessible for experimentation and custom media workflows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; The tool is ideal for developers who need real-time video pipelines or streaming capabilities. But it may not be a fit for applications requiring easy embedding or interactive UIs. &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;comparison-to-imgly-3&quot;&gt;&lt;strong&gt;Comparison to IMG.LY&lt;/strong&gt; &lt;/h3&gt;
&lt;p&gt;GStreamer operates at the infrastructure level, ideal for backend media processing where you need precise control over data flow and performance. It gives you the flexibility to build custom video pipelines, but doing so requires significant technical effort and time. &lt;/p&gt;
&lt;p&gt;IMG.LY provides a ready-to-embed, interactive editor with automation and multi-platform support, so you can focus on building user experiences rather than managing low-level media infrastructure.&lt;/p&gt;
&lt;h2 id=&quot;5-remotion&quot;&gt;&lt;strong&gt;5. Remotion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Remotion enables developers to create videos programmatically using React components. Developers can define video scenes, transitions, and animations directly in React. While it’s a flexible approach, building long or high-resolution videos can demand careful optimization to ensure smooth performance.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; It supports timeline-based video composition, text overlays, animations, audio integration, and programmatic transitions, all rendered through React. Developers can create videos entirely with code, defining scenes and effects inside React components.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platforms:&lt;/strong&gt; Remotion is built for Node.js and browser-based environments via headless rendering. You can render videos directly in the browser or on a Node.js server, which gives developers flexibility in how they deploy and automate video creation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building difficulty &amp;#x26; potential roadblocks:&lt;/strong&gt; Building difficulty using Remotion is at a medium level because it requires React and JavaScript proficiency. The potential issues you might face while using this include debugging challenges with high-resolution or long-duration renders, along with limited server-side optimization that can affect scalability and performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; Remotion is well-suited for automated video generation, marketing content, and dynamic SaaS video templates. You can use it to create personalized videos or promotional content at scale, using data or user inputs to generate customized output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proofing, support &amp;#x26; pricing:&lt;/strong&gt; The tool is actively maintained and is built with a modern web stack using React and TypeScript, which ensures long-term stability and adaptability. You can find help through detailed documentation, GitHub issues, and an engaged developer community. While it doesn’t offer formal support, its open-source nature encourages collaboration and contributions that keep the framework improving. Like other tools we’ve discussed, this is also free and open-source, making it an accessible choice for developers exploring programmatic video creation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; Based on its features and capabilities, it’s best for React developers who want to generate videos programmatically. However, it lacks an interactive editor and may not scale easily for enterprise automation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;comparison-to-imgly-4&quot;&gt;&lt;strong&gt;Comparison to IMG.LY&lt;/strong&gt; &lt;/h3&gt;
&lt;p&gt;Remotion excels in programmatic video creation, allowing you to build videos entirely through code with precision and flexibility. However, it lacks interactive editing tools or native SDKs that can be directly embedded into products. &lt;/p&gt;
&lt;p&gt;IMG.LY CE.SDK, by comparison, gives you both automation capabilities and user-facing editors across platforms, helping teams build complete video experiences without maintaining separate systems. You can find more information on &lt;a href=&quot;https://img.ly/remotion-alternative&quot;&gt;how IMG.LY compares to Remotion here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;6-imgly-cesdk&quot;&gt;&lt;strong&gt;6. IMG.LY CE.SDK&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;A commercial solution that offers enterprise-grade functionality and developer-friendly implementation.&lt;/p&gt;
&lt;p&gt;IMG.LY CreativeEditor SDK is built for interactive video editing and automation. It gives developers the tools to build powerful, embeddable video editors without the complexity of starting from scratch. It balances the flexibility developers expect from open-source frameworks with the stability and support of a commercial-grade platform.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; It includes timeline editing, multi-layer video composition, templates, AI-assisted editing, transitions, video export, and server-side automation. The SDK simplifies complex workflows by offering prebuilt editors and APIs for integration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platforms:&lt;/strong&gt; Available on Web, iOS, Android, React Native, Flutter, Node.js, and Electron. This broad platform support allows developers to build consistent video editing experiences across desktop, mobile, and web environments. Whether you’re integrating into an existing app or launching a new product, the IMG.LY CE SDK ensures a unified editing interface and workflow across all platforms.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building difficulty &amp;#x26; potential roadblocks:&lt;/strong&gt; Integration is straightforward, with minimal setup required, making it the easiest SDK to build with among all the tools we compared in this list. Most implementation effort lies in customizing workflows rather than solving technical barriers. This simplicity comes from well-documented APIs, prebuilt UI components, and consistent cross-platform behavior, which together reduce the development time. Potential roadblocks are minimal, allowing you to focus on building product features instead of managing infrastructure or compatibility issues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use cases:&lt;/strong&gt; IMG.LY is best suited for SaaS apps, marketing automation, social content tools, and video personalization platforms that need seamless interactive editing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proofing, support &amp;#x26; pricing:&lt;/strong&gt; &lt;a href=&quot;https://img.ly/whats-new&quot;&gt;Frequent releases&lt;/a&gt;, an expanding AI roadmap, and a scalable engine ensure long-term reliability for developers and enterprises. You get access to dedicated onboarding engineers, solution architects, and enterprise SLAs that make implementation and scaling easier. Pricing follows a custom enterprise licensing model, offering flexibility for different business needs. But you can &lt;a href=&quot;https://img.ly/forms/free-trial&quot;&gt;take a free trial to get started.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who it’s for: I&lt;/strong&gt;MG.LY is designed for companies that need scalable, interactive video editing and automation in one package. Its ideal for teams seeking low development overhead and enterprise-grade reliability.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;why-imgly-stands-out-as-the-best-open-source-video-editor-sdk&quot;&gt;&lt;strong&gt;Why IMG.LY stands out as the best open source video editor SDK&lt;/strong&gt; &lt;/h3&gt;
&lt;p&gt;IMG.LY combines interactive editing, server-side automation, and multi-platform SDKs in one stack, giving you everything needed to build scalable, modern video products. You can create, edit, and automate workflows within the same ecosystem without relying on separate tools. None of the open-source options on this list deliver this level of integration and consistency across web, mobile, and desktop environments.&lt;/p&gt;
&lt;p&gt;Check out how IMG.LY has helped over 600 innovative startups, government entities, and Fortune 500 companies to streamline their design, video, and photo editing workflows. &lt;a href=&quot;https://img.ly/case-studies&quot;&gt;Read our case studies here.&lt;/a&gt; &lt;/p&gt;
&lt;h2 id=&quot;overview-table&quot;&gt;&lt;strong&gt;Overview table&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Here’s a brief overview of all the video editor SDKs we’ve discussed to help you choose the right one. &lt;/p&gt;

















































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature / Use Case&lt;/th&gt;&lt;th&gt;&lt;strong&gt;FFmpeg&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;MoviePy&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;OpenShot / MLT&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;GStreamer&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Remotion&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;IMG.LY CE.SDK&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Timeline editing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;❌ No GUI timeline; timeline-like operations only possible via scripting in CLI.&lt;/td&gt;&lt;td&gt;⚠️ Timeline functionality simulated through Python scripts; suitable for small-scale projects.&lt;/td&gt;&lt;td&gt;✅ Native timeline-based video editing with GUI; library supports composition though GUI integration can be limited.&lt;/td&gt;&lt;td&gt;⚠️ Pipeline-centric; timeline must be assembled programmatically, no native GUI timeline.&lt;/td&gt;&lt;td&gt;✅ Timeline created programmatically using React components; no interactive GUI timeline.&lt;/td&gt;&lt;td&gt;✅ Full-featured interactive timeline, multi-layer support, drag-and-drop UI&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Filters &amp;#x26; Effects&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Supports CLI-based filters, overlays, color correction; requires manual configuration&lt;/td&gt;&lt;td&gt;✅ Python effects library; scripting needed to combine filters&lt;/td&gt;&lt;td&gt;✅ Built-in video effects and transitions; limited prebuilt UI&lt;/td&gt;&lt;td&gt;✅ Plugin-based filters; flexible but requires pipeline setup&lt;/td&gt;&lt;td&gt;✅ Animations, text overlays, audio effects via scripting; programmatic transitions&lt;/td&gt;&lt;td&gt;✅ AI-enhanced effects, transitions, multi-layer composition, background removal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Server-side automation&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Excellent for backend batch processing and transcoding; CLI automation is robust&lt;/td&gt;&lt;td&gt;✅ Python scripting enables automated content generation&lt;/td&gt;&lt;td&gt;⚠️ Limited server-side automation; mainly library-level&lt;/td&gt;&lt;td&gt;✅ Suitable for large-scale pipelines and streaming&lt;/td&gt;&lt;td&gt;✅ Automated video rendering via Node.js; works with server-side scripts&lt;/td&gt;&lt;td&gt;✅ Full automation APIs; combines server-side rendering + interactive editing in one SDK&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Ease of embedding&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;❌ CLI only; difficult to embed in apps&lt;/td&gt;&lt;td&gt;⚠️ Python scripts can be integrated, but no GUI&lt;/td&gt;&lt;td&gt;⚠️ Library-only; integration requires custom UI&lt;/td&gt;&lt;td&gt;⚠️ Complex pipelines; requires deep development knowledge&lt;/td&gt;&lt;td&gt;⚠️ Node.js / headless browser integration possible; UI must be custom-built&lt;/td&gt;&lt;td&gt;✅ Ready-to-embed SDKs for Web, iOS, Android, React Native, Flutter; includes prebuilt editors&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Difficulty building / integration&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;High — complex CLI usage, codec handling, and scripting required&lt;/td&gt;&lt;td&gt;Medium — Python knowledge required, scripting-intensive&lt;/td&gt;&lt;td&gt;Medium-High — API can be unstable, dependencies must be managed&lt;/td&gt;&lt;td&gt;High — pipeline setup and plugin management are challenging&lt;/td&gt;&lt;td&gt;Medium — React knowledge needed; performance optimization may be required&lt;/td&gt;&lt;td&gt;Low — SDK provides prebuilt editor components and APIs for easy integration&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Potential roadblocks&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;CLI complexity, codec licensing (H.264), debugging pipelines, no GUI&lt;/td&gt;&lt;td&gt;Large videos may be slow, performance issues, dependency management&lt;/td&gt;&lt;td&gt;API instability, documentation gaps, integration with UI requires effort&lt;/td&gt;&lt;td&gt;Steep learning curve, pipeline debugging, plugin version conflicts&lt;/td&gt;&lt;td&gt;Rendering performance for long/high-resolution videos, debugging programmatic scripts&lt;/td&gt;&lt;td&gt;Minimal; most challenges relate to workflow decisions during integration&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Cross-platform support&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Desktop/server; Windows, macOS, Linux&lt;/td&gt;&lt;td&gt;✅ Desktop/server; cross-platform Python&lt;/td&gt;&lt;td&gt;✅ Desktop/server; cross-platform&lt;/td&gt;&lt;td&gt;✅ Desktop/server; cross-platform&lt;/td&gt;&lt;td&gt;✅ Node.js + headless browser; works across server environments&lt;/td&gt;&lt;td&gt;✅ Web + mobile + desktop; consistent UI across platforms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;AI / Automation&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;❌ None&lt;/td&gt;&lt;td&gt;⚠️ Programmatic automation via scripting&lt;/td&gt;&lt;td&gt;✅ AI-assisted editing, automation workflows, plugin ecosystem&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✅ Excellent for batch and server pipelines&lt;/td&gt;&lt;td&gt;⚠️ Limited; performance depends on scripting and hardware&lt;/td&gt;&lt;td&gt;⚠️ Medium; suitable for desktop-scale apps&lt;/td&gt;&lt;td&gt;✅ Large-scale pipelines, real-time streaming&lt;/td&gt;&lt;td&gt;✅ Programmatic generation can scale, but may need server resources&lt;/td&gt;&lt;td&gt;✅ Enterprise-grade; cloud-ready, multi-platform, high-volume video workflows&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pricing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Free, OSS; H.264 encoding may require commercial license&lt;/td&gt;&lt;td&gt;Free, OSS&lt;/td&gt;&lt;td&gt;Free, OSS&lt;/td&gt;&lt;td&gt;Free, OSS&lt;/td&gt;&lt;td&gt;Free, OSS&lt;/td&gt;&lt;td&gt;Custom enterprise licensing&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Developers building automation pipelines, server-side video processing, or streaming workflows&lt;/td&gt;&lt;td&gt;Python developers building scripted video content and automation&lt;/td&gt;&lt;td&gt;Developers building desktop-focused video apps with timeline editing&lt;/td&gt;&lt;td&gt;Developers needing real-time pipelines or advanced streaming&lt;/td&gt;&lt;td&gt;Developers using React for programmatic video generation and templating&lt;/td&gt;&lt;td&gt;Companies needing interactive, embedded video editing + AI automation + multi-platform SDK&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;choosing-the-right-video-sdk-how-to-make-the-right-choice&quot;&gt;&lt;strong&gt;Choosing the right video SDK: How to make the right choice&lt;/strong&gt; &lt;/h2&gt;
&lt;p&gt;When choosing the right video SDK, the best option depends on what you’re building and who it’s for.&lt;/p&gt;
&lt;p&gt;Choose open-source SDKs like FFmpeg, MoviePy, OpenShot/MLT, GStreamer, and Remotion if you prefer flexibility and complete control. These tools are free, customizable, and well-suited for automation, research, or proof-of-concept projects. However, they often require significant development time, scripting knowledge, and ongoing maintenance, which can slow down production or scaling.&lt;/p&gt;
&lt;p&gt;For teams building commercial or enterprise-ready video products, commercial SDKs offer a more practical route. They save you time on integration, provide dedicated support, and come with consistent updates to ensure reliability across platforms.&lt;/p&gt;
&lt;p&gt;That’s why developers choose IMG.LY SDK.&lt;/p&gt;
&lt;p&gt;It combines interactive editing, automation, and cross-platform SDKs in a single stack, something open-source solutions can’t fully replicate. It’s designed for SaaS, social, and enterprise use cases where scalability, ease of use, and performance matter most. You can embed editors, automate workflows, and scale confidently without managing multiple systems.&lt;/p&gt;
&lt;p&gt;So if you want a complete, production-ready platform with AI features, automation, and an intuitive editing experience, IMG.LY is the right choice. &lt;/p&gt;
&lt;p&gt;Get in touch with our team to see how it’s deployed in over 500 applications and used by millions of users across 29 countries. &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/forms/free-trial&quot;&gt;Start a free trial&lt;/a&gt; or &lt;a href=&quot;https://img.ly/forms/contact-sales&quot;&gt;book your call today&lt;/a&gt;!&lt;/p&gt;</content:encoded><dc:creator>Vatsala</dc:creator><media:content url="https://blog.img.ly/2025/11/open-source-video-editor-sdk-whitelabel-best-comparison--1-.jpg" medium="image"/><category>Video Editing</category><category>Video Editor</category><category>OpenSource</category><category>Insights</category></item><item><title>The Top 7 Video Editing SDKs in 2026</title><link>https://img.ly/blog/top-7-video-editing-sdks-in-2025/</link><guid isPermaLink="true">https://img.ly/blog/top-7-video-editing-sdks-in-2025/</guid><description>In this guide, we break down the seven leading video editing SDK solutions: IMG.LY, Meishe, Banuba, Shotstack, BytePlus, Rendley, and Picsart, covering their features, platforms, use cases, and trade-offs. </description><pubDate>Tue, 02 Sep 2025 11:19:08 GMT</pubDate><content:encoded>&lt;p&gt;With dozens of video editing SDKs on the market, choosing the right one can feel like a daunting task.&lt;/p&gt;
&lt;p&gt;To help you cut through the noise, we’ve put together a breakdown of the &lt;strong&gt;7 best video editing SDKs in 2026:&lt;/strong&gt; IMG.LY, Meishe SDK, Banuba, Shotstack, BytePlus Effects, Rendley, and Picsart. We’ll cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Key features and capabilities&lt;/li&gt;
&lt;li&gt;Supported platforms and customization options&lt;/li&gt;
&lt;li&gt;Ideal use cases and trade-offs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This guide is unbiased, but we’ll also highlight how IMG.LY compares and where it stands out as the only solution that combines a polished editor with scalable automation in a single package.&lt;/p&gt;
&lt;h2 id=&quot;1-imgly-creativeeditor-sdk-cesdk&quot;&gt;&lt;strong&gt;1. IMG.LY CreativeEditor SDK (CE.SDK)&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Choosing IMG.LY means selecting a platform that offers both: a Canva-grade editor for your users and a powerful Engine API for automation. That dual focus is what sets CE.SDK apart.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; CE.SDK works best when you see it as a bridge between what end users expect and what your product team needs behind the scenes. On the surface, users get familiar tools including multi‑track editing, ready‑made templates, and a growing set of AI features like text‑to‑image, text‑to‑video, and AI voiceovers. Behind the scenes, developers can extend and customise with a plugin system so the editor adapts as your product evolves.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platforms &amp;#x26; customization:&lt;/strong&gt; This flexibility carries over to platforms. CE.SDK works across Web, iOS, Android, React Native, Flutter, Electron, and Node.js. It’s also fully white‑label, which means your customers see a seamless extension of your brand, not a third‑party tool.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation &amp;#x26; use cases:&lt;/strong&gt; Getting started with our tool doesn’t require a huge lift. Teams can spin up a proof of concept quickly, then scale into enterprise deployment when ready. That’s why you’ll see CE.SDK inside SaaS platforms, e‑commerce personalization tools, DAM systems, and even social networks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future‑proofing, support &amp;#x26; pricing&lt;/strong&gt;: What reassures teams is the long‑term roadmap: regular feature releases, AI integrations, and direct support from solution engineers. Enterprise SLAs and SSO come standard. Pricing depends on the usage, which makes it easier to scale without committing to rigid licensing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; CE.SDK is valuable for SaaS, MarTech, e-commerce, and DAM platforms. These teams need to give users a simple, branded editing experience while also managing complex automation in the background. Instead of stitching together multiple tools or sacrificing one capability for another, CE.SDK provides an all-in-one foundation: polished editing, scalable automation, enterprise-grade support, and ongoing AI-driven innovation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;key-differentiator&quot;&gt;&lt;strong&gt;Key differentiator&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;CE.SDK doesn’t force you to choose between usability and power. On one side, it delivers a polished, user-facing editor that feels familiar to end users. On the other hand, it provides a powerful automation engine that scales with your product. Most SDKs lean heavily in one direction. They either focus on end-user editing or specialize in backend automation. CE.SDK is different because it combines both in a single platform.&lt;/p&gt;
&lt;h2 id=&quot;2-meishe-sdk-meicam&quot;&gt;&lt;strong&gt;2. Meishe SDK (Meicam)&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Meishe SDK, also known as Meicam, is a mature Chinese SDK that has carved out a space in many professional apps across Asia. Think of it as a toolkit built for industries that need stability and advanced editing power, though it comes with a few trade‑offs that teams should weigh carefully.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; Meishe offers multi‑track timelines, real‑time effects, and plugin support across mobile, web, and PC. Industries like automotive, broadcasting, and education have already used Meishe successfully, showing how it handles complex and demanding video workflows.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platforms &amp;#x26; customization:&lt;/strong&gt; It supports full UI customization, white‑labeling, and plugins. And while customization depth is solid, integration tends to be heavier compared to other tools. Documentation can feel dense, which sometimes slows teams down as they work toward launch.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation &amp;#x26; use cases:&lt;/strong&gt; Meishe SDK is beginning to layer in AI integrations like intelligent editing and motion tracking. For large organizations in Asia with strong internal dev resources, these capabilities can be appealing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future‑proofing, support &amp;#x26; pricing:&lt;/strong&gt; Meishe continues to expand with new AI features like facial recognition and virtual anchors. It also offers custom enterprise support agreements. However, teams often struggle with the integration process, and the developer experience feels less polished. Setting up complex projects can take longer, and the documentation isn’t as approachable, which leaves some developers hesitant to adopt it widely. Pricing typically follows an enterprise licensing model, which can be less flexible for fast‑scaling SaaS companies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; Meishe SDK is best suited for large-scale apps in Asia and companies with internal dev resources.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly&quot;&gt;&lt;strong&gt;How it compares to IMG.LY&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Meishe delivers solid editing capabilities and is a proven choice in professional and regional contexts. But the trade‑offs become clear when you look at integration and support. It can feel heavy to implement, and documentation isn’t as approachable.&lt;/p&gt;
&lt;p&gt;IMG.LY pulls ahead here with stronger web support, compatibility with creative file types like PSD, AI, and INDD, and a faster onboarding process that makes it easier for teams to move from idea to production.&lt;/p&gt;
&lt;p&gt;Learn more about how &lt;a href=&quot;https://img.ly/meishesdk-alternative&quot;&gt;IMG.LY compares to Meishe SDK here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;3-banuba&quot;&gt;&lt;strong&gt;3. Banuba&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Banuba is a mobile‑first SDK with a strong focus on augmented reality (AR). It has built its reputation on powering social and UGC apps with effects that mimic the TikTok experience. If your product relies on immersive filters, beauty effects, or virtual try‑on, Banuba often appears at the top of the evaluation list.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; The SDK provides a TikTok‑like editor with AR masks, beauty filters, face tracking, background removal, and even virtual try‑on features. These tools are designed to keep users engaged with interactive and shareable content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platforms &amp;#x26; customization:&lt;/strong&gt; Banuba supports iOS, Android, Flutter, and React Native. It offers modular components with a preset UI, which makes implementation faster for mobile. That said, customization options are limited when compared to solutions designed for enterprise-level flexibility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation &amp;#x26; use cases:&lt;/strong&gt; Integration is relatively quick for mobile teams, and the SDK has proven popular among social media platforms, beauty apps, and e‑commerce companies offering AR try‑on. However, support for web or large‑scale enterprise environments is limited, which narrows its scope.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future‑proofing, support &amp;#x26; pricing:&lt;/strong&gt; The company continues to expand its AR and AI features, focusing on personalization and beauty‑driven effects. Banuba operates with a smaller team of about 70 employees, which can affect the pace of enterprise‑grade support. Licensing costs are typically high and not publicly disclosed, which may be a barrier for smaller companies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; Banuba is best suited for mobile apps that need advanced AR features like beauty filters, face tracking, or virtual try‑on to keep users engaged.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-1&quot;&gt;&lt;strong&gt;How it compares to IMG.LY&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Banuba leads when it comes to AR‑driven capabilities, making it a natural fit for beauty and social platforms. But when teams look beyond filters to enterprise readiness, automation, and cross‑platform support, other options such as IMG.LY offer broader possibilities.&lt;/p&gt;
&lt;p&gt;Learn more about how &lt;a href=&quot;https://img.ly/banuba-alternative&quot;&gt;IMG.LY compares to Banuba here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;4-shotstack&quot;&gt;&lt;strong&gt;4. Shotstack&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Shotstack focuses squarely on automation. It’s a cloud‑based video editing API designed for bulk rendering rather than end‑user editing. Teams often evaluate it when they need to generate thousands of videos quickly and at scale.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; Shotstack runs on a JSON‑driven API that lets developers programmatically create and assemble video content. With this approach, teams can handle automated ad generation, personalization, or large‑scale marketing campaigns. While powerful for automation, it doesn’t include a native editor, which means you must build a custom UI if you want end‑user editing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platforms &amp;#x26; customization:&lt;/strong&gt; Shotstack is built as a REST API in the cloud, so it fits naturally into modern development stacks. It allows teams to design workflows programmatically, though the absence of prebuilt UI components makes it harder to use the tool right away as compared to other SDKs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation &amp;#x26; use cases:&lt;/strong&gt; Developers appreciate the smooth onboarding experience and clear API structure. Typical use cases include bulk rendering of ads, dynamic personalization for campaigns, and other scenarios where scaling output matters more than in‑app editing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future‑proofing, support &amp;#x26; pricing:&lt;/strong&gt; Shotstack continues to invest in automation and AI‑powered generation, offering tools that personalize video creation at scale. The vendor provides commercial SLAs, but support resources remain limited given the team size. Pricing follows a pay‑as‑you‑go model ($0.30 per minute) or subscription plans, which can work well for predictable, high‑volume usage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; Shotstack is best suited for teams that need scalable rendering pipelines and automation rather than in‑app editing features.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-2&quot;&gt;&lt;strong&gt;How it compares to IMG.LY&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Shotstack gives you powerful rendering automation and programmatic workflows. IMG.LY takes it further by combining those automation strengths with a complete, user‑facing editor, so you can address both your development needs and your end‑users’ experiences in one solution.&lt;/p&gt;
&lt;p&gt;Get a detailed &lt;a href=&quot;https://img.ly/shotstack-alternative&quot;&gt;comparison of IMG.LY CreativeEditor SDK and Shotstack&lt;/a&gt; here.&lt;/p&gt;
&lt;h2 id=&quot;5-byteplus-effects&quot;&gt;&lt;strong&gt;5. BytePlus Effects&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;BytePlus Effects is modelled after TikTok and CapCut. It’s designed to give app developers the same kind of short‑form, social‑first experience that has made those platforms successful. As a result, it appeals to teams that want to replicate TikTok‑like engagement inside their own apps.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; The SDK offers more than 80,000 effects and filters, including AR stickers and beautification tools. These features aim to keep users engaged by giving them endless ways to personalize and enhance their content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platforms &amp;#x26; customization:&lt;/strong&gt; BytePlus integrates with iOS, Android, React Native, and Flutter, making it a strong option for mobile‑first development. You can customise the UI to match your brand, but customization beyond theming is limited, which can be a constraint if you need deeper control.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation &amp;#x26; use cases:&lt;/strong&gt; Since it’s optimized for mobile integration, you can embed it relatively quickly into short‑form consumer video apps. Common use cases include social platforms, beauty apps, and any consumer‑facing product that thrives on AR‑enhanced video.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future‑proofing, support &amp;#x26; pricing:&lt;/strong&gt; With the backing of TikTok’s ecosystem, BytePlus is evolving rapidly, adding new AI‑driven AR and beauty effects frequently. However, commercial support feels less transparent, and licensing comes through enterprise negotiations with annual fees. This structure can work for large consumer platforms, but may be harder for smaller teams.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; BytePlus is best suited for apps that want to recreate TikTok‑style user experiences and rely heavily on prebuilt AR effects to keep users engaged.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-3&quot;&gt;&lt;strong&gt;How it compares to IMG.LY&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;BytePlus takes a step ahead when it comes to prebuilt effects and AR‑driven experiences. But if you need more flexibility in customization, automation capabilities, or enterprise‑grade workflows, IMG.LY offers a broader solution.&lt;/p&gt;
&lt;p&gt;For a detailed comparison, take a look at our guide on &lt;a href=&quot;https://img.ly/byteplus-alternative&quot;&gt;IMG.LY vs BytePlus Video Editor.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;6-rendley&quot;&gt;&lt;strong&gt;6. Rendley&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Rendley is a newer player in the SDK space and has gained attention because of its browser‑only approach. It’s JavaScript‑based and runs entirely in the browser, which means you don’t need a server to get started. This makes it attractive for teams that want a lightweight, client‑only setup without managing infrastructure.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; The SDK supports multi‑track editing, keyframes, and even integrates with After Effects (AE). These features give frontend developers enough flexibility to build interactive editing experiences directly in the browser.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platforms &amp;#x26; customization:&lt;/strong&gt; Rendley runs entirely in the browser, which makes it a natural fit for lightweight web apps and UGC platforms. Developers get flexibility through an open, in‑browser approach. However, without enterprise‑level frameworks, scaling to larger organizations becomes more difficult.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation &amp;#x26; use cases:&lt;/strong&gt; Setting up Rendley is straightforward for frontend teams, which makes it appealing for lightweight UGC applications or smaller web projects. That ease of entry, however, comes with limits: AI integrations aren’t a core focus, so its potential for more advanced future applications remains restricted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future‑proofing, support &amp;#x26; pricing:&lt;/strong&gt; Rendley is still early‑stage and hasn’t yet proven itself at enterprise scale. Support is provided by a small vendor team, which can make long‑term stability less certain. Pricing details are not publicly available, leaving prospective users to negotiate directly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; Rendley fits developers who want a browser‑native, client‑only editing tool without the need for server infrastructure.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-4&quot;&gt;&lt;strong&gt;How it compares to IMG.LY&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Rendley works well as a lightweight, browser‑native solution. But if you need enterprise‑grade robustness, automation, or dedicated support, IMG.LY offers more comprehensive coverage.&lt;/p&gt;
&lt;p&gt;Learn more about how &lt;a href=&quot;https://img.ly/rendley-alternative&quot;&gt;IMG.LY is a great alternative for Rendley&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;7-picsart-video-sdk&quot;&gt;&lt;strong&gt;7. Picsart Video SDK&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Picsart Video SDK is an embeddable video editor SDK that brings Picsart’s creative editing tools into third-party apps or websites.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Features &amp;#x26; capabilities:&lt;/strong&gt; This SDK brings the company’s well‑known creative editing tools into third‑party products. Out of the box, you get features like trimming, multi‑scene editing, transitions, dynamic audio, subtitles, and text overlays, enough to cover the basics of video creation. AI‑driven tools extend these capabilities with smarter image and video editing options.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platforms &amp;#x26; customization:&lt;/strong&gt; The SDK is React Native‑based but optimized for web embedding, making it appealing for web‑first platforms. You can configure the UI, apply theming, white‑label the experience, toggle features on or off, and integrate your own asset library so the editor matches your product’s design and workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation &amp;#x26; use cases:&lt;/strong&gt; One of Picsart’s strengths is ease of setup: installation is fast, with a React editor installation process that reduces complexity, documentation is detailed, and the editor is designed to embed with minimal lift. This makes it a good choice for advertising or marketing platforms, edu‑tech products, and media platforms that want to give users creative tools quickly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future‑proofing, support &amp;#x26; pricing:&lt;/strong&gt; The SDK is backed by Picsart’s large ecosystem and its AI research arm (PAIR), so teams can expect regular updates, new features, and scalable performance. Support comes through developer documentation, a support team, and enterprise collaboration options. Pricing isn’t public, but it’s likely offered as enterprise or usage‑based licensing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Who it’s for:&lt;/strong&gt; Picsart’s Video SDK is best for teams that need a web‑based video editor to power product features or educational video production without investing heavily in custom development.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-it-compares-to-imgly-5&quot;&gt;&lt;strong&gt;How it compares to IMG.LY&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Picsart offers a fast, embeddable editor with AI effects and a strong ecosystem. However, IMG.LY provides deeper customization, more automation capabilities, cross‑platform support, and enterprise‑grade integrations.&lt;/p&gt;
&lt;h2 id=&quot;overview-table-use-cases-vs-solutions&quot;&gt;&lt;strong&gt;Overview Table (Use Cases vs. Solutions)&lt;/strong&gt;&lt;/h2&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;When you line these SDKs up side by side, it’s clear that each one has its own niche strengths and limitations. Here’s a quick overview:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Banuba / BytePlus:&lt;/strong&gt; These are the strongest options for AR and social apps, with beauty filters, effects, and TikTok-like workflows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meishe:&lt;/strong&gt; A professional, Asia-centric SDK with heavy native capabilities, but a steeper implementation curve.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shotstack / Rendley:&lt;/strong&gt; Both shine in automation pipelines or lightweight browser-based setups, but they don’t offer polished editor UIs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Picsart:&lt;/strong&gt; A strong web-first, prebuilt editor with AI effects that’s simple to embed, though limited in customization and automation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;where-does-that-leave-you&quot;&gt;Where does that leave you?&lt;/h3&gt;
&lt;p&gt;If you’re evaluating SDKs, you need to balance two priorities: delivering a great editor UX for your users and scaling automation behind the scenes. Only IMG.LY covers both ends: offering a polished, enterprise-ready editor and a scalable automation engine.&lt;/p&gt;
&lt;p&gt;That makes it the go-to option for teams planning not only their current projects but also long-term growth. With IMG.LY, you can give users a polished editing experience today while building the automation backbone that will let your product scale tomorrow&lt;/p&gt;
&lt;p&gt;If you’d like to see how IMG.LY can fit into your platform, &lt;a href=&quot;https://img.ly/forms/contact-sales&quot;&gt;get in touch with our experts today&lt;/a&gt; for a deeper look and tailored guidance.&lt;/p&gt;</content:encoded><dc:creator>Jan</dc:creator><media:content url="https://blog.img.ly/2025/09/top-video-editor-sdks-in-2025--1-.png" medium="image"/><category>Video Editor</category><category>Insights</category></item><item><title>A Modern JavaScript Video Editor: Integration Guide</title><link>https://img.ly/blog/a-modern-javascript-video-editor-integration-guide/</link><guid isPermaLink="true">https://img.ly/blog/a-modern-javascript-video-editor-integration-guide/</guid><description>Learn how to integrate IMG.LY&apos;s Javascript video editor into your web app and how to best leverage its capabilities.</description><pubDate>Thu, 16 Jan 2025 15:29:04 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Discover how to integrate&lt;/em&gt; &lt;a href=&quot;https://img.ly/docs/cesdk/js/starterkits/video-editor-e1nlor/&quot;&gt;&lt;em&gt;IMG.LY’s JavaScript video editor&lt;/em&gt;&lt;/a&gt; &lt;em&gt;into your web application and unlock its full range of features.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Video content has always been a powerhouse for engagement, becoming even more impactful with the rise of short-form videos. Platforms like YouTube and TikTok have built their empires on video content, as that remains the preferred medium for both creating and consuming information.&lt;/p&gt;
&lt;p&gt;Not only have those platforms changed how we consume information, but they have also transformed user behavior. We do not just want to watch videos—we want to create them, expecting the process to be both simple and professional.&lt;/p&gt;
&lt;p&gt;Here is why embedding video creation and editing capabilities directly into your website, web or mobile application can significantly boost user engagement and satisfaction.&lt;/p&gt;
&lt;p&gt;In this guide, you will learn how to integrate a JavaScript video editor using CreativeEditor SDK (CE.SDK). We will explore when it is most useful and what customizations it supports to suit your unique needs.&lt;/p&gt;
&lt;p&gt;Want to jump into the code? For a quick start, visit our &lt;a href=&quot;https://github.com/imgly/cesdk-web-examples/tree/main/integrate-with-vanilla-js&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let’s dive in!&lt;/p&gt;
&lt;h2 id=&quot;why-does-your-javascript-web-app-need-a-video-editor&quot;&gt;Why Does Your JavaScript Web App Need a Video Editor?&lt;/h2&gt;
&lt;p&gt;The world of content is constantly evolving—from text to images, from static visuals to long-form videos, and now from long videos to bite-sized clips. What stays consistent is that &lt;a href=&quot;https://www.idomoo.com/blog/surprising-video-engagement-statistics/&quot;&gt;video content resonates deeply with us as humans&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No wonder, &lt;a href=&quot;https://www.statista.com/statistics/1285960/top-downloaded-mobile-apps-worldwide/&quot;&gt;TikTok tops global app download charts&lt;/a&gt;, while &lt;a href=&quot;https://www.similarweb.com/top-websites/&quot;&gt;YouTube, Facebook, and Instagram rank among the most visited sites&lt;/a&gt; right after Google. These platforms have not just built their empires on video—they have revolutionized how we think about video production.&lt;/p&gt;
&lt;p&gt;They set the gold standard by enabling anyone to create professional-looking videos with minimal effort, offering tools for adding filters, overlays, audio, and text in just a few clicks. This ease of use has made intuitive video editing a must-have for web applications featuring social media integration, marketing ambitions, or content management capabilities.&lt;/p&gt;
&lt;p&gt;By embedding a user-friendly JavaScript video editor in your application, you can ride this trend, providing a feature billions of users are already familiar with. The payoff? Lower barriers to user-generated content, enhanced engagement, and wider content distribution.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CreativeEditor SDK&lt;/a&gt; from &lt;a href=&quot;https://IMG.LY&quot;&gt;IMG.LY&lt;/a&gt; delivers a seamless, high-performance, and feature-rich JavaScript solution for in-browser design, video, and photo editing—ready to meet your users’ expectations.&lt;/p&gt;
&lt;h2 id=&quot;getting-started-adding-a-video-editor-in-javascript&quot;&gt;Getting Started: Adding a Video Editor in JavaScript&lt;/h2&gt;
&lt;p&gt;Follow this step-by-step guide to learn how to integrate a JavaScript video editor into your site using CreativeEditor SDK.&lt;/p&gt;
&lt;p&gt;Get started with integrating CE.SDK in a vanilla JavaScript application!&lt;/p&gt;
&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK runs directly in your browser’s JavaScript engine, so no specific prerequisites are needed.&lt;/p&gt;
&lt;p&gt;If your web application relies on Node.js, ensure that you have the &lt;a href=&quot;https://nodejs.org/en/download&quot;&gt;latest stable versions of Node.js and NPM installed&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;installation-and-library-import&quot;&gt;Installation and Library Import&lt;/h3&gt;
&lt;p&gt;In a vanilla JavaScript application, create a JavaScript module file (e.g., video-editor.js) and import the CreativeEditorSDK library:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;&amp;#x3C;https://cdn.img.ly/packages/imgly/cesdk-js/1.42.0/index.js&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In this example, the SDK is served from our CDN for convenience. In a production environment, you should &lt;a href=&quot;https://img.ly/docs/cesdk/js/serve-assets-b0827c/&quot;&gt;host assets on your own servers&lt;/a&gt; for improved control and performance.&lt;/p&gt;
&lt;p&gt;Alternatively, if you are using a bundler like Webpack, Rollup, Parcel, or Vite, and you want to integrate the CreativeEditor module within your existing project, simply add the &lt;a href=&quot;https://www.npmjs.com/package/@cesdk/cesdk-js&quot;&gt;@cesdk/cesdk-js&lt;/a&gt; npm package as a dependency to your project:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; [@cesdk/cesdk-js](&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;https://www.npmjs.com/package/@cesdk/cesdk-js&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can then import it as below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; &quot;@cesdk/cesdk-js&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Well done!&lt;/p&gt;
&lt;h3 id=&quot;initialize-the-video-editor&quot;&gt;Initialize the Video Editor&lt;/h3&gt;
&lt;p&gt;In your JavaScript module, right below the library import, initialize CreativeEditor SDK with the following logic:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// src/video-editor.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;&amp;#x3C;https://cdn.img.ly/packages/imgly/cesdk-js/1.42.0/index.js&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// your CE.SDK license and user configs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  license: &lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;YOUR_LICENSE&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  userId: &lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;YOUR_USER_ID&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;CreativeEditorSDK.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;#cesdk_container&apos;&lt;/span&gt;&lt;span&gt;, config).&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;editor&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // do something with your instance of CreativeEditor SDK...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // when done, clean up and free up resources&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  editor.&lt;/span&gt;&lt;span&gt;dispose&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;#x3C;YOUR_LICENSE&gt;&lt;/code&gt; with the license key you get from CreativeEditor SDK and &lt;code&gt;&amp;#x3C;YOUR_USER_ID&gt;&lt;/code&gt; with your user ID. The user ID is optional and helps track MAUs (Monthly Active Users) across different devices.&lt;/p&gt;
&lt;p&gt;To integrate the video-editor.js file, import it into your HTML page like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;module&quot;&lt;/span&gt;&lt;span&gt; src&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;video-editor.js&quot;&lt;/span&gt;&lt;span&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules&quot;&gt;type=“module”&lt;/a&gt; attribute. This tells the browser to treat the script as an ES6 module, so that you can use import and export statements within your JavaScript code.&lt;/p&gt;
&lt;p&gt;Make sure the same HTML page includes the following div element where the video editor will be embedded:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;cesdk_container&quot;&lt;/span&gt;&lt;span&gt; style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;width: 100%; height: 100vh;&quot;&lt;/span&gt;&lt;span&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will load the video editor with the default video preset, giving users the ability to trim, cut, apply filters, add text overlays, include music, and more to enhance their videos.&lt;/p&gt;
&lt;p&gt;Congratulations, you have successfully integrated the video editor!&lt;/p&gt;
&lt;h2 id=&quot;creativeeditor-sdk-javascript-video-editing-api-for-web-desktop-and-mobile&quot;&gt;CreativeEditor SDK: JavaScript Video Editing API for Web, Desktop, and Mobile&lt;/h2&gt;
&lt;p&gt;You just saw how to integrate the CE.SDK into a browser application. Yet, do not forget that the SDK supports a wide variety of frameworks and libraries—including mobile and web applications.&lt;/p&gt;
&lt;h3 id=&quot;web-framework-support&quot;&gt;Web Framework Support&lt;/h3&gt;
&lt;p&gt;CE.SDK is designed to work with several popular JavaScript frameworks and libraries. For more detailed integration instructions, take a look at the official page on the documentation for each framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/react/get-started/overview-e18f40/&quot;&gt;React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/angular/get-started/overview-e18f40/&quot;&gt;Angular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/vue/get-started/overview-e18f40/&quot;&gt;Vue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/svelte/get-started/overview-e18f40/&quot;&gt;Svelte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/js/get-started/overview-e18f40/&quot;&gt;JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, the SDK is available for headless mode and works well in a &lt;a href=&quot;https://img.ly/docs/cesdk/node/get-started/overview-e18f40/&quot;&gt;Node.js environment&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;cross-platform-support&quot;&gt;Cross-Platform Support&lt;/h3&gt;
&lt;p&gt;One of the standout features of CreativeEditor SDK is its cross-platform philosophy. This extends beyond JavaScript ecosystems for the web, and includes mobile (iOS and Android) and desktop, thanks to support for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/react-native/get-started/overview-e18f40/&quot;&gt;React Native&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/electron/get-started/overview-e18f40/&quot;&gt;Electron&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is made possible through a powerful engine that powers your app via features like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unified API&lt;/strong&gt;: The same underlying API is shared across web, desktop, iOS, and Android applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-Platform Feature Parity&lt;/strong&gt;: CE.SDK guarantees that features are available consistently across platforms. Since core functionality is implemented at the engine level, features you use on one platform will be available on others, with only slight differences in release timelines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interoperable Designs&lt;/strong&gt;: Designs created in the editor component on one platform work on all platforms supported by CE.SDK. Whether a user is designing on iOS, Android, or the web, their design files can be imported seamlessly between platforms.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Native iOS and Android libraries, along with other frameworks, are also available. &lt;a href=&quot;https://img.ly/docs/cesdk/&quot;&gt;Learn more in our documentation!&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;javascript-video-editor-use-cases&quot;&gt;JavaScript Video Editor Use Cases&lt;/h2&gt;
&lt;p&gt;It is time to explore some key use cases. Let’s see how the unique features of the CreativeEditor SDK can cover many scenarios!&lt;/p&gt;
&lt;h3 id=&quot;social-media-publishing&quot;&gt;Social Media Publishing&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK features what users need to create engaging and easy-to-share videos optimized for popular social media platforms like Instagram, TikTok, YouTube, LinkedIn, and more. This is possible due to a large set of capabilities, which include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reusable Templates&lt;/strong&gt;: Users can either design their own templates and share them with the community or download those created by others. This variety of ready-to-use templates for different scenarios helps users skip the daunting blank canvas to bring their ideas to life. Explore various templates in our &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web?template=month-in-review&amp;#x26;ref=img.ly&quot;&gt;video editor demo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music and Audio Library&lt;/strong&gt;: In CE.SDK, adding audio to videos is simple and intuitive. Given the impact of audio, users can set the tone with music or narration in just a few clicks, creating a more immersive atmosphere for their content.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Animations&lt;/strong&gt;: The SDK includes a &lt;a href=&quot;https://img.ly/docs/cesdk/js/animation/overview-6a2ef2/&quot;&gt;wide selection of animations&lt;/a&gt; to enhance the design elements positioned within video scenes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After creating a video within your web app, users can export it directly from CE.SDK in the appropriate formats and aspect ratios for their target social media platforms.&lt;/p&gt;
&lt;h3 id=&quot;product-showcase-for-e-commerce-applications&quot;&gt;Product Showcase for E-Commerce Applications&lt;/h3&gt;
&lt;p&gt;Images have long been a simple yet powerful tool for showcasing products on e-commerce platforms, and sites like eBay, Amazon, AliExpress, and Walmart have relied on them for years (and still do!).&lt;/p&gt;
&lt;p&gt;However, in recent years, customer expectations have shifted. Today’s buyers crave more interactive and immersive ways to visualize products—they want to see how items look and perform in real-world settings.&lt;/p&gt;
&lt;p&gt;Short, dynamic product videos offer a superior presentation experience. According to &lt;a href=&quot;https://www.retaildive.com/spons/the-future-of-e-commerce-is-video-5-undeniable-consumer-stats/711062/&quot;&gt;an analysis by Firework&lt;/a&gt;, video content increases purchase likelihood by 51%, highlighting its undeniable impact on buying decisions. This is why many sellers have already embraced video to enhance product displays.&lt;/p&gt;
&lt;p&gt;With a CE.SDK-powered JavaScript video editor, producing compelling videos that deliver a seamless, multi-device shopping experience becomes effortless. Plus, reusable templates help you generate unique product videos while maintaining brand consistency.&lt;/p&gt;
&lt;h3 id=&quot;engaging-video-messages-for-sales-outreach&quot;&gt;Engaging Video Messages for Sales Outreach&lt;/h3&gt;
&lt;p&gt;Marketers and sales teams know that cold emails often come across as impersonal and boring. The solution to this challenge? Personalized video messages!&lt;/p&gt;
&lt;p&gt;Customized video messages are proving to be an effective outreach tool, with studies showing &lt;a href=&quot;https://www.tavus.io/post/video-marketing-statistics&quot;&gt;significantly higher conversion rates&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With CreativeEditor SDK, sales and marketing teams can easily create personalized videos tailored to individual clients or leads, making their outreach more engaging and impactful. Unlike traditional email campaigns, personalized videos create a sense of real, one-on-one interaction.&lt;/p&gt;
&lt;p&gt;Additionally, the SDK’s translation features help sales teams break down language barriers, allowing them to reach a global audience. This ensures that the personalized messages resonate with clients from different regions.&lt;/p&gt;
&lt;p&gt;Explore this feature in our &lt;a href=&quot;https://img.ly/showcases/cesdk/language/web&quot;&gt;translation and internationalization demo&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;digital-asset-management&quot;&gt;Digital Asset Management&lt;/h3&gt;
&lt;p&gt;DAM, short for &lt;a href=&quot;https://www.ibm.com/think/topics/digital-asset-management&quot;&gt;Digital Asset Management&lt;/a&gt;, is the process of organizing, storing, and managing digital assets, including video content. As your business grows, an effective DAM system becomes key to enabling multiple teams to easily access and collaborate on assets across different projects.&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK backs DAM workflows by offering powerful tools to organize, edit, and repurpose video content through an embeddable, centralized interface. Its core JavaScript video editor component empowers users to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Effortlessly adapt and customize video assets.&lt;/li&gt;
&lt;li&gt;Ensure brand consistency while automating updates across various assets.&lt;/li&gt;
&lt;li&gt;Edit content efficiently within a collaborative environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although CE.SDK does not provide built-in role-based permissions, it integrates smoothly with backend systems to control user access. In particular, its flexible architecture supports the definition of custom hooks for permission checks to customize the editor’s behavior.&lt;/p&gt;
&lt;h3 id=&quot;automated-video-creation&quot;&gt;Automated Video Creation&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK streamlines the automation of asset creation by enabling users to generate on-brand video content variations for multiple channels. Thanks to adaptable templates, &lt;a href=&quot;https://img.ly/docs/cesdk/js/create-templates/add-dynamic-content/text-variables-7ecb50/&quot;&gt;dynamic text variables&lt;/a&gt;, and lockable designs, the SDK ensures consistency and brand compliance over all produced videos.&lt;/p&gt;
&lt;p&gt;Given a template, the creative engine automates the generation of countless personalized assets by populating them with resources from various data sources. That eliminates manual effort, reduces design bottlenecks, and accelerates production, making it perfect for scaling campaign-specific videos or building dedicated &lt;a href=&quot;https://img.ly/industries/marketing-tech&quot;&gt;marketing tech&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;customizing-your-creativeeditor-sdk-instance&quot;&gt;Customizing your CreativeEditor SDK Instance&lt;/h2&gt;
&lt;p&gt;CreativeEditor SDK is not a one-size-fits-all JavaScript video editor. Instead, it is built for flexibility, offering a wide set of customization options to tailor the editor to your unique requirements and brand identity. These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Theming Options&lt;/strong&gt;: Match the editor’s look to your app’s style with built-in themes, generate new ones using the &lt;a href=&quot;https://img.ly/docs/cesdk/js/user-interface/appearance/theming-4b0938/#using-the-theme-generator&quot;&gt;theme generator&lt;/a&gt;, or create custom themes manually. Explore theming possibilities in our &lt;a href=&quot;https://img.ly/showcases/cesdk/theming/web&quot;&gt;dedicated demo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom UI&lt;/strong&gt;: Build entirely bespoke JavaScript video editing user interfaces that align with your specific use case.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media Library Integration&lt;/strong&gt;: Set up sortable, flexible media libraries and integrate popular third-party libraries like &lt;a href=&quot;https://img.ly/showcases/cesdk/unsplash-image-assets/web&quot;&gt;Unsplash and others&lt;/a&gt;. Get easy access to external assets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Localization&lt;/strong&gt;: Adapt the editor to different languages and regions with &lt;a href=&quot;https://img.ly/docs/cesdk/js/user-interface/localization-508e20/&quot;&gt;full i18n support&lt;/a&gt;, letting you extend or overwrite any language setting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Toolbar Customization&lt;/strong&gt;: Rearrange toolbar elements, update icons, or rename tools to deliver a tailored user experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these customization options, CreativeEditor SDK ensures your video editor is as unique as your JavaScript application.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Implementing a JavaScript video editor in your web app can greatly improve the user experience and provide a powerful feature to drive higher engagement, retention, and even product distribution. This is true whether you are developing an e-commerce platform, a social media app, a tool for influencers, or a SaaS web solution.&lt;/p&gt;
&lt;p&gt;With the CreativeEditor SDK, adding a fully customizable video editing experience to your web application takes only a few minutes. Explore CE.SDK’s video capabilities and &lt;a href=&quot;https://img.ly/docs/cesdk/flutter/prebuilt-solutions/video-editor-9e533a/&quot;&gt;dive into the docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Stay tuned for more updates, and please &lt;a href=&quot;https://img.ly/forms/contact-sales?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=plugins1&quot;&gt;reach out&lt;/a&gt; if you have any questions. Thank you for reading.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Over 3,000 creative professionals gain early access to our new features, demos, and updates—don’t miss out, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i?ref=img.ly&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Antonello</dc:creator><media:content url="https://blog.img.ly/2025/01/video-editor-javascript.jpg" medium="image"/><category>JavaScript</category><category>Video Editor</category><category>CE.SDK</category></item><item><title>How I Built a Short Video Generator with AI &amp; CE.SDK in One Day</title><link>https://img.ly/blog/how-to-build-short-video-generator-ai-creative-sdk/</link><guid isPermaLink="true">https://img.ly/blog/how-to-build-short-video-generator-ai-creative-sdk/</guid><description>Can AI really accelerate product development? I built a short video generator in one day using AI and CE.SDK to find out.</description><pubDate>Thu, 09 Jan 2025 11:27:13 GMT</pubDate><content:encoded>&lt;p&gt;Here’s the crux of product development in the age of LLMs: how much can AI truly accelerate the development process?&lt;/p&gt;
&lt;p&gt;We have seen videos of solo developers building small apps entirely with AI with just a few prompts. But how does it scale to more complex development projects? As LLMs rapidly evolve, their scope and impact will only increase.&lt;/p&gt;
&lt;p&gt;That’s why I regularly challenge myself to build a small project with the help of AI. I’m a prime candidate to test the AI productivity boost: a jack-of-all-trades (and a master of none) with a background in both design and engineering, yet no hands-on experience in the past five years. My latest challenge? Build a web-based short video generator within one day.&lt;/p&gt;
&lt;p&gt;In this post, I’ll share the most intriguing takeaways from tackling this project.&lt;/p&gt;
&lt;h2 id=&quot;why-a-short-video-generator&quot;&gt;Why a Short Video Generator?&lt;/h2&gt;
&lt;p&gt;Why focus on this idea? It’s simple: to ride the wave of a new trend. A format called “&lt;strong&gt;faceless&lt;/strong&gt;” short videos is gaining traction among creators on platforms like YouTube and TikTok.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/embed/DfQ3fhqfKVc?feature=oembed&quot;&gt;https://www.youtube.com/embed/DfQ3fhqfKVc?feature=oembed&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What’s fascinating about these videos is their automation: an LLM generates a script, which is then transformed into speech, images, and text assets using various AI services. These assets are automatically assembled into a cohesive video.&lt;/p&gt;
&lt;p&gt;The general concept is compelling: It’s still generative content, but mixed with classic video composition techniques. This approach offers greater accuracy, consistency, and control over pure generative AI.&lt;/p&gt;
&lt;p&gt;The potential to automate video production at this scale is exciting. Add its relatively low complexity and high production value, and it became the perfect topic for my challenge.&lt;/p&gt;
&lt;h2 id=&quot;enter-cesdk&quot;&gt;Enter CE.SDK&lt;/h2&gt;
&lt;p&gt;Another reason I chose this challenge was its compatibility with CE.SDK, our design and video editor library. CE.SDK offers a robust editing toolkit that integrates into any product with just a few lines of code. Its features, like headless mode, are ideal for automating workflows like video generation.&lt;/p&gt;
&lt;p&gt;Most faceless video services use React-based video generation and achieve fair results. However, using CE.SDK instead of a react-based library could potentially boost the overall experience with three critical improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Editable Outputs:&lt;/strong&gt; This is huge. Full automation often needs human adjustments for fine-tuning. CE.SDK enables automated video generation while allowing manual refinement of the results.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Visual Quality:&lt;/strong&gt; CE.SDK has its own rendering pipeline, allowing for more nuanced visual effects and animations. When you’re competing against others in this space, it can make a huge difference if you’re able to produce higher fidelity in the visual output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visual Design Workflow:&lt;/strong&gt; Create design components or even entire templates visually, and then use them via code. This authoring workflow can be extremely helpful in creating rich, interesting designs for the generated videos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-ground-rules&quot;&gt;The Ground Rules&lt;/h2&gt;
&lt;p&gt;To keep the challenge focused, I set strict rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Time Limit:&lt;/strong&gt; Spend no more than 12 hours on the challenge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Manual Coding:&lt;/strong&gt; Avoid writing any code yourself—everything should be built through conversations with AI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trust the AI:&lt;/strong&gt; Do not read or analyze code generated by the AI. Rely entirely on its decisions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skip External Research:&lt;/strong&gt; Do not read or explore the APIs you intend to use. Instead, provide links to the AI and let it determine how to use them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compare AI Performance:&lt;/strong&gt; Alternate Claude Sonnet 3.5 and ChatGPT o1 for code generation to evaluate which performs better.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-tools--workflow&quot;&gt;The Tools &amp;#x26; Workflow&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Code Editor:&lt;/strong&gt; &lt;a href=&quot;https://www.cursor.com/&quot;&gt;&lt;strong&gt;Cursor&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
Built on VSCode’s foundation, Cursor stood out as the only editor offering both an integrated chat interface and the ability to switch between different LLMs. However, with GitHub’s recent significant updates to Copilot, I’ll switch to VSCode with Copilot for future challenges.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UI Prototyping:&lt;/strong&gt; &lt;a href=&quot;https://madewithclaude.com/&quot;&gt;&lt;strong&gt;Claude Artifacts&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
Rather than building the entire project in my code editor, I chose to prototype the UI directly through Claude’s web interface. The benefits were immense:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Instant results:&lt;/strong&gt; To create an artifact, Claude streamlines development by automatically writing and compiling code while leveraging essential UI libraries and components. This automation eliminates setup time and technical overhead, allowing me to focus purely on design iterations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instants Variations:&lt;/strong&gt; Claude enables rapid prototyping through parallel conversations. When a design direction didn’t quite work, I could simply start a fresh conversation with modified requirements and evaluate a new prototype. This approach helped me develop three viable concepts quickly - a pace that would have been impossible in a traditional code editor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quality of execution:&lt;/strong&gt; Claude transforms rough concepts into polished, intuitive interfaces. Its suggestions often surpassed my initial ideas, offering sophisticated solutions I hadn’t considered.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep it clean:&lt;/strong&gt; By prototyping outside the code editor, I kept the main project’s codebase clean and focused. This separation prevented the accumulation of experimental code and maintained the clarity of our primary development environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/how-to/er-ai/0108.mp4&quot; controls loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Quickly prototype your interface with Claude Artifacts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;APIs&lt;/strong&gt;&lt;br&gt;
Key APIs used in the project included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Script Generation:&lt;/strong&gt; Claude Sonnet 3.5 vs various ChatGPT models.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image/Video Assets:&lt;/strong&gt; &lt;a href=&quot;https://Fal.ai&quot;&gt;Fal.ai&lt;/a&gt; Flux models.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speech Synthesis:&lt;/strong&gt; &lt;a href=&quot;https://elevenlabs.io/&quot;&gt;ElevenLabs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;building-the-app-divide-and-conquer&quot;&gt;Building the App: Divide and Conquer&lt;/h2&gt;
&lt;p&gt;After having prototyped the UI, I started to chat with the LLM inside the code editor so that it can code the app. To work with the AI efficiently, I followed a divide-and-conquer approach. Rather than simply asking it to “build me a video app,” I broke down the problem into manageable steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Generate a video script&lt;/strong&gt;&lt;br&gt;
Create an AI prompt that includes user input and examples of the desired output format. Pass this prompt to the LLM API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parse the script to generate assets (speech, images, text)&lt;/strong&gt;&lt;br&gt;
Parse the LLM’s response to extract image prompts and speech paragraphs. Send these to their respective APIs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compose the final video&lt;/strong&gt;&lt;br&gt;
Load all the generated assets into a predefined template to generate the finished video through the CE.SDK library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After completing these steps, I was finally able to generate my first fully automated videos! With a few more tweaks and additions, I had an MVP ready within twelve hours.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/how-to/er-ai/shortyroll.mp4&quot; controls loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;The final result: A Short Video Generator&lt;/p&gt;
&lt;p&gt;There are still some missing features, partly because I spent a significant amount of time refining the prompt to generate the video script. I also had to bend the rules occasionally—sometimes the LLM would hit a wall, and I had to read or write small snippets of code.&lt;/p&gt;
&lt;h2 id=&quot;key-takeaways&quot;&gt;Key Takeaways&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Engineering Knowledge Is Essential&lt;/strong&gt;&lt;br&gt;
You should have some engineering background to achieve the AI productivity boost in development.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI doesn’t solve everything for you. You are still the architect. You provide a lot of input and guidance. AI often needs to be pointed to the right strategy. Foundational knowledge of computer science is hugely advantageous for working with AI effectively.&lt;/li&gt;
&lt;li&gt;As mentioned, I had to read and write a few lines of code myself. Without coding experience, I would have probably not been able to progress, as the LLM was not able to.&lt;/li&gt;
&lt;li&gt;The getting started experience is nowhere close to novice-friendly. How do you get started with a new project in a code editor that actually requires you to do the setup manually? My workaround was to create an empty project, and then ask the LLM to instruct me to use a boilerplate for react. Again, this is engineering knowledge, any novice would have hit a wall already at this point.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Claude Outperformed ChatGPT&lt;/strong&gt;&lt;br&gt;
Claude was a clear winner in the side-by-side comparison, because of three reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Artifacts was a game changer for UI prototyping.&lt;/li&gt;
&lt;li&gt;It was generally better at writing and understanding code. Difficult to quantify, but in some cases Claude fixed the mess ChatGPT left in the code&lt;/li&gt;
&lt;li&gt;Claude can process URLs, which makes working with APIs much smoother.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Who would have thought new LLMs would catch up to OpenAI so quickly after they released the first version of ChatGPT?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Complexity Slows AI&lt;/strong&gt;&lt;br&gt;
The more code in my project, the slower the overall progress. LLMs struggled with the growing complexity. Their context windows filled more quickly, and their responses became increasingly unreliable. At some point, it becomes extremely difficult to make architectural changes, especially if this affects multiple parts of the app. When trying to fix errors, you’ll often find yourself in a whack-a-mole game. While the AI would resolve one issue, it would inadvertently introduce new problems elsewhere, creating an endless loop of fixes and regressions.&lt;/p&gt;
&lt;p&gt;Ultimately, the time invested in this challenge was well worth it. While LLMs can’t build products end to end on their own, they can significantly streamline product development when paired with the right human collaboration. The real question is whether development teams are ready to adapt their habits and explore new workflows to boost productivity.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;This challenge has inspired me to refine and expand on this project. Future iterations will focus on harnessing CE.SDK’s unique features to push the boundaries of automated video generation.&lt;/p&gt;
&lt;p&gt;Stay tuned for part two of this series—there’s much more to explore!&lt;/p&gt;
&lt;p&gt;UPDATE: Read &lt;a href=&quot;https://img.ly/blog/how-to-build-a-short-video-generator-using-ce-sdk-2/&quot;&gt;part two&lt;/a&gt; - a cookbook how to build your own short video creator!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Over 3,000 creative professionals gain early access to our new features, insights and updates—don’t miss out, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i?ref=img.ly&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Eray</dc:creator><media:content url="https://blog.img.ly/2025/01/build-ai-video-generator-1.jpg" medium="image"/><category>How-To</category><category>AI</category><category>CE.SDK</category><category>Artificial Intelligence</category><category>Video Editor</category></item><item><title>A Modern Vue.js Video Editor: Setup Guide</title><link>https://img.ly/blog/a-modern-vue-js-video-editor/</link><guid isPermaLink="true">https://img.ly/blog/a-modern-vue-js-video-editor/</guid><description>Learn how to integrate IMG.LY&apos;s video editor for Vue.js into your web app and how to best leverage its capabilities.</description><pubDate>Wed, 08 Jan 2025 11:24:43 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Discover how to integrate&lt;/em&gt; &lt;a href=&quot;https://img.ly/docs/cesdk/vue/starterkits/video-editor-e1nlor/&quot;&gt;&lt;em&gt;IMG.LY’s video editor&lt;/em&gt;&lt;/a&gt; &lt;em&gt;into your Vue.js application and unlock its full potential.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Platforms like Instagram, YouTube, and TikTok have revolutionized how we engage with content, setting new standards for consuming video media. With the growing popularity of short-form videos, this trend shows no signs of slowing down.&lt;/p&gt;
&lt;p&gt;Users now not only love to watch videos but also expect intuitive video creation and editing features from modern web applications. Here is why adding a video editor to your Vue.js web application can significantly boost user engagement and satisfaction.&lt;/p&gt;
&lt;p&gt;In this guide, you will discover how to integrate a video editor into a Vue.js project using CreativeEditor SDK (also referred to as &lt;em&gt;CE.SDK&lt;/em&gt;). We will also discuss when this functionality is most beneficial and how to customize the editor for your specific needs.&lt;/p&gt;
&lt;p&gt;For a quick setup, take a look at the &lt;a href=&quot;https://github.com/imgly/cesdk-web-examples/tree/main/integrate-with-vue&quot;&gt;GitHub Vue.js video editor integration&lt;/a&gt; repository to kick off your project.&lt;/p&gt;
&lt;p&gt;Let’s dive in!&lt;/p&gt;
&lt;h2 id=&quot;why-you-should-add-a-video-editor-to-your-vuejs-app&quot;&gt;Why You Should Add a Video Editor to Your Vue.js App?&lt;/h2&gt;
&lt;p&gt;The digital landscape is constantly evolving, but one truth has remained steady: video content continues to dominate.&lt;/p&gt;
&lt;p&gt;Statistics about videos are clear. According to &lt;a href=&quot;https://datareportal.com/reports/digital-2022-instagram-headlines&quot;&gt;Datareportal&lt;/a&gt;, over one-third of all Instagram reels are videos. Similarly, YouTube Shorts garners &lt;a href=&quot;https://blog.youtube/inside-youtube/shorts-revenue-sharing-update/&quot;&gt;over 70 billion daily views&lt;/a&gt;, and TikTok boasts more than &lt;a href=&quot;https://www.statista.com/statistics/272014/global-social-networks-ranked-by-number-of-users/&quot;&gt;1.5 billion monthly active users worldwide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The reasons behind these staggering numbers are two:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Videos are incredibly engaging for audiences.&lt;/li&gt;
&lt;li&gt;Social media platforms have made it remarkably easy to create professional-looking content.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Users now expect to be able to add filters, overlays, audio, music, and text with just a few clicks. As a result, not only do we anticipate video editing features in web applications, but we also demand that these features be simple to use.&lt;/p&gt;
&lt;p&gt;By integrating an intuitive video editor, your Vue.js web app can capitalize on that trend. The goal is to provide a feature that billions of users are already familiar with—and likely expect from your application.&lt;/p&gt;
&lt;p&gt;The payoff? Lowering the barriers to user-generated content, increasing engagement, and driving product distribution!&lt;/p&gt;
&lt;h2 id=&quot;how-to-integrate-a-video-editor-in-vuejs&quot;&gt;How to Integrate a Video Editor in Vue.js&lt;/h2&gt;
&lt;p&gt;In this section, you will learn how to set up a Vue.js video editor using CreativeEditor SDK.&lt;/p&gt;
&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;
&lt;p&gt;Before starting, ensure you have the latest LTS version of Node.js installed on your machine. Otherwise, download and install it from the &lt;a href=&quot;https://nodejs.org/en/download&quot;&gt;official Node.js website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you do not already have a Vue.js project, create a new &lt;a href=&quot;https://vite.dev/&quot;&gt;Vite&lt;/a&gt;-based Vue project by running the following command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; vue@latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will install and run &lt;a href=&quot;https://github.com/vuejs/create-vue&quot;&gt;create-vue&lt;/a&gt;, the official Vue project scaffolding tool. During the process, you will be prompted to select optional features like TypeScript and testing support. Below is an example of how you can respond to the prompts:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Project&lt;/span&gt;&lt;span&gt; name:&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt; my-vue-video-editor-app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; TypeScript?&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; JSX&lt;/span&gt;&lt;span&gt; Support?&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; Vue&lt;/span&gt;&lt;span&gt; Router&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; Single&lt;/span&gt;&lt;span&gt; Page&lt;/span&gt;&lt;span&gt; Application&lt;/span&gt;&lt;span&gt; development?&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; Pinia&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; state&lt;/span&gt;&lt;span&gt; management?&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; Vitest&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; Unit&lt;/span&gt;&lt;span&gt; Testing?&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; an&lt;/span&gt;&lt;span&gt; End-to-End&lt;/span&gt;&lt;span&gt; Testing&lt;/span&gt;&lt;span&gt; Solution?&lt;/span&gt;&lt;span&gt; »&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; ESLint&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; code&lt;/span&gt;&lt;span&gt; quality?&lt;/span&gt;&lt;span&gt; »&lt;/span&gt;&lt;span&gt; Yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;√&lt;/span&gt;&lt;span&gt; Add&lt;/span&gt;&lt;span&gt; Prettier&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; code&lt;/span&gt;&lt;span&gt; formatting?&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; Yes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are unsure about an option, simply select “No” by pressing Enter.&lt;/p&gt;
&lt;p&gt;After the project is set up, navigate to the project folder and install CreativeEditor SDK via &lt;a href=&quot;https://www.npmjs.com/package/@cesdk/cesdk-js&quot;&gt;&lt;code&gt;@cesdk/cesdk-js&lt;/code&gt;&lt;/a&gt; package with this command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @cesdk/cesdk-js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your package.json file will now include the SDK as a dependency:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;@cesdk/cesdk-js&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^1.41.1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;vue&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^3.5.13&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;vue-router&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^4.4.5&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, open your project in a JavaScript IDE, and you are ready to start coding!&lt;/p&gt;
&lt;h3 id=&quot;create-the-video-editor-component&quot;&gt;Create the Video Editor Component&lt;/h3&gt;
&lt;p&gt;In the &lt;code&gt;src/components&lt;/code&gt; folder, create a new file named &lt;code&gt;VideoEditor.vue&lt;/code&gt;. This file will serve as your Vue.js single-file component for the CE.SDK-based video editor.&lt;/p&gt;
&lt;p&gt;In the  like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@cesdk/cesdk-js&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, create your video editor component using the following lines of code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;!--&lt;/span&gt;&lt;span&gt; src&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;components&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;VideoEditor.vue &lt;/span&gt;&lt;span&gt;--&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;cesdk_container&quot;&lt;/span&gt;&lt;span&gt; style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;height: 100vh; width: 100vw&quot;&lt;/span&gt;&lt;span&gt;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import CreativeEditorSDK from &apos;@cesdk/cesdk-js&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export default {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  props: { config: Object },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  _cesdk: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  mounted: &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; mounted&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    CreativeEditorSDK.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;#cesdk_container&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.config).&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      this&lt;/span&gt;&lt;span&gt;._cesdk &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      // customize the editor behavior...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  methods: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  watch: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  beforeUnmount: &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; beforeDestroy&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // clean up the CE.SDK instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;._cesdk) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      this&lt;/span&gt;&lt;span&gt;._cesdk.&lt;/span&gt;&lt;span&gt;dispose&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      this&lt;/span&gt;&lt;span&gt;._cesdk &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The component defined above embeds the &lt;code&gt;CreativeEditorSDK&lt;/code&gt; JavaScript element into an HTML &lt;code&gt;&amp;#x3C;div&gt;&lt;/code&gt; container.&lt;/p&gt;
&lt;h3 id=&quot;use-the-component&quot;&gt;Use the Component&lt;/h3&gt;
&lt;p&gt;You can now import the &lt;code&gt;VideoEditor&lt;/code&gt; component in the 
&lt;/p&gt;&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; VideoEditor &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./components/VideoEditor.vue&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, include it in the &lt;template&gt; section as shown in this snippet:
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;VideoEditor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  :config=&quot;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    license:&lt;/span&gt;&lt;span&gt; &apos;&amp;#x3C;YOUR_LICENSE&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    userId:&lt;/span&gt;&lt;span&gt; &apos;&amp;#x3C;YOUR_USER_ID&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;#x3C;YOUR_LICENSE&gt;&lt;/code&gt; with the license key provided by CreativeEditor SDK and &lt;code&gt;&amp;#x3C;YOUR_USER_ID&gt;&lt;/code&gt; with your user ID to optionally track monthly active users (MAUs) across different devices.&lt;/p&gt;
&lt;p&gt;This setup will launch the video editor with a video preset, enabling users to trim, cut, apply filters, add text overlays, include music, and perform other enhancements to their videos.&lt;/p&gt;
&lt;h2 id=&quot;use-cases-for-the-vuejs-video-editor&quot;&gt;Use Cases for the Vue.js Video Editor&lt;/h2&gt;
&lt;p&gt;Now that you have seen how to build a Vue.js video editor component with a basic CreativeEditor SDK setup, it is time to explore some practical use cases and scenarios.&lt;/p&gt;
&lt;h3 id=&quot;automated-marketing&quot;&gt;Automated Marketing&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK equips marketers with powerful tools to produce branded videos for multiple campaigns at scale. Key features for this task include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Integration&lt;/strong&gt;: Integrate the SDK’s API to automate the creation of videos, reducing manual effort and supporting large-scale video production. This opens the door to automated workflows for marketing campaigns, ad creation, and A/B testing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pre-Designed, Editable Templates&lt;/strong&gt;: Define placeholders, lock or unlock specific design elements, and guide what other users can edit and how. Thanks to this template-based process, it is possible to produce professional assets by leveraging editable &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;video templates&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Template Import from Photoshop:&lt;/strong&gt; Configure the SDK to bulk import .PSD files from Adobe Photoshop, converting them into the CE.SDK scene archive format for streamlined design integration and editing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manage Branded Assets&lt;/strong&gt;: Build &lt;a href=&quot;https://img.ly/docs/cesdk/vue/import-media/asset-panel/customize-c9a4de/&quot;&gt;custom content libraries&lt;/a&gt; to manage brand assets, including logos, vector graphics, stock photos, and templates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These capabilities make CE.SDK a reliable technology for scalable, efficient, and brand-consistent video marketing automation.&lt;/p&gt;
&lt;h3 id=&quot;informative-videos-for-e-learning&quot;&gt;Informative Videos for E-Learning&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK gives educators, teachers, and coaches the tools they need to create impactful and information-rich videos. The entire content creation and editing process requires no advanced technical skills. In detail, users can record, edit, and organize videos across desktop, mobile, or tablet devices.&lt;/p&gt;
&lt;p&gt;Beyond simplifying video production, the SDK is based on reusable templates, so that instructors can quickly adapt materials for various topics while maintaining consistency. Additionally, &lt;a href=&quot;https://img.ly/docs/cesdk/vue/user-interface/ui-extensions-d194d1/&quot;&gt;interactivity plugins&lt;/a&gt;—featuring quizzes, polls, and other learner-focused elements—enhances engagement, making lessons more dynamic and personalized.&lt;/p&gt;
&lt;h3 id=&quot;unique-videos-for-lead-outreach&quot;&gt;Unique Videos for Lead Outreach&lt;/h3&gt;
&lt;p&gt;Cold emails often feel dull and impersonal, frequently ending up in the spam or trash folder. In contrast, personalized video messages are revolutionizing lead outreach.&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK empowers sales, marketing, and business development teams to deliver engaging videos that outshine standard email pitches, offering features such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Customized Video Messages for Leads&lt;/strong&gt;: Craft personalized videos for specific clients or prospects, adding a genuine human touch to your messages. Thanks to &lt;a href=&quot;https://img.ly/docs/cesdk/vue/create-templates/add-dynamic-content/text-variables-7ecb50/&quot;&gt;configurable text variables&lt;/a&gt;, you can customize video content at scale to leave a lasting impression compared to traditional cold emails.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seamless Integration for Scalable Outreach&lt;/strong&gt;: Produce professional and customized video messages at scale, making it easy for sales teams to personalize outreach without sacrificing efficiency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Translation Capabilities for Global Reach&lt;/strong&gt;: Leverage the SDK’s built-in translation and internationalization features to communicate with audiences worldwide. Adapt your messages to the local customs to convey a truly personalized experience. Test this feature &lt;a href=&quot;https://img.ly/showcases/cesdk/language/web&quot;&gt;in our translation demo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Take your lead outreach to the next level with these innovative video solutions.&lt;/p&gt;
&lt;h3 id=&quot;social-media-video-content-generation&quot;&gt;Social Media Video Content Generation&lt;/h3&gt;
&lt;p&gt;CE.SDK offers all the tools users need to create captivating videos. It makes it easy to produce shareable content for platforms like Instagram, TikTok, YouTube, LinkedIn, and more.&lt;/p&gt;
&lt;p&gt;Users can take advantage of reusable templates to rapidly bring their ideas to life, without having to start from scratch. They can choose from a variety of pre-designed options, which you can explore in &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;our video editor demo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The support for &lt;a href=&quot;https://img.ly/docs/cesdk/vue/animation/overview-6a2ef2/&quot;&gt;configurable animations&lt;/a&gt; increase engagement and improve the visual appealing. In the SDK, users can also set the mood with music or add narration. Once complete, videos can finally be seamlessly exported in the ideal format and aspect ratio for social media platforms.&lt;/p&gt;
&lt;h3 id=&quot;digital-asset-management&quot;&gt;Digital Asset Management&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://business.adobe.com/blog/basics/digital-asset-management&quot;&gt;Digital Asset Management&lt;/a&gt;, commonly referred to as DAM, is the process of organizing, storing, and managing digital assets—such as videos. Given the large volume of assets companies produce and the way employees and users interact with them, DAM has become a key business process for many organizations.&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK supports DAM by offering an embeddable Vue.js video editor UI component, allowing for centralized video organization, production, repurposing, and editing. This component exposes features like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Asset Libraries&lt;/strong&gt;: CE.SDK can load assets from local files or even integrate third-party libraries via API. Users can search and browse local assets as well as remote images from platforms like Pexels, Unsplash, and Getty within the editor. You can explore our &lt;a href=&quot;https://img.ly/showcases/cesdk?tags=assets&quot;&gt;asset library demo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Permissions for Asset Control&lt;/strong&gt;: Although the SDK does not include role-based permissions out of the box, it connects with backend technologies to manage user access and permissions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extendability for Custom Permissions&lt;/strong&gt;: Developers can extend the SDK to create custom hooks that check permissions and modify the editor’s behavior, ensuring the right users have access to and can edit assets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These features make CreativeEditor SDK a valuable tool for businesses managing video assets while maintaining brand consistency and workflow efficiency.&lt;/p&gt;
&lt;h2 id=&quot;customizing-your-creativeeditor-sdk-instance&quot;&gt;Customizing your CreativeEditor SDK Instance&lt;/h2&gt;
&lt;p&gt;CreativeEditor SDK does not provide a static, pre-configured Vue.js video editor experience. Instead, it supports a large set of customization options to tailor the editor to your specific needs and brand requirements.&lt;/p&gt;
&lt;p&gt;Key customization features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Build Custom UIs&lt;/strong&gt;: Create fully personalized user interfaces and adapt the editor to your specific use case. This includes repositioning toolbar elements, changing icons, or renaming tools to provide a unique editing experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feature Activation&lt;/strong&gt;: Enable or disable features based on default settings, giving you control over what is available to users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internationalization (i18n)&lt;/strong&gt;: Tailor the video editor to different languages and regions. CE.SDK &lt;a href=&quot;https://img.ly/docs/cesdk/vue/user-interface/localization-508e20/&quot;&gt;fully supports i18n&lt;/a&gt;, enabling you to overwrite and extend all text strings in any language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media Libraries&lt;/strong&gt;: Define custom, sortable, resource-rich media libraries. CE.SDK supports integration with third-party libraries via API for easy access to external media assets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single Page Mode&lt;/strong&gt;: Configure the editor to display only one active page at a time for a streamlined experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Theming&lt;/strong&gt;: Adjust the editor’s theme to align with your app’s design. Choose from built-in themes, generate new ones using the &lt;a href=&quot;https://img.ly/docs/cesdk/vue/user-interface/appearance/theming-4b0938/&quot;&gt;theme generator&lt;/a&gt;, or manually create a custom theme. Test theming in our &lt;a href=&quot;https://img.ly/showcases/cesdk/theming/web&quot;&gt;demo page&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See all of these customizations in action in our &lt;a href=&quot;https://img.ly/showcases/cesdk?tags=customization&quot;&gt;customization demo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Featuring a Vue.js video editor in your web application can greatly improve the user experience, making it a valuable addition to boosting product success, user reviews, and retention. This is true whether you are building a sales tool, an e-learning platform, or a web app with social media integration.&lt;/p&gt;
&lt;p&gt;With CreativeEditor SDK, you can integrate a fully customizable video editing experience into your Vue.js application in minutes.&lt;/p&gt;
&lt;p&gt;By following the steps outlined in this blog post, you saw how to bring professional-level video editing features to your web users. Explore CE.SDK’s video capabilities and &lt;a href=&quot;https://img.ly/docs/cesdk/vue/prebuilt-solutions/video-editor-9e533a/&quot;&gt;dive into the docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Stay tuned for more updates, and please &lt;a href=&quot;https://img.ly/forms/contact-sales?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=plugins1&quot;&gt;reach out&lt;/a&gt; if you have any questions. Thank you for reading.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Over 3,000 creative professionals gain early access to our new features, demos, and updates—don’t miss out, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i?ref=img.ly&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter.&lt;/strong&gt;&lt;/p&gt;&lt;/template&gt;&lt;/p&gt;</content:encoded><dc:creator>Antonello</dc:creator><media:content url="https://blog.img.ly/2025/01/video-editor-vue_js.jpg" medium="image"/><category>Vue.js</category><category>Video Editor</category><category>How-To</category></item><item><title>A Modern React Video Editor: Integration Guide</title><link>https://img.ly/blog/a-modern-react-video-editor/</link><guid isPermaLink="true">https://img.ly/blog/a-modern-react-video-editor/</guid><description>Learn how to integrate IMG.LY&apos;s video editor for React Native into your app and how to best leverage its capabilities.</description><pubDate>Wed, 08 Jan 2025 09:31:11 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Learn how to integrate&lt;/em&gt; &lt;a href=&quot;https://img.ly/docs/cesdk/react/starterkits/video-editor-e1nlor/&quot;&gt;&lt;em&gt;IMG.LY’s video editor for React&lt;/em&gt;&lt;/a&gt; &lt;em&gt;into your web app and make the most of all its features.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Video content has seen steadily growing demand, especially with the rising popularity of short-form videos. It is no surprise that platforms like YouTube have heavily invested in short-form video content, as video remains a dominant medium for users to create and consume content.&lt;/p&gt;
&lt;p&gt;Platforms like Instagram, TikTok, and YouTube have changed user habits forever. Here is why integrating video creation and editing directly within your web application can dramatically enhance user satisfaction.&lt;/p&gt;
&lt;p&gt;In this guide, you will see how to integrate a video editor into a React app using CreativeEditor SDK (&lt;em&gt;CE.SDK&lt;/em&gt;, for short). We will discuss when it is useful and explain how to customize the editor for your specific use cases.&lt;/p&gt;
&lt;p&gt;For a quick start, check out the &lt;a href=&quot;https://github.com/imgly/cesdk-web-examples/tree/main/integrate-with-react&quot;&gt;GitHub repository&lt;/a&gt; featuring the code for integrating a React video editor.&lt;/p&gt;
&lt;p&gt;Let’s dive in!&lt;/p&gt;
&lt;h2 id=&quot;why-integrate-a-video-editor-in-your-react-web-app&quot;&gt;Why Integrate a Video Editor in Your React Web App?&lt;/h2&gt;
&lt;p&gt;The digital landscape is ever-evolving, but one truth has remained constant for several years: video content reigns supreme.&lt;/p&gt;
&lt;p&gt;The data speaks for itself. Platforms like &lt;a href=&quot;https://newsroom.tiktok.com/en-us/1-billion-people-on-tiktok&quot;&gt;TikTok boast over 1.04 billion monthly active users worldwide&lt;/a&gt;. Similarly, one of most recent &lt;a href=&quot;https://abc.xyz/2024-q1-earnings-call/&quot;&gt;Google’s earnings call&lt;/a&gt; revealed that YouTube Shorts generated approximately 70 billion daily views in just one quarter—a significant leap from 30 billion daily views just two years ago.&lt;/p&gt;
&lt;p&gt;These platforms have set the gold standard by empowering users to create professional-looking videos effortlessly—adding filters, overlays, audio, and text with just a few clicks. This simplicity has made video editing an essential feature across various industries, from social media apps to marketing tools.&lt;/p&gt;
&lt;p&gt;Then, the shift toward shorter, more engaging videos has transformed how users create content and how we consume it. Audiences now demand bite-sized, engaging clips that are easy to produce and share.&lt;/p&gt;
&lt;p&gt;By integrating an easy-to-use video editor, your React web app can tap into this trend. The idea is to offer a feature that billions of users are familiar with—and may already expect from your application.&lt;/p&gt;
&lt;p&gt;The result? Lowering the barrier for user-generated content, boosting engagement, and driving distribution!&lt;/p&gt;
&lt;p&gt;React’s flexibility and component-based architecture make it the perfect match for IMG.LY’s &lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CreativeEditor SDK&lt;/a&gt;, which guarantees a seamless, high-performance, and feature-rich experience for design, video, and photo editing—all directly in the browser.&lt;/p&gt;
&lt;h2 id=&quot;getting-started-adding-a-video-editor-in-react&quot;&gt;Getting Started: Adding a Video Editor in React&lt;/h2&gt;
&lt;p&gt;Follow this step-by-step tutorial section and learn how to set up a React video editor in your web app using CreativeEditor SDK. For a different approach, see our guide on &lt;a href=&quot;https://img.ly/blog/how-to-build-a-video-editor-with-wasm-in-react/&quot;&gt;how to build a video editor in React with Wasm&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Integrate CE.SDK in React with the following instructions!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before getting started, make sure you have the latest LTS version of Node.js installed on your machine. Otherwise, &lt;a href=&quot;https://nodejs.org/en/download&quot;&gt;download it from the official website&lt;/a&gt; and install it.&lt;/p&gt;
&lt;p&gt;Next, if you do not already have a React project set up, create a new one using &lt;a href=&quot;https://vite.dev/guide/&quot;&gt;Vite&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; vite@latest&lt;/span&gt;&lt;span&gt; my-react-video-editor-app&lt;/span&gt;&lt;span&gt; –&lt;/span&gt;&lt;span&gt; --template&lt;/span&gt;&lt;span&gt; react&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Install CE.SDK via the &lt;a href=&quot;https://www.npmjs.com/package/@cesdk/cesdk-js&quot;&gt;@cesdk/cesdk-js&lt;/a&gt; package with this command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @cesdk/cesdk-js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your &lt;code&gt;package.json&lt;/code&gt; file will now include it as a dependency:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@cesdk/cesdk-js&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^1.41.1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;react&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^18.3.1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;react-dom&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^18.3.1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Load your project in a JavaScript IDE, as you are ready to start coding!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create the Video Editor Component&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the src folder, create a &lt;code&gt;VideoEditor.jsx&lt;/code&gt; file. This will contain your CE.SDK-based React video editor component.&lt;/p&gt;
&lt;p&gt;Import CreativeEditorSDK from &lt;code&gt;@cesdk/cesdk-js&lt;/code&gt; as below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@cesdk/cesdk-js&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, initialize your video editor React component with this logic:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// src/VideoEditor.jsx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@cesdk/cesdk-js&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useEffect, useRef, useState } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// your CE.SDK license and user configs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  license: &lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;YOUR_LICENSE&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  userId: &lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;YOUR_USER_ID&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; VideoEditor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; cesdk_container&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; useRef&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;cesdk&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setCesdk&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // if the CE.SDK container has already been initialized&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;cesdk_container.current) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let&lt;/span&gt;&lt;span&gt; cleanedUp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // initialize a CE.SDK instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let&lt;/span&gt;&lt;span&gt; instance;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    CreativeEditorSDK.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(cesdk_container.current, config).&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;_instance&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        instance &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; _instance;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (cleanedUp) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          instance.&lt;/span&gt;&lt;span&gt;dispose&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // customize the editor behavior...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        setCesdk&lt;/span&gt;&lt;span&gt;(instance);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // clean up the CE.SDK instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; cleanup&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      cleanedUp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      instance?.&lt;/span&gt;&lt;span&gt;dispose&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setCesdk&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; cleanup;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [cesdk_container]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{cesdk_container}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{{ width: &lt;/span&gt;&lt;span&gt;&apos;100vw&apos;&lt;/span&gt;&lt;span&gt;, height: &lt;/span&gt;&lt;span&gt;&apos;100vh&apos;&lt;/span&gt;&lt;span&gt; }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;#x3C;YOUR_LICENSE&gt;&lt;/code&gt; with the license key you obtain from CreativeEditor SDK and &lt;code&gt;&amp;#x3C;YOUR_USER_ID&gt;&lt;/code&gt; with your user ID to optionally track monthly active users (MAUs) across different devices.&lt;/p&gt;
&lt;p&gt;The component defined above loads the &lt;a href=&quot;https://img.ly/docs/cesdk/js/get-started/overview-e18f40/&quot;&gt;CreativeEditorSDK&lt;/a&gt; JavaScript element into an HTML &lt;/p&gt;&lt;div&gt; element.&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use the Component&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can now import the VideoEditor component as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; VideoEditor &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./VideoEditor&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, use it as below:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;#x3C;VideoEditor /&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This will open the video editor with the video preset, allowing users to trim, cut, apply filters, add text overlays, include music, and more to enhance their videos.&lt;/p&gt;
&lt;p&gt;Have a look at our &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web?ref=img.ly&quot;&gt;interactive demo&lt;/a&gt; to see what the resultant editor should look like.&lt;/p&gt;
&lt;h2 id=&quot;react-video-editor-use-cases&quot;&gt;React Video Editor Use Cases&lt;/h2&gt;
&lt;p&gt;Now that you know how to integrate a React video editor into your web app, you are ready to explore some key use cases. See how the specific features of CreativeEditor SDK can support different scenarios.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Social Media Publishing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK equips users with the tools they need to create engaging video content. It makes it easier to produce shareable videos for popular social media platforms like Instagram, TikTok, and LinkedIn with features like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reusable Templates&lt;/strong&gt;: Start with video templates downloaded from others or create your own templates and share them with the community. By selecting from a variety of ready-to-use templates for different use cases, users can avoid the blank canvas syndrome and bring their ideas to life quickly. You can explore a range of different templates in our &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web?template=month-in-review&amp;#x26;ref=img.ly&quot;&gt;video editor demo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music and Audio Library&lt;/strong&gt;: Users can easily add audio files to their videos, setting the tone through music or narration and creating a captivating atmosphere for their content.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Animations&lt;/strong&gt;: The SDK comes with a wide set of &lt;a href=&quot;https://img.ly/docs/cesdk/react/animation/overview-6a2ef2/&quot;&gt;configurable animations&lt;/a&gt; to improve the appearance of design elements within video scenes, significantly boosting engagement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once a video has been created in your React application, CE.SDK lets users export it in the appropriate formats and aspect ratios for the target social media platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Digital Asset Management&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;DAM, short for &lt;a href=&quot;https://www.ibm.com/think/topics/digital-asset-management&quot;&gt;Digital Asset Management&lt;/a&gt;, refers to the process of organizing, storing, and managing any digital asset—including videos. Over time, DAM has become essential for businesses to maintain efficiency, streamline workflows, and ensure brand consistency across teams.&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK supports DAM by giving your team the ability to organize, edit, and repurpose video content within a centralized, embeddable system. Within the React video editor component, users can easily adapt and edit their assets, ensuring brand consistency while automatically propagating changes across multiple assets.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;Video templates&lt;/a&gt; support placeholders and permissions to guide users’ designs, guaranteeing that all assets stay on-brand. While CE.SDK does not directly support role-based permissions, it can be integrated with any backend technology or framework to control user access.&lt;/p&gt;
&lt;p&gt;Keep in mind that the SDK is also extendable. That way, developers can create custom hooks that check permissions and customize the editor’s behavior accordingly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marketing Automation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK provides &lt;a href=&quot;https://img.ly/industries/marketing-tech&quot;&gt;marketing tech&lt;/a&gt; to efficiently craft branded, campaign-specific videos at scale.&lt;/p&gt;
&lt;p&gt;Features like pre-designed, editable, and customizable designs help save time in video production and management. Changes to these templates can be automatically propagated, also eliminating the need for manual updates.&lt;/p&gt;
&lt;p&gt;The SDK also supports advanced scenarios like A/B testing, so that your marketing teams can campaign reach by comparing different solutions to see how they perform. Plus, the ability to generate customized videos with &lt;a href=&quot;https://img.ly/docs/cesdk/react/create-templates/add-dynamic-content/text-variables-7ecb50/&quot;&gt;configurable text variables&lt;/a&gt; makes personalizing content easier than ever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Personalized Videos for Sales Outreach&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We all know how boring and annoying cold emails can be. Marketers and salespeople understand this too, which is why personalized video messages have become the new frontier for pitching.&lt;/p&gt;
&lt;p&gt;Thanks to CreativeEditor SDK, sales teams can easily produce customized videos tailored to specific clients or leads. These videos are far more engaging than standard emails because they feel like a real conversation.&lt;/p&gt;
&lt;p&gt;Also, the translation capabilities offered by the SDK allow sales teams to reach multiple audiences worldwide, breaking down language barriers and personalizing the message for a broader range of targets. Test this feature in our &lt;a href=&quot;https://img.ly/showcases/cesdk/language/web&quot;&gt;translation and internationalization demo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;E-Learning&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK provides educators with the tools they need to create informative videos. Teachers and coaches can quickly produce professional-quality content without requiring extensive technical skills.&lt;/p&gt;
&lt;p&gt;The SDK enhances the learning experience on your React-based e-learning platform through features like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reusability&lt;/strong&gt;: Build a library of templates that can be easily adapted and integrated into existing materials.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy video production&lt;/strong&gt;: Record, edit, and arrange videos directly within the editor, accessible on desktop, mobile, or tablet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugins for learner interactivity&lt;/strong&gt;: Boost engagement by &lt;a href=&quot;https://img.ly/docs/cesdk/react/user-interface/ui-extensions-d194d1/&quot;&gt;integrating plugins&lt;/a&gt; that add quizzes, polls, and other interactive components within the videos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;customizing-your-creativeeditor-sdk-instance&quot;&gt;Customizing your CreativeEditor SDK Instance&lt;/h2&gt;
&lt;p&gt;CreativeEditor SDK does not offer a static, pre-configured React video editor experience. Quite the opposite, it presents several customization features to tailor the editor to your specific needs and brand requirements.&lt;/p&gt;
&lt;p&gt;The key customization options are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Build Custom UIs&lt;/strong&gt;: Define fully custom user interfaces adapted to your specific use case.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Theming&lt;/strong&gt;: Adjust the editor’s theme to match your app’s design. Choose from built-in themes, generate new ones using the &lt;a href=&quot;https://img.ly/docs/cesdk/react/user-interface/appearance/theming-4b0938/&quot;&gt;theme generator&lt;/a&gt;, or manually create a custom theme. Test theming in our &lt;a href=&quot;https://img.ly/showcases/cesdk/theming/web&quot;&gt;dedicated demo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media Libraries&lt;/strong&gt;: Set up customizable, sortable media libraries. CE.SDK supports integration with third-party libraries accessible via API, such as &lt;a href=&quot;https://img.ly/showcases/cesdk/unsplash-image-assets/web&quot;&gt;Unsplash&lt;/a&gt;, allowing you to easily access and use external media assets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Toolbar Customization&lt;/strong&gt;: Reposition toolbar elements, change icons, or rename tools to suit your needs, providing a unique editing experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internationalization&lt;/strong&gt;: Adapt the video editor component to different languages and regions. CE.SDK offers &lt;a href=&quot;https://img.ly/docs/cesdk/react/user-interface/localization-508e20/&quot;&gt;full i18n support&lt;/a&gt;, enabling you to overwrite and extend all text strings in any language.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Integrating a React video editor into your web app can significantly enhance the user experience and serve as a valuable feature to boost retention, engagement, and potential product distribution. This holds true whether you are building a social media platform, a tool for influencers, a marketing SaaS, or an e-learning system.&lt;/p&gt;
&lt;p&gt;With CreativeEditor SDK, you can quickly add a fully customizable video editing experience to your React application in just minutes.&lt;/p&gt;
&lt;p&gt;By following the steps outlined in this blog post, you can bring professional-level video editing features to your web users. Explore CE.SDK’s video capabilities and &lt;a href=&quot;https://img.ly/docs/cesdk/react/prebuilt-solutions/video-editor-9e533a/&quot;&gt;dive into the docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Stay tuned for more updates, and please &lt;a href=&quot;https://img.ly/forms/contact-sales?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=plugins1&quot;&gt;reach out&lt;/a&gt; if you have any questions. Thank you for reading.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Over 3,000 creative professionals gain early access to our new features, demos, and updates—don’t miss out, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i?ref=img.ly&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter.&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;</content:encoded><dc:creator>Antonello</dc:creator><media:content url="https://blog.img.ly/2025/01/video-editor-react.jpg" medium="image"/><category>React</category><category>How-To</category><category>Video Editor</category></item><item><title>A Modern Angular Video Editor: Setup Guide</title><link>https://img.ly/blog/a-modern-angular-video-editor/</link><guid isPermaLink="true">https://img.ly/blog/a-modern-angular-video-editor/</guid><description>Learn how to integrate IMG.LY&apos;s video editor for Angular into your web app and how to best leverage its capabilities.</description><pubDate>Wed, 08 Jan 2025 08:19:25 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Learn how to integrate&lt;/em&gt; &lt;a href=&quot;https://img.ly/docs/cesdk/angular/starterkits/video-editor-e1nlor/&quot;&gt;&lt;em&gt;IMG.LY’s video editor&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for Angular into your web application and get the most out of it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;TikTok, Instagram, Facebook, WhatsApp Messenger, YouTube, and X are among the most popular social media platforms. They consistently rank in the top 10 most visited websites and downloaded mobile apps globally. Have you ever asked what is the common thread between them? Video content!&lt;/p&gt;
&lt;p&gt;These platforms have revolutionized how we consume video content. Videos are now shorter, often include subtitles for silent viewing, and are designed to be engaging, professionally produced, and artfully crafted.The challenge lies in meeting user expectations, as modern web applications are now expected to offer intuitive video creation and editing tools. After all, Instagram and TikTok have set the bar quite high when it comes to seamless video production.&lt;/p&gt;
&lt;p&gt;This guide will walk you through implementing a video editor in your Angular web app using CreativeEditor SDK (&lt;em&gt;CE.SDK&lt;/em&gt;). We will also take a look at some scenarios where this video editing is useful and explain how to customize the editor to meet your unique requirements.To jumpstart your project, check out the &lt;a href=&quot;https://github.com/imgly/cesdk-web-examples/tree/main/integrate-with-angular&quot;&gt;GitHub repository for Angular video editor integration&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let’s dive in!&lt;/p&gt;
&lt;h2 id=&quot;why-add-a-video-editor-to-an-angular-application&quot;&gt;Why Add a Video Editor to an Angular Application?&lt;/h2&gt;
&lt;p&gt;Over the past few months, AI has been revolutionizing the tech industry. It all started with AI-generated text and images, but what is next on the horizon? AI-generated videos!&lt;/p&gt;
&lt;p&gt;The appeal is clear—numerous studies show that video is the most engaging medium, resonating deeply with us as humans. This is no surprise, given that &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_most-visited_websites&quot;&gt;YouTube and Instagram rank among the top five most visited websites&lt;/a&gt;, and &lt;a href=&quot;https://www.statista.com/statistics/1285960/top-downloaded-mobile-apps-worldwide/&quot;&gt;TikTok is the most downloaded app worldwide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The problem is that users now demand more than just video content. They expect engaging, professionally edited videos. On top of that, platforms like Instagram and TikTok have raised the bar for intuitive video production and editing. &lt;/p&gt;
&lt;p&gt;As a result, we all expect to be able to add filters, overlays, audio, music, and text to videos with just a few clicks. Meeting these expectations is essential for any application offering video generation features.&lt;/p&gt;
&lt;p&gt;Adding an easy-to-use video editor into your Angular project gives users a powerful tool that they are likely to desire and are already familiar with. That will surely boosts user engagement and help you accelerate the distribution of your online product or service!&lt;/p&gt;
&lt;h2 id=&quot;how-to-set-up-a-video-editor-in-angular&quot;&gt;How to Set Up a Video Editor in Angular&lt;/h2&gt;
&lt;p&gt;In this section, you will learn how to integrate an Angular video editor into your wev application through CreativeEditor SDK.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;br&gt;
Before you begin, make sure you have the latest LTS version of Node.js installed on your machine. If that is not your case, download and install it from the &lt;a href=&quot;https://nodejs.org/en/download&quot;&gt;official Node.js website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next, open your terminal and run the following command to install the &lt;a href=&quot;https://angular.dev/tools/cli&quot;&gt;Angular CLI&lt;/a&gt; globally:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; -g&lt;/span&gt;&lt;span&gt; @angular/cli&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will make it easy to create and manage Angular projects.&lt;/p&gt;
&lt;p&gt;Once the installation is complete, if you don’t have an Angular project set up, initialize a new Angular project by running:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ng&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; my-angular-video-editor-app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will be prompted with a few questions:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Would you like to share pseudonymous usage data about this project with the Angular Team at Google under Google&apos;s Privacy Policy at https://policies.google.com/privacy. For more details and how to change this setting, see https://angular.dev/cli/analytics.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;No&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Global setting: disabled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Local setting: No local workspace configuration file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Effective status: disabled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;✔ Which stylesheet format would you like to use? CSS [ https://developer.mozilla.org/docs/Web/CSS ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;✔ Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? No&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are unsure, press Enter to accept the default answer.&lt;/p&gt;
&lt;p&gt;After the project is created, navigate to the project folder and install the CreativeEditor SDK (&lt;a href=&quot;https://www.npmjs.com/package/@cesdk/cesdk-js&quot;&gt;@cesdk/cesdk-js&lt;/a&gt;) npm package by running:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;npm install @cesdk/cesdk-js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Your &lt;strong&gt;package.json&lt;/strong&gt; file will now include the SDK as a dependency:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/animations&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/common&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/compiler&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/core&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/forms&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/platform-browser&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/platform-browser-dynamic&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@angular/router&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^19.0.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;@cesdk/cesdk-js&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^1.41.1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;rxjs&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;~7.8.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;tslib&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;^2.3.0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &quot;zone.js&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;~0.15.0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open your project in a JavaScript IDE, as you are ready to start coding!&lt;/p&gt;
&lt;h3 id=&quot;create-a-video-editor-component&quot;&gt;Create a Video Editor Component&lt;/h3&gt;
&lt;p&gt;First, use the Angular CLI to generate the scaffold for your video editor component:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ng&lt;/span&gt;&lt;span&gt; generate&lt;/span&gt;&lt;span&gt; component&lt;/span&gt;&lt;span&gt; video-editor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open the &lt;code&gt;video-editor.component.ts&lt;/code&gt; file inside the &lt;code&gt;src/app/video-editor&lt;/code&gt; folder and initialize your CE.SDK-based Angular video editor component as below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Component, ElementRef, ViewChild } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@angular/core&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK, { Configuration } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@cesdk/cesdk-js&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  selector: &lt;/span&gt;&lt;span&gt;&apos;app-video-editor&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  imports: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  templateUrl: &lt;/span&gt;&lt;span&gt;&apos;./video-editor.component.html&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  styleUrl: &lt;/span&gt;&lt;span&gt;&apos;./video-editor.component.css&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; VideoEditorComponent&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ViewChild&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;cesdk_container&apos;&lt;/span&gt;&lt;span&gt;) containerRef: ElementRef = {} &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; ElementRef&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ngAfterViewInit&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Configuration&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      license: &lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;YOUR_LICENSE&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      userId: &lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;YOUR_USER_ID&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    CreativeEditorSDK.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.containerRef.nativeElement, config).&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; any&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // customize the editor behavior...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        await&lt;/span&gt;&lt;span&gt; instance.&lt;/span&gt;&lt;span&gt;createDesignScene&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;#x3C;YOUR_LICENSE&gt;&lt;/code&gt; with the license key provided by CreativeEditor SDK. Optionally, also set &lt;code&gt;&amp;#x3C;YOUR_USER_ID&gt;&lt;/code&gt; to your user ID to start collecting monthly active user (MAU) data.Then, define video-editor.component.html as below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; #cesdk_container&lt;/span&gt;&lt;span&gt; [style.height.vh]=&quot;&apos;100&apos;&quot;&lt;/span&gt;&lt;span&gt; [style.width.vw]=&quot;&apos;100&apos;&quot;&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way, VideoEditorComponent will be mounted on the above &lt;/p&gt;&lt;div&gt; element.&lt;p&gt;&lt;/p&gt;
&lt;h3 id=&quot;use-the-component&quot;&gt;Use the Component&lt;/h3&gt;
&lt;p&gt;You can now import the component and register it in your &lt;code&gt;app.components.ts&lt;/code&gt; file with these lines of code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Component } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@angular/core&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { RouterOutlet } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@angular/router&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { VideoEditorComponent } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./video-editor/video-editor.component&apos;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;// import the video editor component&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  selector: &lt;/span&gt;&lt;span&gt;&apos;app-root&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  imports: [RouterOutlet, VideoEditorComponent], &lt;/span&gt;&lt;span&gt;// register the video editor component&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  templateUrl: &lt;/span&gt;&lt;span&gt;&apos;./app.component.html&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  styleUrl: &lt;/span&gt;&lt;span&gt;&apos;./app.component.css&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; AppComponent&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  title&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;my-angular-video-editor-app&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, you can use it in app.component.html with:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;app-video-editor&gt;&amp;#x3C;/app-video-editor&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This setup will open the video editor with a predefined video template, allowing users to trim, cut, apply filters, add text overlays, insert music, and make other video enhancements.&lt;/p&gt;
&lt;p&gt;Have a look at our &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;interactive demo&lt;/a&gt; to see what the resultant editor should look like.&lt;/p&gt;
&lt;h2 id=&quot;use-cases-the-your-angular-video-editor&quot;&gt;Use Cases the Your Angular Video Editor&lt;/h2&gt;
&lt;p&gt;After learning how to create an Angular video editor component with a basic CreativeEditor SDK integration, it is time to explore some practical use cases in real-world scenarios.&lt;/p&gt;
&lt;h3 id=&quot;video-messages-for-marketing-outreach&quot;&gt;Video Messages for Marketing Outreach&lt;/h3&gt;
&lt;p&gt;Cold emails often come across as generic and impersonal, often ending up in spam or being ignored. In contrast, personalized &lt;a href=&quot;https://www.linkedin.com/pulse/harnessing-power-video-messages-sales-outreach-oliveira-phd--fqrle/&quot;&gt;video messages are transforming marketing outreach&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK enables marketers to create compelling videos that stand out from standard email approaches with capabilities like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Personalized Video Messages for Leads&lt;/strong&gt;: Create tailored videos for individual clients or prospects, adding a personal touch to your marketing outreach efforts and make a stronger impact compared to traditional cold emails.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Global Reach with Translation Features&lt;/strong&gt;: Use the SDK’s built-in translation and internationalization tools to engage with a global audience. Customize messages to fit local cultures and ensure a personalized experience. Try out this feature in our &lt;a href=&quot;https://img.ly/showcases/cesdk/language/web&quot;&gt;translation demo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;educational-videos-for-e-learning-platforms&quot;&gt;Educational Videos for E-Learning Platforms&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK offers users in the e-learning industry an intuitive tool to create engaging and educational videos. &lt;/p&gt;
&lt;p&gt;Educators, teachers, and coaches do not need technical skills, as video creation is simple and accessible. Specifically, users can record, edit, and organize videos across desktop, mobile, or tablet browsers with just a few clicks. &lt;/p&gt;
&lt;p&gt;The SDK simplifies content creation through reusable templates. Instructors can integrate their materials into those template to maintain consistency while covering different topics. Finally, support for &lt;a href=&quot;https://img.ly/docs/cesdk/angular/user-interface/ui-extensions-d194d1/&quot;&gt;interactive plugins&lt;/a&gt;—such as quizzes, polls, and other engagement tools—adds a dynamic layer to video lessons.&lt;/p&gt;
&lt;h3 id=&quot;video-content-for-social-media&quot;&gt;Video Content for Social Media&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK simplifies the process of producing shareable videos for social media sites like Instagram, TikTok, YouTube, but also LinkedIn and others. That is possible thanks to features like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reusable Templates&lt;/strong&gt;: Start with video templates from other creators or design your own and share them with the community. By choosing from a variety of pre-designed templates for different needs, users can avoid the frustration of starting from scratch and bring their ideas to life quickly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Animations&lt;/strong&gt;: Access a broad &lt;a href=&quot;https://img.ly/docs/cesdk/angular/animation/overview-6a2ef2/&quot;&gt;selection of customizable animations&lt;/a&gt; to enhance the visual appeal of video elements, driving higher engagement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audio Library&lt;/strong&gt;: Effortlessly incorporate audio files into your videos, such as music, voiceovers, or sound effects, to set the mood and create an immersive experience for viewers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once a video is created in Angular application with CE.SDK, users can export it in the ideal formats and aspect ratios for different social media platforms.&lt;/p&gt;
&lt;h3 id=&quot;showcase-products-on-e-commerce-applications&quot;&gt;Showcase Products on E-Commerce Applications&lt;/h3&gt;
&lt;p&gt;Images have long been a simple and effective way to showcase products on e-commerce platforms. Many sites, from eBay to Amazon, have used them for years. At the same time, customer expectations have evolved, and they now seek more engaging ways to visualize products.&lt;/p&gt;
&lt;p&gt;Short, dynamic product videos significantly enhance product presentation. In particular, Amazon data shows that &lt;a href=&quot;https://sellercentral.amazon.com/seller-forums/discussions/t/b031f21d-e8e2-49ea-933c-bef293bf9427&quot;&gt;adding videos can boost sales by up to 9.7%&lt;/a&gt;. It is no surprise that many Amazon sellers have already adopted video to showcase their products.&lt;/p&gt;
&lt;p&gt;With a CE.SDK-based Angular video editor, you can easily create videos that work seamlessly across multiple devices for a unified shopping experience. Thanks to reusable templates, you can customize product videos while maintaining scalability and brand consistency.By leveraging multiple templates and feeding them with diverse data, you can generate automated product video variations at scale.&lt;/p&gt;
&lt;h3 id=&quot;smart-and-automated-workflows&quot;&gt;Smart and Automated Workflows&lt;/h3&gt;
&lt;p&gt;CreativeEditor SDK supports the development of a tool for creating branded videos at scale.&lt;/p&gt;
&lt;p&gt;As it is based on ready-made and editable templates, it simplifies video production and management. The reason is that users can define these templates once through an intuitive point-and-click interface, then effortlessly customize the produced videos via different input resources or &lt;a href=&quot;https://img.ly/docs/cesdk/angular/create-templates/add-dynamic-content/text-variables-7ecb50/&quot;&gt;configurable text variables&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;That automated workflow process boosts productivity and scalability. The SDK also supports advanced features like &lt;a href=&quot;https://www.oracle.com/cx/marketing/what-is-ab-testing/&quot;&gt;A/B testing&lt;/a&gt;. That way, teams can create multiple versions of a campaign video, distribute them on social platforms, and compare their performance.&lt;/p&gt;
&lt;h2 id=&quot;customizing-your-creativeeditor-sdk-instance&quot;&gt;Customizing your CreativeEditor SDK Instance&lt;/h2&gt;
&lt;p&gt;CreativeEditor SDK features a versatile Angular video editor experience that can be easily configured and customized to fit your specific requirements and visual preferences.Key customization options supported by CE.SDK include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Feature Activation&lt;/strong&gt;: Enable or disable features as you need, so that you can control the functionality available to users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom UIs&lt;/strong&gt;: Create fully personalized user interfaces, adapting the editor to your unique use case. This includes repositioning toolbar elements, changing icons, or renaming tools for a tailored editing experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internationalization&lt;/strong&gt;: Adapt the video editor for different languages and regions. CE.SDK provides &lt;a href=&quot;https://img.ly/docs/cesdk/angular/user-interface/localization-508e20/&quot;&gt;full support for internationalization&lt;/a&gt;, enabling you to customize all text strings in any language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Export Options&lt;/strong&gt;: Configure which file formats users can select for exporting, along with settings for quality, dimensions, and more.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Role Customization&lt;/strong&gt;: &lt;a href=&quot;https://img.ly/docs/cesdk/angular/configuration-2c1c3d/&quot;&gt;CE.SDK supports roles&lt;/a&gt;, which are a set of global settings and scopes. When the role changes, the default settings for that role are applied. You can also use a callback to adjust configurations whenever the role changes and define custom roles to tailor settings for specific user needs or workflows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media Libraries:&lt;/strong&gt; Create custom, sortable media libraries. CE.SDK supports integration with third-party libraries via API, offering easy access to external media assets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose the Start Video:&lt;/strong&gt; Set the editor to display a predefined video at the start, eliminating the blank canvas effect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Theming&lt;/strong&gt;: Adjust the editor’s theme to match your app’s design. You can select from built-in themes, generate new ones using the &lt;a href=&quot;https://img.ly/docs/cesdk/angular/user-interface/appearance/theming-4b0938/&quot;&gt;theme generator&lt;/a&gt;, or manually create a custom theme. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See all of these customizations in action in our &lt;a href=&quot;https://img.ly/showcases/cesdk?tags=customization&quot;&gt;customization demo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Adding an video editor to your Angular site or web application greatly enhances user experience. Such a feature drives product success by improving user reviews and increasing retention. Whether you are creating a marketing tool, an e-learning or e-commerce platform, or any web app with social media functionality, a video editor adds immense value.&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK gives you what you need to implement a fully customizable video editing solution into your Angular application in minutes.&lt;/p&gt;
&lt;p&gt;By following the steps in this guide, you learned how to equip your users with a professional and intuitive video editing experience. Explore CE.SDK’s video capabilities and &lt;a href=&quot;https://img.ly/docs/cesdk/angular/prebuilt-solutions/video-editor-9e533a/&quot;&gt;dive into the docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Stay tuned for more updates, and please &lt;a href=&quot;https://img.ly/forms/contact-sales?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=plugins1&quot;&gt;reach out&lt;/a&gt; if you have any questions. Thank you for reading.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Over 3,000 creative professionals gain early access to our new features, demos, and updates—don’t miss out, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i?ref=img.ly&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter.&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;</content:encoded><dc:creator>Antonello</dc:creator><media:content url="https://blog.img.ly/2025/01/video-editor-angular.jpg" medium="image"/><category>Angular</category><category>How-To</category><category>Video Editor</category></item><item><title>A Modern Video Editor SDK for Your React Native App</title><link>https://img.ly/blog/a-modern-video-editor-sdk-for-your-react-native-app/</link><guid isPermaLink="true">https://img.ly/blog/a-modern-video-editor-sdk-for-your-react-native-app/</guid><description>Learn how to integrate IMG.LY&apos;s video editor for React Native into your app and how to best leverage its capabilities.</description><pubDate>Mon, 06 Jan 2025 10:40:35 GMT</pubDate><content:encoded>&lt;p&gt;Learn how to integrate &lt;a href=&quot;https://img.ly/docs/cesdk/react-native/prebuilt-solutions/video-editor-9e533a/&quot;&gt;IMG.LY’s video editor for React Native&lt;/a&gt; into your app and how to leverage its capabilities best.&lt;/p&gt;
&lt;h2 id=&quot;why-add-a-video-editor-to-your-react-native-app&quot;&gt;Why Add a Video Editor to Your React Native App?&lt;/h2&gt;
&lt;p&gt;Video content is solidifying its status as the most engaging form of digital media. Platforms like TikTok, Instagram Reels, and YouTube Shorts have made video consumption and creation an engrained habit with billions of users. You can harness this trend by adding a video editor to your app significantly enhancing user engagement and retention.&lt;/p&gt;
&lt;p&gt;React Native, with its ability to create cross-platform applications from a single codebase, is a perfect match for IMG.LY’s &lt;strong&gt;CreativeEditor SDK Video Editor&lt;/strong&gt;. It ensures seamless performance on iOS and Android, powered by the same unified graphics engine across platforms.&lt;/p&gt;
&lt;p&gt;Whether your app focuses on social media, marketing, or eCommerce, integrating a video editor empowers users with a creative tool set while elevating the overall experience.&lt;/p&gt;
&lt;h2 id=&quot;getting-started-integrating-the-video-editor-in-react-native&quot;&gt;Getting Started: Integrating the Video Editor in React Native&lt;/h2&gt;
&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;
&lt;p&gt;Before diving into the integration, ensure your environment meets these requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;React Native&lt;/strong&gt;: 0.73+&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;iOS&lt;/strong&gt;: 16+&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Swift&lt;/strong&gt;: 5.10 (Xcode 15.4)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Android&lt;/strong&gt;: 7+&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To get started, add the &lt;strong&gt;@imgly/editor-react-native&lt;/strong&gt; package to your project:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; @imgly/editor-react-native&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;setting-up-the-editor&quot;&gt;Setting Up the Editor&lt;/h3&gt;
&lt;p&gt;Once the package is installed, initialize the editor by importing the necessary modules and creating an instance of &lt;code&gt;EditorSettingsModel&lt;/code&gt;. You’ll need a license key, which you can obtain from the IMG.LY dashboard.&lt;/p&gt;
&lt;p&gt;Here’s how to set up and launch the video editor:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;tsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; IMGLYEditor, { EditorSettingsModel } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@imgly/editor-react-native&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; const&lt;/span&gt;&lt;span&gt; openVideoEditor&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; async&lt;/span&gt;&lt;span&gt; ()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Promise&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; settings&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; EditorSettingsModel&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    license: &lt;/span&gt;&lt;span&gt;&apos;YOUR_LICENSE_KEY&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; result&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; IMGLYEditor.&lt;/span&gt;&lt;span&gt;openEditor&lt;/span&gt;&lt;span&gt;(settings);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This launches the editor with the &lt;strong&gt;Video Editor&lt;/strong&gt; preset, enabling users to trim, cut, and enhance their videos with filters, text overlays, stickers, and music.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1080px) 1080px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1080&quot; height=&quot;1080&quot; src=&quot;https://img.ly/_astro/Video-UI_Z17RDlV.webp&quot; srcset=&quot;/_astro/Video-UI_Z1hzsFw.webp 640w, /_astro/Video-UI_ZUG5b8.webp 750w, /_astro/Video-UI_Oc4wg.webp 828w, /_astro/Video-UI_Z17RDlV.webp 1080w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;use-cases-building-a-tiktok-like-experience&quot;&gt;Use Cases: Building a TikTok-Like Experience&lt;/h2&gt;
&lt;p&gt;Now that the video editor is integrated into your React Native app, let’s explore some key use cases and how to configure the editor to support them.&lt;/p&gt;
&lt;h3 id=&quot;short-form-video-creation&quot;&gt;Short-Form Video Creation&lt;/h3&gt;
&lt;p&gt;For apps targeting TikTok-style short-form video content, prioritize features that simplify the editing process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Timeline Control&lt;/strong&gt;: Allow users to trim clips and sync overlays like stickers or music.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filters &amp;#x26; Effects&lt;/strong&gt;: Offer filters to let users add certain moods to their videos with themes like retro, high contrast, or pastel tones.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Text &amp;#x26; Stickers&lt;/strong&gt;: Add captions and playful stickers for videos that are often consumed on mute.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music &amp;#x26; Audio&lt;/strong&gt;: Let users add soundtracks or sound effects, with a library of trending music for inspirational background music.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Video Templates&lt;/strong&gt;: Provide ready-made templates that users can customize for specific occasions or themes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This setup allows influencers and brands to create professional-looking videos that they can share across social media platforms with ease.&lt;/p&gt;
&lt;h3 id=&quot;influencers-and-marketing&quot;&gt;Influencers and Marketing&lt;/h3&gt;
&lt;p&gt;If your app serves influencers or businesses, the ability to create polished, on-brand videos is key. Features to consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Branded Templates&lt;/strong&gt;: Pre-designed templates aligned with specific brand aesthetics, simplifying content creation for marketing campaigns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watermarks&lt;/strong&gt;: Add brand logos or watermarks to videos, ensuring creators and brands maintain visibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These features empower influencers and businesses to quickly generate content that’s ready for distribution across platforms.&lt;/p&gt;
&lt;h3 id=&quot;e-commerce-and-user-generated-content&quot;&gt;E-commerce and User-Generated Content&lt;/h3&gt;
&lt;p&gt;Video editing is a powerful tool for e-commerce apps, enabling sellers and customers to create engaging product demos, unboxing videos, reviews and tutorials. Features like trimming, filters, and music tools make it easy to produce compelling content that enhances the shopping experience.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vendors can create promotional videos for products.&lt;/li&gt;
&lt;li&gt;Customers can share authentic reviews or tutorials, increasing trust and boosting sales.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;customization-options-with-creativeeditor-sdk&quot;&gt;Customization Options with CreativeEditor SDK&lt;/h2&gt;
&lt;p&gt;The React Native plugin offers a range of customization options to adapt the editor to your app’s needs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UI Customization&lt;/strong&gt;: Change themes, colors, and layouts to match your app’s branding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Video Presets&lt;/strong&gt;: Configure presets for specific use cases, such as limiting video length or optimizing for a particular resolution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom Assets&lt;/strong&gt;: Add unique filters, stickers, and fonts to create a personalized experience for your audience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Templates&lt;/strong&gt;: Use the CreativeEditor SDK Web UI to create custom templates, enabling users to start with professional-grade designs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Integrating a video editor into your React Native appwill improve your UX, and help boost engagement, retention, and potential distribution of your product, whether you’re building a social media platform, an influencer tool, or an e-commerce app.&lt;br&gt;
With CreativeEditor SDK, you can create a TikTok-like video editing experience or offer specialized tools for businesses and creators.&lt;/p&gt;
&lt;p&gt;By following the steps in this guide, you can empower your users to create professional-quality video content directly within your app. Explore the full capabilities of the SDK by visiting the &lt;a href=&quot;https://img.ly/docs/cesdk/react-native/prebuilt-solutions/video-editor-9e533a/&quot;&gt;React Native documentation&lt;/a&gt; and getting started today.&lt;/p&gt;
&lt;p&gt;Stay tuned for updates, and don’t hesitate to &lt;a href=&quot;https://img.ly/forms/contact-sales?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=reactnative&quot;&gt;reach out&lt;/a&gt; with any questions.&lt;/p&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3,000+ creative professionals gain early access to new features and updates—don’t miss out, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i?ref=img.ly&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Jan</dc:creator><media:content url="https://blog.img.ly/2024/12/how-to-react-native-video-editor-sdk.jpg" medium="image"/><category>React Native</category><category>How-To</category><category>Video Editor</category><category>Expo</category></item><item><title>CE.SDK Video Editor Now Available on Android</title><link>https://img.ly/blog/ce-sdk-video-editor-now-available-on-android/</link><guid isPermaLink="true">https://img.ly/blog/ce-sdk-video-editor-now-available-on-android/</guid><description>Integrate a fully-customizable Video Editor into your Android App with CE.SDK.</description><pubDate>Tue, 22 Oct 2024 11:44:02 GMT</pubDate><content:encoded>&lt;p&gt;We are excited to announce the release of CE.SDK’s video editing and video content creation tools for Android!&lt;/p&gt;
&lt;p&gt;After the successful iOS launch, CE.SDK’s professional video editing capabilities are now available for Android. Whether your app focuses on social media, e-commerce, or marketing technology, CE.SDK enables users to create high-quality videos directly within your app.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/1-36/uncompressed/Android-crop-split-trim.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Getting up and running with an instance of the CE.SDK video editor for Android is easy.&lt;/p&gt;
&lt;p&gt;After downloading your license (get your trial license here) from your dashboard, simply &lt;a href=&quot;https://img.ly/docs/cesdk/android/prebuilt-solutions/video-editor-9e533a/&quot;&gt;invoke &lt;code&gt;VideoEditor&lt;/code&gt; as composable function, Activity or Fragment.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;our-video-editing-backstory&quot;&gt;Our Video Editing Backstory&lt;/h2&gt;
&lt;p&gt;Since we launched VideoEditor SDK almost ten years ago, we have seen an astounding range of creative and unique use cases of our SDK in customer projects. From Cameo connecting celebrities and their fans in new ways, over Multibrain supercharging their users marketing campaigns with editable video content, to &lt;a href=&quot;https://zigazoo.com/&quot;&gt;Zigazoo&lt;/a&gt; powering video content within their social network for kids while putting safety and parental control first.&lt;/p&gt;
&lt;p&gt;Since then, millions of users have experienced IMG.LY’s VideoEditor SDK through our customers’ products, shaping how they expect to interact with and modify videos. Continuous feedback from both our customers and their users has also influenced the way we approach video interface design, helping us refine and innovate along the way.&lt;/p&gt;
&lt;p&gt;Our goal was to combine the reliability and robustness of the VideoEditor SDK with true cross-platform compatibility and the flexibility to meet diverse needs. By applying the lessons we’ve learned, we aimed to deliver an exceptional video editing user experience straight out of the box. We described how those learnings shaped the &lt;a href=&quot;https://img.ly/blog/designing-a-timeline-for-mobile-video-editing/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=androidvideo&quot;&gt;design of the mobile video editing interface.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;key-capabilities&quot;&gt;Key Capabilities&lt;/h2&gt;
&lt;p&gt;With CE.SDK’s sleek timeline interface, your Android users can now take their video editing from simple transforms and adjustments to complex composition and multi-track editing:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Timeline-Based Editing&lt;/strong&gt;&lt;br&gt;
Split, trim, arrange video and audio tracks. Position elements such as images and stickers on the timeline and control their duration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multi-Track Editing&lt;/strong&gt;&lt;br&gt;
Work with multiple video and audio tracks, allowing for complex composition.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Transform &amp;#x26; Enhance&lt;/strong&gt;&lt;br&gt;
Crop, flip, rotate, and use presets for common video formats. Add filters, effects, blur and essential adjustments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Customizable Templates&lt;/strong&gt;&lt;br&gt;
Create and import templates using our web video editor, to jumpstart your users’ video composition and designs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Asset Integration&lt;/strong&gt;&lt;br&gt;
Integrate your own asset libraries for audio tracks, sound effects, images, and more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-platform Interoperability&lt;/strong&gt;&lt;br&gt;
CE.SDK’s video capabilities extends across iOS, Android and the Web, enabling cross-platform applications to offer seamless video editing capabilities. Users can edit and save work in progress and pick up on any device.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/android?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=androidvideo&quot;&gt;showcase app for an interactive demo&lt;/a&gt; of these features.&lt;/p&gt;
&lt;h2 id=&quot;customization&quot;&gt;Customization&lt;/h2&gt;
&lt;p&gt;The ability to tailor the video editor to your app’s particular use case has been a front and center concern in its development.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/android/configuration-2c1c3d/&quot;&gt;&lt;strong&gt;UI Customization&lt;/strong&gt;&lt;/a&gt;: While theming is currently limited to &lt;code&gt;dark&lt;/code&gt; and &lt;code&gt;light&lt;/code&gt; model, future releases will introduce more flexible theming, allowing you to modify the look and feel of the editor to match your app’s branding. Furthermore, we expose &lt;strong&gt;callbacks&lt;/strong&gt; that make it possible to hook into editor events and &lt;strong&gt;overlays&lt;/strong&gt; for custom dialogues.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/android/create-video-c41a08/&quot;&gt;&lt;strong&gt;Configure Video Presets&lt;/strong&gt;&lt;/a&gt;: You can configure the editor to create video presets based on your users’ needs. For instance, you may want to fix the video’s aspect ratio or optimize for certain resolutions, depending on the target platform.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/android/use-templates/apply-template-35c73e/&quot;&gt;&lt;strong&gt;Video Templates&lt;/strong&gt;&lt;/a&gt;: With the CE.SDK video editor web UI, you can create an unlimited number of video templates, such as collages, text designs, and animations, providing your users with professional-quality starting points for their video designs.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/android/import-media/asset-panel/customize-c9a4de/&quot;&gt;&lt;strong&gt;Assets&lt;/strong&gt;&lt;/a&gt;: Provide custom filters, fonts, and stickers to enhance the user experience. For niche apps, this can be an excellent way to engage users by offering content that feels unique to your community.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;ideal-for-social-media-ecommerce-and-marketing-tech-apps&quot;&gt;Ideal for Social Media, Ecommerce, and Marketing Tech Apps&lt;/h2&gt;
&lt;p&gt;CE.SDK’s new Android video editing capabilities are perfect for a variety of use cases, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/use-cases/story-reels-short-video-creation&quot;&gt;&lt;strong&gt;Social Media Applications&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; The CE.SDK video editor for Android excels at short-form video, ideal for social media applications, whether your users are publishing to other networks or you run a network yourself.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/industries/e-commerce&quot;&gt;&lt;strong&gt;Ecommerce&lt;/strong&gt;&lt;/a&gt;: Allow your users to create engaging product showcases, ads, and promotional videos, testimonials or reviews.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/industries/marketing-tech&quot;&gt;&lt;strong&gt;Marketing Tech Platforms&lt;/strong&gt;&lt;/a&gt;: Users can leverage our versatile templating to easily create polished social media and marketing graphics from within your app.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next?&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Camera UI: Record videos on Android.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;988&quot; src=&quot;https://img.ly/_astro/camera-UI-Android-1_1FyMRS.webp&quot; srcset=&quot;/_astro/camera-UI-Android-1_ZjEi38.webp 640w, /_astro/camera-UI-Android-1_Z743FA.webp 750w, /_astro/camera-UI-Android-1_ZYwhh4.webp 828w, /_astro/camera-UI-Android-1_8a3zG.webp 1080w, /_astro/camera-UI-Android-1_19mjIs.webp 1280w, /_astro/camera-UI-Android-1_1FyMRS.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;This Android release is just the beginning! We are about to launch a &lt;strong&gt;Camera UI&lt;/strong&gt; for Android and are working on more advanced template creation features. So stay tuned.&lt;br&gt;
To see some of these features in action, check out our iOS demo, where the next phase of innovation is unfolding.&lt;/p&gt;
&lt;h2 id=&quot;get-started&quot;&gt;Get Started&lt;/h2&gt;
&lt;p&gt;Explore our &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/android?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=androidvideo&quot;&gt;Video UI Showcase&lt;/a&gt; and &lt;a href=&quot;https://img.ly/docs/cesdk/android/prebuilt-solutions/video-editor-9e533a/&quot;&gt;Documentation for Android&lt;/a&gt; to discover how CE.SDK can streamline your content creation projects and make Android video editing easier than ever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Over 3,000 creative professionals gain early access to new features and updates—don’t miss out, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Jan</dc:creator><media:content url="https://blog.img.ly/2024/10/android-video-editor-sdk-imgly-creative-editor_s.jpg" medium="image"/><category>Android</category><category>Android App Development</category><category>Creative Editor</category><category>Video Editing</category><category>Video Editor</category></item><item><title>CE.SDK v1.21 Release Notes</title><link>https://img.ly/blog/creative-editor-sdk-v-1-21-0-release-notes/</link><guid isPermaLink="true">https://img.ly/blog/creative-editor-sdk-v-1-21-0-release-notes/</guid><description>Create stunning videos using a brand-new timeline for web.</description><pubDate>Thu, 22 Feb 2024 16:22:28 GMT</pubDate><content:encoded>&lt;p&gt;Since our &lt;a href=&quot;https://img.ly/blog/creative-editor-sdk-v_1_20_0-release-notes/&quot;&gt;last release&lt;/a&gt;, we’ve been crafting new features to empower your users’ creative journey. Today, we are happy to introduce CE.SDK v1.21!&lt;/p&gt;
&lt;h3 id=&quot;create-videos-with-a-new-timeline-for-web&quot;&gt;Create Videos With A New Timeline for Web&lt;/h3&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/1-21/video-for-web-121-s.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Create eye-catching videos within your web app for any platform, including Instagram, TikTok, or YouTube! Here’s what’s new: the integrated &lt;strong&gt;timeline&lt;/strong&gt; supports the arrangement of elements like videos, photos, text, audio, shapes and stickers. Users can fine-tune their projects with adjustments or filters, and personalize their creations with audio from a customizable library.&lt;/p&gt;
&lt;p&gt;To simplify your content creation, use our formats that automatically &lt;strong&gt;set your canvas size&lt;/strong&gt; &lt;strong&gt;for social media&lt;/strong&gt; and other popular video resolutions.&lt;/p&gt;
&lt;p&gt;Effectively &lt;strong&gt;arrange&lt;/strong&gt; and edit multiple elements within your videos, offering precise control over the editing process. Easily split, trim, and replace. Lastly, make it pop by adding audio files to the composition.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Refine designs in our Showcase by customizing templates: adjust filters, swap visuals or audio, including integration with Soundstripe for premium stock audio.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1964px) 1964px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1964&quot; height=&quot;1468&quot; src=&quot;https://img.ly/_astro/grafik-1_1f8RgA.webp&quot; srcset=&quot;/_astro/grafik-1_Z270Y1B.webp 640w, /_astro/grafik-1_mTAMV.webp 750w, /_astro/grafik-1_1wMhS0.webp 828w, /_astro/grafik-1_Z1e88GP.webp 1080w, /_astro/grafik-1_ZhzA1h.webp 1280w, /_astro/grafik-1_27z0Wj.webp 1668w, /_astro/grafik-1_1f8RgA.webp 1964w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Creating &lt;strong&gt;templates&lt;/strong&gt; with placeholders for your users is just as easy. Simply select an element, click ‘Placeholder’, and decide which elements can be edited.&lt;/p&gt;
&lt;p&gt;To integrate, browse our &lt;a href=&quot;https://img.ly/docs/cesdk/js/prebuilt-solutions/video-editor-9e533a/&quot;&gt;Guide&lt;/a&gt;. Try the &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;video editor live demo&lt;/a&gt; yourself. This showcase contains templates, audio and video examples for you to try.&lt;/p&gt;
&lt;h3 id=&quot;keep-designs-in-focus-on-ios&quot;&gt;Keep Designs in Focus on iOS&lt;/h3&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/1-21/iOS-zoom-apparel-designer-sdk.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Our new Camera Zoom Limits make editing a design easier. Your page stays in focus to &lt;strong&gt;avoid accidental scrolling&lt;/strong&gt; outside the design. The zoom level is set within a minimum and maximum range, ensuring a practical, usable view at all times. When you select an element in your design, it stays in focus when opening adjustments or other inspectors. It allows you to immediately see changes made to the selected element. This improvement is available for iOS and Android, and can be tested in our Design Editor Demo on the &lt;a href=&quot;https://apps.apple.com/de/app/img-ly-design-editor/id1672991141&quot;&gt;App Store&lt;/a&gt; and &lt;a href=&quot;https://play.google.com/store/apps/details?id=ly.img.cesdk.catalog&quot;&gt;Google Play&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;ensure-color-purity-in-print&quot;&gt;Ensure Color Purity in Print&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;643&quot; src=&quot;https://img.ly/_astro/1-12_underlayer_Z1gSAz3.webp&quot; srcset=&quot;/_astro/1-12_underlayer_1vaO7T.webp 640w, /_astro/1-12_underlayer_ZiCV0p.webp 750w, /_astro/1-12_underlayer_1QlNIp.webp 828w, /_astro/1-12_underlayer_1J6A8t.webp 1080w, /_astro/1-12_underlayer_Z2iYz7K.webp 1280w, /_astro/1-12_underlayer_Z1gSAz3.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our newly introduced &lt;strong&gt;Underlayer API&lt;/strong&gt; guarantees the preservation of color purity whenever you export designs using our CE.SDK for print. This solution specifically addresses the challenge of maintaining the richness and vibrancy of colors, irrespective of the color of the canvas, which could range from apparel to paper.&lt;/p&gt;
&lt;p&gt;When you’re ready to export your design, this feature adds a special ‘&lt;strong&gt;underbase&lt;/strong&gt;’ layer, underneath your design. This layer, typically a white or specific primer coat, makes sure the final printed colors match your original vision perfectly.&lt;/p&gt;
&lt;h3 id=&quot;very-soon-integrate-short-form-video-creation&quot;&gt;Very soon: Integrate Short-Form Video Creation&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1920px) 1920px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://img.ly/_astro/VCC_head-loading_s_ZTQpN2.webp&quot; srcset=&quot;/_astro/VCC_head-loading_s_Z1FDdaR.webp 640w, /_astro/VCC_head-loading_s_17HiQ3.webp 750w, /_astro/VCC_head-loading_s_5DATp.webp 828w, /_astro/VCC_head-loading_s_69D9S.webp 1080w, /_astro/VCC_head-loading_s_Z1ghRHI.webp 1280w, /_astro/VCC_head-loading_s_ZaUdJP.webp 1668w, /_astro/VCC_head-loading_s_ZTQpN2.webp 1920w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Video remains key for attracting, engaging and retaining audiences, especially on mobile. Creating a video editor can be tough, thus we’re thrilled to soon release our turnkey solution for &lt;strong&gt;mobile video content creation&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Combined with our new &lt;a href=&quot;https://img.ly/products/camera-sdk&quot;&gt;Camera SDK&lt;/a&gt;, users can seamlessly blend video, audio, text, and graphics on a sleek timeline. It includes features like voiceover, zoom, tap to record, and the popular split screen modes for reactions and duets. You may recognize these from Instagram or TikTok!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Last chance:&lt;/strong&gt; &lt;strong&gt;Secure your waitlist spot&lt;/strong&gt; to our Video Content Creation Release. You will also receive access to our TestFlight app.&lt;br&gt;
Registration is only open until March 6, 2024.&lt;/p&gt;
&lt;p&gt;? &lt;a href=&quot;https://share.hsforms.com/1mrIXiBbURn6sMqYgZG9c6A1hk3i&quot;&gt;Gain Access&lt;/a&gt; to our Video Content Creation Release&lt;br&gt;
? &lt;a href=&quot;https://2498814.fs1.hubspotusercontent-na1.net/hubfs/2498814/Newsletter-Digest/nov-2023/IMGLY_VIDEO_SDK.pdf?utm_campaign=Video%20Content%20Creation&amp;#x26;utm_medium=releasenotes&amp;#x26;_hsmi=2&amp;#x26;utm_content=2&amp;#x26;utm_source=blog&quot;&gt;Download Feature Exposé&lt;/a&gt; instantly (PDF)&lt;/p&gt;
&lt;p&gt;We can’t wait to hear your feedback!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading. Join over 3000 specialists with powerful apps, and&lt;/strong&gt; &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter. We keep you in the loop with brand-new features and updates.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Neslihan</dc:creator><media:content url="https://blog.img.ly/2024/02/video-web-editor-sdk-imgly-s.jpg" medium="image"/><category>Release Notes</category><category>Video Editing</category><category>Video Editor</category><category>Web-to-print</category><category>Print</category><category>iOS App Development</category></item><item><title>How To Build a Video Editor With Wasm in React</title><link>https://img.ly/blog/how-to-build-a-video-editor-with-wasm-in-react/</link><guid isPermaLink="true">https://img.ly/blog/how-to-build-a-video-editor-with-wasm-in-react/</guid><description>Use the ffmpeg.wasm library to build a React video editor that performs video processing directly in the browser.</description><pubDate>Mon, 16 Jan 2023 16:31:57 GMT</pubDate><content:encoded>&lt;p&gt;You may think that video processing can only be performed on a server, but this is not true. Thanks to WebAssembly (Wasm), you can run high-performance code written in C or C++ in your browser. This opens up a lot of possibilities and gives you the ability to build a client-side video editor. Let’s now learn how to create a Wasm-based video editor in React.&lt;/p&gt;
&lt;p&gt;Follow this tutorial and learn how to build the application below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Upload and crop your video, and covert it as a GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 671px) 671px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;671&quot; height=&quot;943&quot; src=&quot;https://img.ly/_astro/ffmpeg-video-editor-wasm_1i2zGn.webp&quot; srcset=&quot;/_astro/ffmpeg-video-editor-wasm_1FMujk.webp 640w, /_astro/ffmpeg-video-editor-wasm_1i2zGn.webp 671w&quot;&gt;&lt;/p&gt;
&lt;p&gt;This React video editor allows users to upload a video, select a portion of it, convert it to GIF, and download the resulting image file – all of this in your browser.&lt;/p&gt;
&lt;h2 id=&quot;what-is-webassembly&quot;&gt;What is WebAssembly?&lt;/h2&gt;
&lt;p&gt;WebAssembly (also called Wasm) is a new type of code that modern web browsers can run and understand. Specifically, Wasm provides new functionality to web development and brings significant performance benefits. This applies to both frontend and backend, since Wasm can be used by both clients and servers.&lt;/p&gt;
&lt;p&gt;Wasm code should not be written by hand. This is because Wasm is a binary instruction format. So, Wasm is designed to be a compilation target for source languages such as C, C++, Rust, and others. Learn more about Wasm on the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/WebAssembly&quot;&gt;WebAssembly MDN Web Docs page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wasm provides a way to run code written in several languages on the Web at near-native speed. This means that WebAssembly forms can be easily imported and executed by a Web client or server application. In other words, you can use WebAssembly functions via JavaScript and achieve results that were not previously possible on a browser, especially in terms of performance.&lt;/p&gt;
&lt;h2 id=&quot;what-is-ffmpegwasm&quot;&gt;What is &lt;code&gt;ffmpeg.wasm&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;As stated on the &lt;a href=&quot;https://github.com/ffmpegwasm/ffmpeg.wasm&quot;&gt;GitHub page of the project&lt;/a&gt;, &lt;code&gt;ffmpeg.wasm&lt;/code&gt; is a WebAssembly and JavaScript port of FFmpeg. If you are not familiar with it, FFmpeg is an open-source software suite that includes several libraries and programs for managing audio, video, streams, and other media files. All of these tools can be invoked and executed via the &lt;code&gt;ffmpeg&lt;/code&gt; command-line instruction.&lt;/p&gt;
&lt;p&gt;Therefore, &lt;code&gt;ffmpeg.wasm&lt;/code&gt; enables video and audio processing in JavaScript-based web applications. In detail, it enables video and audio recording, format transcoding, video and audio editing, and video scaling. Even though it is a WebAssembly-based library, you can use it in your JavaScript code just like any other &lt;code&gt;npm&lt;/code&gt; library. This is the power of Wasm.&lt;/p&gt;
&lt;p&gt;Since it transpiles to Wasm, you can take advantage of &lt;code&gt;ffmpeg.wasm&lt;/code&gt; directly in your browser without performance concerns. This means that &lt;code&gt;ffmpeg.wasm&lt;/code&gt; opens the door to client-side audio and video processing. Let’s now learn how to use &lt;code&gt;ffmpeg.wasm&lt;/code&gt; to build a client-side video editor in React!&lt;/p&gt;
&lt;h2 id=&quot;building-a-video-editor-in-react-with-wasm&quot;&gt;Building a Video Editor in React with WASM&lt;/h2&gt;
&lt;p&gt;In this step-by-step tutorial, you will learn how to build a Wasm-based video editor in React with &lt;code&gt;ffmpeg.wasm&lt;/code&gt;. This React video editor application will allow you to upload a video, trim it, and convert it to GIF in the browser, without using any backend functionality or external API.&lt;/p&gt;
&lt;p&gt;Clone the &lt;a href=&quot;https://github.com/imgly/video-editor-wasm-react&quot;&gt;GitHub repository that supports the tutorial&lt;/a&gt; and try the video editor application by launching the following commands:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;git clone https://github.com/Tonel/video-editor-wasm-react&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cd video-editor-wasm-react&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm run start&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s waste no more time and see how to build a video editor application in React.&lt;/p&gt;
&lt;h3 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;This is the list of libraries the video editor application you are about to build depends on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nodejs.org/en/download/package-manager&quot;&gt;Node.js and npm 8+ and higher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/main/CHANGELOG.md#1820-june-14-2022&quot;&gt;React 18.2+&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[ffmpeg.wasm](https://github.com/ffmpegwasm/ffmpeg.wasm)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[antd](https://www.npmjs.com/package/antd)&lt;/code&gt; &gt;= 4.3&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[video-react](https://www.npmjs.com/package/video-react)&lt;/code&gt; &gt;= 0.15&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;antd&lt;/code&gt; is one of the most popular UI libraries for React. In this tutorial, its &lt;code&gt;[Slider](https://ant.design/components/slider/)&lt;/code&gt; component will be used to implement the video cutting feature. So, any other UI library including a slider component with a &lt;code&gt;range&lt;/code&gt; option will do.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;video-react&lt;/code&gt; is one of the most advanced and reliable HTML5 video players for React. You can replace it with any other React video player library.&lt;/p&gt;
&lt;h3 id=&quot;initializing-a-react-project&quot;&gt;Initializing a React Project&lt;/h3&gt;
&lt;p&gt;Let’s initialize a new &lt;a href=&quot;https://create-react-app.dev/docs/getting-started/&quot;&gt;Create React App&lt;/a&gt; React project called &lt;code&gt;video-editor-wasm-react&lt;/code&gt; with the command below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npx create-react-app video-editor-wasm-react&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your &lt;code&gt;video-editor-wasm-react&lt;/code&gt; directory should now contain the following files:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;video-editor-wasm-react&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── node_modules&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── package.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── .gitignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── public&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── favicon.ico&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── index.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── logo192.png&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── logo512.png&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── manifest.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── robots.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── App.css&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── App.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── App.test.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── index.css&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── index.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── logo.svg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├── reportWebVitals.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    └── setupTests.js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enter the &lt;code&gt;video-editor-wasm-react&lt;/code&gt; folder in your terminal and launch a React local server with the commands below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cd video-editor-wasm-react&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm start&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, visit the &lt;code&gt;[http://localhost:3000/](http://localhost:3000/)&lt;/code&gt; page in your browser, and you should be seeing the default Create React App screen.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The default Create React App screen&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 983px) 983px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;983&quot; height=&quot;728&quot; src=&quot;https://img.ly/_astro/s_D2E103F8349A30F6AA8E27CD2BA4B6EDB946A8DEF5B8272009321B4F51D679F9_1624366125534_image_ZvCahg.webp&quot; srcset=&quot;/_astro/s_D2E103F8349A30F6AA8E27CD2BA4B6EDB946A8DEF5B8272009321B4F51D679F9_1624366125534_image_1hpMyh.webp 640w, /_astro/s_D2E103F8349A30F6AA8E27CD2BA4B6EDB946A8DEF5B8272009321B4F51D679F9_1624366125534_image_Zy6hVM.webp 750w, /_astro/s_D2E103F8349A30F6AA8E27CD2BA4B6EDB946A8DEF5B8272009321B4F51D679F9_1624366125534_image_Z184VNu.webp 828w, /_astro/s_D2E103F8349A30F6AA8E27CD2BA4B6EDB946A8DEF5B8272009321B4F51D679F9_1624366125534_image_ZvCahg.webp 983w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Before installing &lt;code&gt;ffmpeg.wasm&lt;/code&gt;, you need to get your server ready. As stated &lt;a href=&quot;https://github.com/ffmpegwasm/ffmpeg.wasm#installation&quot;&gt;in the official documentation&lt;/a&gt;, &lt;code&gt;fmmpeg.wasm&lt;/code&gt; depends on &lt;code&gt;[SharedArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer)&lt;/code&gt;. This means that only browsers that support &lt;code&gt;SharedArrayBuffer&lt;/code&gt; can run &lt;code&gt;ffmpeg.wasm&lt;/code&gt;. You can find a complete list of all browsers &lt;a href=&quot;https://caniuse.com/sharedarraybuffer&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the most popular browsers, &lt;code&gt;SharedArrayBuffer&lt;/code&gt; is only available to &lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/#cross-origin-isolation&quot;&gt;cross-origin isolated&lt;/a&gt; webpages. To enable this, you need to set the following headers in your server hosting the React application:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Cross-Origin-Opener-Policy: same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In a Create-React-App application, you achieve this by creating a &lt;code&gt;src/setupProxy.js&lt;/code&gt; file and making sure it contains the following code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;module.exports = function (app) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    app.use(function (req, res, next) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        res.setHeader(&quot;Cross-Origin-Opener-Policy&quot;, &quot;same-origin&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        res.setHeader(&quot;Cross-Origin-Embedder-Policy&quot;, &quot;require-corp&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        next()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your local development server is now ready to use &lt;code&gt;ffmpeg.wasm&lt;/code&gt;!&lt;/p&gt;
&lt;h3 id=&quot;installing-the-projects-dependencies&quot;&gt;Installing the Project’s Dependencies&lt;/h3&gt;
&lt;p&gt;It is now time to add the aforementioned required dependencies to your project.&lt;/p&gt;
&lt;p&gt;First, install &lt;code&gt;ffmpeg.wasm&lt;/code&gt; with the following command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install @ffmpeg/ffmpeg @ffmpeg/core&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, let’s install &lt;a href=&quot;https://ant.design/&quot;&gt;Antd Design&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install antd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, it is time to install &lt;a href=&quot;https://video-react.js.org/&quot;&gt;Video-React&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install video-react redux&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that &lt;code&gt;video-react&lt;/code&gt; also requires &lt;code&gt;[redux](https://www.npmjs.com/package/redux)&lt;/code&gt; to work.&lt;/p&gt;
&lt;p&gt;You have now everything you need to start developing your React video editor!&lt;/p&gt;
&lt;h3 id=&quot;uploading-a-video-to-the-video-editor&quot;&gt;Uploading a Video to the Video Editor&lt;/h3&gt;
&lt;p&gt;Create a &lt;code&gt;VideoUpload&lt;/code&gt; component as below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// src/components/VideoUpload.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Button, Upload } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;antd&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; VideoUpload&lt;/span&gt;&lt;span&gt;({ &lt;/span&gt;&lt;span&gt;disabled&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;onChange&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {}, &lt;/span&gt;&lt;span&gt;onRemove&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {} }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;&lt;/span&gt;&lt;span&gt;Upload&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        disabled&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{disabled}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        beforeUpload&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          return&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        accept&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;video/*&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        onChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          if&lt;/span&gt;&lt;span&gt; (info.fileList &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; info.fileList.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; &gt;&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onChange&lt;/span&gt;&lt;span&gt;(info.fileList[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].originFileObj);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        showUploadList&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&gt;Upload Video&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;Upload&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        danger&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        disabled&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;disabled}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        onClick&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          onRemove&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        Remove&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; VideoUpload;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this component uses the &lt;a href=&quot;https://ant.design/components/upload/&quot;&gt;Antd Design Upload&lt;/a&gt; component to allow users to upload a video file. Then, a “Remove” button gives users the ability to remove the uploaded video. Note that when the &lt;code&gt;Upload&lt;/code&gt; component is enabled, the “Remove” button is disabled and vice versa. This way, users can deal with only one video at a time.&lt;/p&gt;
&lt;h3 id=&quot;playing-a-video-in-react&quot;&gt;Playing a Video in React&lt;/h3&gt;
&lt;p&gt;You now need a &lt;code&gt;VideoPlayer&lt;/code&gt; component to play the uploaded video. You can build it as below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// src/components/VideoPlayer.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  BigPlayButton,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ControlBar,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  LoadingSpinner,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Player,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  PlayToggle,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;video-react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;video-react/dist/video-react.css&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useEffect, useState } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; VideoPlayer&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  src&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  onPlayerChange&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  onChange&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  startTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; undefined&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;player&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setPlayer&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;playerState&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setPlayerState&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (playerState) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      onChange&lt;/span&gt;&lt;span&gt;(playerState);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [playerState]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    onPlayerChange&lt;/span&gt;&lt;span&gt;(player);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (player) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      player.&lt;/span&gt;&lt;span&gt;subscribeToStateChange&lt;/span&gt;&lt;span&gt;(setPlayerState);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [player]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;video-player&apos;&lt;/span&gt;&lt;span&gt;}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;&lt;/span&gt;&lt;span&gt;Player&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;player&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          setPlayer&lt;/span&gt;&lt;span&gt;(player);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        startTime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{startTime}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;source&lt;/span&gt;&lt;span&gt; src&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{src} /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;BigPlayButton&lt;/span&gt;&lt;span&gt; position&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;center&quot;&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;LoadingSpinner&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;ControlBar&lt;/span&gt;&lt;span&gt; autoHide&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;disableDefaultControls&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;PlayToggle&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;/&lt;/span&gt;&lt;span&gt;ControlBar&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;Player&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a simple &lt;code&gt;video-react&lt;/code&gt;-based video player component, which only allows playing or stop the video file received with the &lt;code&gt;src&lt;/code&gt; prop.&lt;/p&gt;
&lt;h3 id=&quot;cutting-a-video-in-react&quot;&gt;Cutting a Video in React&lt;/h3&gt;
&lt;p&gt;Your goal is to allow users to select a portion of the video and watch it before converting it into GIF. Implement this with the logic below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Slider } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &quot;antd&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { sliderValueToVideoTime } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &quot;../utils/utils&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; VideoEditor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;sliderValues&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setSliderValues&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // logic to handle videoFile, videoPlayer, and videoPlayerState...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; min&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValues[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      // when the slider values are updated, updating the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      // video time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (min &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; undefined&lt;/span&gt;&lt;span&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; videoPlayerState &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; videoPlayer) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          videoPlayer.&lt;/span&gt;&lt;span&gt;seek&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, min))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [sliderValues])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (videoPlayer &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; videoPlayerState) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          // allowing users to watch only the portion of&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          // the video selected by the slider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;max&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sliderValues&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          const&lt;/span&gt;&lt;span&gt; minTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, min)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          const&lt;/span&gt;&lt;span&gt; maxTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, max)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          if&lt;/span&gt;&lt;span&gt; (videoPlayerState.currentTime &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; minTime) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              videoPlayer.&lt;/span&gt;&lt;span&gt;seek&lt;/span&gt;&lt;span&gt;(minTime)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          if&lt;/span&gt;&lt;span&gt; (videoPlayerState.currentTime &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; maxTime) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              // looping logic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              videoPlayer.&lt;/span&gt;&lt;span&gt;seek&lt;/span&gt;&lt;span&gt;(minTime)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [videoPlayerState])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          // other video editor components...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;Slider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            disabled&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;videoPlayerState}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{sliderValues}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            range&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;values&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              setSliderValues&lt;/span&gt;&lt;span&gt;(values)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            tooltip&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              formatter: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This component equips users with the ability to select a portion of the uploaded video with the Antd Design &lt;code&gt;Slider&lt;/code&gt; component and watch it in loop, before converting it into a GIF file.&lt;/p&gt;
&lt;p&gt;Specifically, the logic here uses the &lt;code&gt;sliderValueToVideoTime()&lt;/code&gt; function below to transform the slider values into time coordinates:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// src/utils/utils.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export function sliderValueToVideoTime(duration, sliderValue) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return Math.round(duration * sliderValue / 100)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the actual video processing slider will be performed by the next component through &lt;code&gt;ffmpeg&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;converting-a-video-to-gif-in-react&quot;&gt;Converting a Video to GIF in React&lt;/h3&gt;
&lt;p&gt;To convert a video to GIF, create a &lt;code&gt;VideoConversionButton&lt;/code&gt; component as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// src/components/VideoConversionButton.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Button } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;antd&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { fetchFile } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@ffmpeg/ffmpeg&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { sliderValueToVideoTime } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;../utils/utils&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; VideoConversionButton&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoPlayerState&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  sliderValues&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoFile&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ffmpeg&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  onConversionStart&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  onConversionEnd&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  onGifCreated&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; convertToGif&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; async&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // starting the conversion process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    onConversionStart&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; inputFileName&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;gif.mp4&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; outputFileName&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;output.gif&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // writing the video file to memory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ffmpeg.&lt;/span&gt;&lt;span&gt;FS&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;writeFile&apos;&lt;/span&gt;&lt;span&gt;, inputFileName, &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; fetchFile&lt;/span&gt;&lt;span&gt;(videoFile));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;max&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sliderValues;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; minTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, min);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; maxTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, max);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // cutting the video and converting it to GIF with an FFMpeg command&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    await&lt;/span&gt;&lt;span&gt; ffmpeg.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &apos;-i&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      inputFileName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &apos;-ss&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      `${&lt;/span&gt;&lt;span&gt;minTime&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &apos;-to&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      `${&lt;/span&gt;&lt;span&gt;maxTime&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &apos;-f&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &apos;gif&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      outputFileName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // reading the resulting file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; data&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; ffmpeg.&lt;/span&gt;&lt;span&gt;FS&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;readFile&apos;&lt;/span&gt;&lt;span&gt;, outputFileName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // converting the GIF file created by FFmpeg to a valid image URL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; gifUrl&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; URL&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createObjectURL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      new&lt;/span&gt;&lt;span&gt; Blob&lt;/span&gt;&lt;span&gt;([data.buffer], { type: &lt;/span&gt;&lt;span&gt;&apos;image/gif&apos;&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    onGifCreated&lt;/span&gt;&lt;span&gt;(gifUrl);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // ending the conversion process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    onConversionEnd&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; &amp;#x3C;&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt; onClick&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; convertToGif&lt;/span&gt;&lt;span&gt;()}&gt;Convert to GIF&amp;#x3C;/&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt;&lt;span&gt;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; VideoConversionButton;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This component uses &lt;code&gt;ffmpeg.wasm&lt;/code&gt; to launch an &lt;code&gt;ffmpeg&lt;/code&gt; command. This command takes care of clipping the video to the time limits defined by &lt;code&gt;sliderValues&lt;/code&gt; and converting it to GIF. Note that all these operations are performed client-side in the browser.&lt;/p&gt;
&lt;p&gt;In detail, the &lt;code&gt;ffmpeg&lt;/code&gt; &lt;code&gt;-ss&lt;/code&gt; flag defines the time from which to start reading the video file, while &lt;code&gt;-to&lt;/code&gt; defines the end time. Then, the &lt;code&gt;gif&lt;/code&gt; option specifies that you want to produce a GIF file. Learn more about the flags and options offered by &lt;code&gt;ffmpeg&lt;/code&gt; &lt;a href=&quot;https://www.ffmpeg.org/ffmpeg.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The resulting GIF image is stored in the &lt;code&gt;output.gif&lt;/code&gt; memory file, loaded as a valid &lt;code&gt;&quot;image/gif&quot;&lt;/code&gt; &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Blob&quot;&gt;Blob&lt;/a&gt;, and finally converted to a valid image URL with the &lt;code&gt;[URL.createObjectURL()](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static)&lt;/code&gt; native function.&lt;/p&gt;
&lt;h3 id=&quot;putting-it-all-together&quot;&gt;Putting It All Together&lt;/h3&gt;
&lt;p&gt;Now, let’s see the full code of the &lt;code&gt;VideoEditor&lt;/code&gt; component:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// src/components/VideoEditor.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { createFFmpeg } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@ffmpeg/ffmpeg&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { useEffect, useState } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Slider, Spin } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;antd&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { VideoPlayer } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./VideoPlayer&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { sliderValueToVideoTime } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;../utils/utils&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; VideoUpload &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./VideoUpload&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; VideoConversionButton &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./VideoConversionButton&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ffmpeg&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; createFFmpeg&lt;/span&gt;&lt;span&gt;({ log: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; VideoEditor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;ffmpegLoaded&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setFFmpegLoaded&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;videoFile&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setVideoFile&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;videoPlayerState&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setVideoPlayerState&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;videoPlayer&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setVideoPlayer&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;gifUrl&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setGifUrl&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;sliderValues&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setSliderValues&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;processing&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setProcessing&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // loading ffmpeg on startup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ffmpeg.&lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setFFmpegLoaded&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, []);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; min&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValues[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // when the slider values are updated, updating the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // video time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (min &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; undefined&lt;/span&gt;&lt;span&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; videoPlayerState &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; videoPlayer) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      videoPlayer.&lt;/span&gt;&lt;span&gt;seek&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, min));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [sliderValues]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (videoPlayer &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; videoPlayerState) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      // allowing users to watch only the portion of&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      // the video selected by the slider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;max&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sliderValues;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; minTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, min);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; maxTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; sliderValueToVideoTime&lt;/span&gt;&lt;span&gt;(videoPlayerState.duration, max);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (videoPlayerState.currentTime &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; minTime) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        videoPlayer.&lt;/span&gt;&lt;span&gt;seek&lt;/span&gt;&lt;span&gt;(minTime);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (videoPlayerState.currentTime &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; maxTime) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // looping logic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        videoPlayer.&lt;/span&gt;&lt;span&gt;seek&lt;/span&gt;&lt;span&gt;(minTime);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [videoPlayerState]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // when the current videoFile is removed,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // restoring the default state&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;videoFile) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setVideoPlayerState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setSliderValues&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setVideoPlayerState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setGifUrl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;undefined&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [videoFile]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;&lt;/span&gt;&lt;span&gt;Spin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        spinning&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{processing &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;ffmpegLoaded}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        tip&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;ffmpegLoaded &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &apos;Waiting for FFmpeg to load...&apos;&lt;/span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt; &apos;Processing...&apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          {videoFile &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;VideoPlayer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              src&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;URL&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createObjectURL&lt;/span&gt;&lt;span&gt;(videoFile)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              onPlayerChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;videoPlayer&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                setVideoPlayer&lt;/span&gt;&lt;span&gt;(videoPlayer);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              onChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;videoPlayerState&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                setVideoPlayerState&lt;/span&gt;&lt;span&gt;(videoPlayerState);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          ) &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;h1&lt;/span&gt;&lt;span&gt;&gt;Upload a video&amp;#x3C;/&lt;/span&gt;&lt;span&gt;h1&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          )}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;upload-div&apos;&lt;/span&gt;&lt;span&gt;}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;VideoUpload&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            disabled&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;!!&lt;/span&gt;&lt;span&gt;videoFile}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;videoFile&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              setVideoFile&lt;/span&gt;&lt;span&gt;(videoFile);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;slider-div&apos;&lt;/span&gt;&lt;span&gt;}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;h3&lt;/span&gt;&lt;span&gt;&gt;Cut Video&amp;#x3C;/&lt;/span&gt;&lt;span&gt;h3&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;Slider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            disabled&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;videoPlayerState}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{sliderValues}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            range&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onChange&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;values&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              setSliderValues&lt;/span&gt;&lt;span&gt;(values);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            tooltip&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              formatter: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;conversion-div&apos;&lt;/span&gt;&lt;span&gt;}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;VideoConversionButton&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onConversionStart&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              setProcessing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onConversionEnd&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              setProcessing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            ffmpeg&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{ffmpeg}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            videoPlayerState&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{videoPlayerState}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            sliderValues&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{sliderValues}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            videoFile&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{videoFile}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onGifCreated&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;girUrl&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              setGifUrl&lt;/span&gt;&lt;span&gt;(girUrl);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        {gifUrl &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;gif-div&apos;&lt;/span&gt;&lt;span&gt;}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;h3&lt;/span&gt;&lt;span&gt;&gt;Resulting GIF&amp;#x3C;/&lt;/span&gt;&lt;span&gt;h3&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;img&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              src&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{gifUrl}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;gif&apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              alt&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;GIF file generated in the client side&apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              href&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{gifUrl}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              download&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;test.gif&apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;ant-btn ant-btn-default&apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              Download&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;/&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        )}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;Spin&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; VideoEditor;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since &lt;code&gt;ffmpeg&lt;/code&gt; takes time to load, you need to let users know that they need to wait a while before they can use the video editor component. Also, &lt;code&gt;ffmpeg&lt;/code&gt; operations take time to execute. This wait logic is implemented by using the Antd Design &lt;code&gt;[Spin](https://ant.design/components/spin/)&lt;/code&gt; component.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://paper-attachments.dropbox.com/s_C8CCC2508B96793E40906CD26AF4C92ACE1FB33CF33FE115E6ACE3BA49F22F52_1663925760548_chrome-capture-2022-8-23.gif&quot; alt=&quot;Preventing users from using the video editor component before ffmpeg is loaded&quot;&gt;&lt;/p&gt;
&lt;p&gt;Also, note that by passing the &lt;code&gt;log: true&lt;/code&gt; option to the &lt;code&gt;createFFmpeg()&lt;/code&gt; function, &lt;code&gt;ffmpeg&lt;/code&gt; will log useful debug info in the console. For example, after &lt;code&gt;ffmpeg&lt;/code&gt; gets loaded, you should be able to see the following lines in the browser console:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[info] use ffmpeg.wasm v0.11.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;createFFmpeg.js:43 [info] load ffmpeg-core&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;createFFmpeg.js:43 [info] loading ffmpeg-core&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;createFFmpeg.js:43 [info] ffmpeg-core loaded&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What the &lt;code&gt;VideoComponent&lt;/code&gt; does is use all the components presented earlier to allow users to upload a video, select a portion through a slider, convert it to GIF, and download the resulting GIF file.&lt;/p&gt;
&lt;p&gt;Et voilà! You just learned how to build a client-side video editor in React without using any backend functionality!&lt;/p&gt;
&lt;h2 id=&quot;commercial-alternative&quot;&gt;Commercial Alternative&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/docs/vesdk/flutter/getting-started/integration/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;VideoEditor SDK&lt;/a&gt; by &lt;a href=&quot;https://img.ly&quot;&gt;IMG.LY&lt;/a&gt; provides powerful video editing features, including cropping and trimming videos in your project. You will receive staples of video editing, including straightening videos, filters, brightness, color adjustments, and more.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Building a client-side video processing and editing application that uses only the browser possible. With WebAssembly, you can run high-performance code written in C or C++ in JavaScript. This allows you to perform complex operations at lightning speed directly in the browser, without having to delegate the work to a server.&lt;/p&gt;
&lt;p&gt;In this tutorial, you learned how to use &lt;code&gt;ffmpeg.wasm&lt;/code&gt; to build a video editor in React. &lt;code&gt;ffmpeg.wasm&lt;/code&gt; is the Wasm port of &lt;code&gt;ffmpeg&lt;/code&gt; and enables video and audio processing and editing directly in the browser. Using it to build a web application to upload a video, cut it, and export it to GIF requires only a few lines of code, and here we have seen how to implement such a video editing application.&lt;/p&gt;
&lt;p&gt;If your app goes beyond merely displaying video, and you want to allow your users to also edit video or create video based templates in the browser, explore our &lt;strong&gt;&lt;a href=&quot;https://img.ly/products/video-sdk&quot;&gt;VideoEditor SDK&lt;/a&gt;&lt;/strong&gt; for the Web – a performant video editing solution based on WASM and WebCodecs. Try the editor for yourself in action with &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;our showcases&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading! Let us know what you think on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt;! To stay in the loop, subscribe to our &lt;a href=&quot;https://photoeditorsdk.us13.list-manage.com/subscribe?u=dc9f652839dbb620d14d6d28d&amp;#x26;id=04a306e4b2&quot;&gt;Newsletter&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Antonello</dc:creator><media:content url="https://blog.img.ly/2023/01/video-editor-ffmpeg-wasm-1.jpg" medium="image"/><category>How-To</category><category>Video Editor</category><category>Web Development</category><category>Web Application</category><category>Video Editing</category><category>Tech</category><category>Tutorial</category></item><item><title>CE.SDK v1.9.0 Release</title><link>https://img.ly/blog/creative-editor-sdk-v_1_9_0-release-notes/</link><guid isPermaLink="true">https://img.ly/blog/creative-editor-sdk-v_1_9_0-release-notes/</guid><description>Get ready to take your creative applications to the next level! This release is packed with exciting new features like video support for web, and more. </description><pubDate>Tue, 13 Dec 2022 08:21:50 GMT</pubDate><content:encoded>&lt;p&gt;We are happy to shine light on more new features since our CE.SDK &lt;a href=&quot;https://img.ly/blog/creative-editor-sdk-v_1_8_0-release-notes/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes&quot;&gt;v1.8.0&lt;/a&gt; Release. To build powerful features for your application, we are excited to hear your feedback and suggestions.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/cesdk-v-1-9-0-summary.mp4&quot; controls playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;CE.SDK v1.9.0 is out now, and it includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Video Support for Web&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Video Timelines&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Web Audio Support&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Native iOS Platform Support&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Swift Package&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Common Touch Gesture Support&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apparel UI Showcase&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Spot and Named Colors&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;More Showcases&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;video-support-for-web&quot;&gt;Video Support for Web&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Apply video fills and blocks to your scene!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;643&quot; src=&quot;https://img.ly/_astro/Web_Video_Fills_16bvcF.webp&quot; srcset=&quot;/_astro/Web_Video_Fills_24RtxW.webp 640w, /_astro/Web_Video_Fills_g3IpD.webp 750w, /_astro/Web_Video_Fills_2q3t9s.webp 828w, /_astro/Web_Video_Fills_ZX0qSJ.webp 1080w, /_astro/Web_Video_Fills_45wDX.webp 1280w, /_astro/Web_Video_Fills_16bvcF.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;We now support adding and editing videos in your web browser. You can apply video fills, add blocks to the scene, and combine any other block to create videos and stories with CE.SDK. For now this feature is only supported in Chromium based browsers.&lt;/p&gt;
&lt;h3 id=&quot;video-timelines&quot;&gt;Video Timelines&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Add, trim and edit your videos in a browser with CE.SDK.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;643&quot; src=&quot;https://img.ly/_astro/Video_Timelines_for_Consumer_UIs_and_Studio_UI_Z1mm045.webp&quot; srcset=&quot;/_astro/Video_Timelines_for_Consumer_UIs_and_Studio_UI_2gzhlA.webp 640w, /_astro/Video_Timelines_for_Consumer_UIs_and_Studio_UI_Z1Kh3x5.webp 750w, /_astro/Video_Timelines_for_Consumer_UIs_and_Studio_UI_Z18b1IC.webp 828w, /_astro/Video_Timelines_for_Consumer_UIs_and_Studio_UI_Z1TDUBc.webp 1080w, /_astro/Video_Timelines_for_Consumer_UIs_and_Studio_UI_T5B4k.webp 1280w, /_astro/Video_Timelines_for_Consumer_UIs_and_Studio_UI_Z1mm045.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Video Timelines and Trimming is coming to our Studio and Design UIs. This adds complete client-side video editing in the browser to our User Interfaces.&lt;/p&gt;
&lt;h3 id=&quot;web-audio-support&quot;&gt;Web Audio Support&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Make it pop! Add your audio to a video.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;643&quot; src=&quot;https://img.ly/_astro/Web_Audio_Support_1WmHmG.webp&quot; srcset=&quot;/_astro/Web_Audio_Support_2tqhgn.webp 640w, /_astro/Web_Audio_Support_24FYXn.webp 750w, /_astro/Web_Audio_Support_Z2v5a4x.webp 828w, /_astro/Web_Audio_Support_Zpf5zK.webp 1080w, /_astro/Web_Audio_Support_Z1L2g10.webp 1280w, /_astro/Web_Audio_Support_1WmHmG.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;In addition to video support, we also introduce a &lt;a href=&quot;https://img.ly/docs/cesdk/js/create-video-c41a08/&quot;&gt;new block type for audio&lt;/a&gt;. You can use audio blocks to add audio files in MP3 and M4a formats to your scene. Like design blocks, you can add and modify them via the Block APIs and attach them to a scene. Note that audio blocks have no visual representation on the canvas, but only in the timeline.&lt;/p&gt;
&lt;p&gt;We dedicate our first implementation to the web. However, native mobile implementations will follow soon.&lt;/p&gt;
&lt;h2 id=&quot;native-ios-support&quot;&gt;Native iOS Support&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;643&quot; src=&quot;https://img.ly/_astro/iOS_Native_Support_1Yqh6a.webp&quot; srcset=&quot;/_astro/iOS_Native_Support_2lOmvf.webp 640w, /_astro/iOS_Native_Support_Z24AdxL.webp 750w, /_astro/iOS_Native_Support_Z5FePS.webp 828w, /_astro/iOS_Native_Support_Z1l5Xxb.webp 1080w, /_astro/iOS_Native_Support_jEDLu.webp 1280w, /_astro/iOS_Native_Support_1Yqh6a.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;With this feature, we support developing native iOS applications with our SDK. It comes with full &lt;strong&gt;Swift API&lt;/strong&gt; support and many integration examples.&lt;/p&gt;
&lt;p&gt;Additionally, CE.SDK v1.9.0 comes with &lt;strong&gt;Common Touch Gesture&lt;/strong&gt; to improve the editing experience on touchpads and mobile devices. That includes gestures like pinch, spread, drag, rotate, tap, and double tap.&lt;/p&gt;
&lt;h2 id=&quot;spot-and-named-colors&quot;&gt;Spot and Named Colors&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Get print-ready with spot and named colors.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;643&quot; src=&quot;https://img.ly/_astro/spotnames_PcsQI.webp&quot; srcset=&quot;/_astro/spotnames_Z7J0F5.webp 640w, /_astro/spotnames_ZJOXtb.webp 750w, /_astro/spotnames_Zyl6he.webp 828w, /_astro/spotnames_Z2c793G.webp 1080w, /_astro/spotnames_ZFrP5Y.webp 1280w, /_astro/spotnames_PcsQI.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;With this release we are extending our support for print use cases by adding spot colors which enable the use of custom color mixes in the printing process. Consult the guides on &lt;a href=&quot;https://img.ly/docs/cesdk/js/colors/for-print/spot-c3a150/&quot;&gt;creating spot colors&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h2 id=&quot;more-showcases&quot;&gt;More Showcases&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Explore our showcase site for creative tools perfect for your application.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1480px) 1480px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1480&quot; height=&quot;643&quot; src=&quot;https://img.ly/_astro/showcases_2sxc8Y.webp&quot; srcset=&quot;/_astro/showcases_Z2wCp9A.webp 640w, /_astro/showcases_1UsKQf.webp 750w, /_astro/showcases_26WD3c.webp 828w, /_astro/showcases_ZyLpLq.webp 1080w, /_astro/showcases_VRSbh.webp 1280w, /_astro/showcases_2sxc8Y.webp 1480w&quot;&gt;&lt;/p&gt;
&lt;p&gt;To explore CE.SDK capabilities firsthand, and to look into cases that might be comparable to yours, we provide more showcases on our website.&lt;/p&gt;
&lt;p&gt;Easily build a&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/showcases/cesdk/mobile-ui/web&quot;&gt;Mobile UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/showcases/cesdk/photo-ui/web&quot;&gt;Photo UI&lt;/a&gt; for easy photo editing&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/showcases/cesdk/post-greeting-cards/web&quot;&gt;Post &amp;#x26; Greeting Card UI&lt;/a&gt; to provide templates and easy adaption for print&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/showcases/cesdk/apparel-ui/web&quot;&gt;Apparel UI&lt;/a&gt; to let users create fantastic apparel designs&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/imgly/cesdk-swift-examples/&quot;&gt;Apparel UI Mobile&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading! Let us know what you think on&lt;/strong&gt; &lt;a href=&quot;https://x.com/imgly&quot;&gt;&lt;strong&gt;Twitter&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;! To stay in the loop, subscribe to our&lt;/strong&gt; &lt;a href=&quot;https://img.us13.list-manage.com/subscribe?u=dc9f652839dbb620d14d6d28d&amp;#x26;id=04a306e4b2&quot;&gt;&lt;strong&gt;Newsletter&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Neslihan</dc:creator><media:content url="https://blog.img.ly/2022/12/creative-editor-sdk-1.png" medium="image"/><category>Release Notes</category><category>Web Application</category><category>Web Development</category><category>Video Editing</category><category>Video Editor</category></item><item><title>How To Build a Video Player in JavaScript</title><link>https://img.ly/blog/how-to-build-video-player-in-javascript/</link><guid isPermaLink="true">https://img.ly/blog/how-to-build-video-player-in-javascript/</guid><description>Create your own JavaScript video player using simple methods for neat results!</description><pubDate>Tue, 27 Sep 2022 17:02:49 GMT</pubDate><content:encoded>&lt;p&gt;Probably a decade ago, it was impossible to play video or audio inside your browser without any third-party services such as Flash or Silverlight. You needed to install a plugin and only play your media while using it, so as you can see, it was very uncomfortable, with low speed and high delays. Nowadays, we have JavaScript with the new version of HTML5. With these new technologies and tools, we can stream our video much quicker, easier, and without any latency. To do it, you will need only a simple &lt;video&gt; tag and give a link to your video stored on your computer. The simple attribute &lt;em&gt;controls&lt;/em&gt; will give you a default video player built into the browser. It’s elementary and doesn’t have many features, so if you want to stream a video on your website in a more professional way using your video player, you’ll need to use JavaScript. And we’ll teach you how to do it in this article!&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;By the end of this guide, you’ll have something similar to this, so if you’re excited, keep reading and follow this tutorial step-by-step!&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;300&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;qBYNxxa&quot; data-user=&quot;paulknulst&quot;&gt;&lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/paulknulst/pen/qBYNxxa&quot;&gt;How to build a video player in Javascript&lt;/a&gt; by Paul Knulst (&lt;a href=&quot;https://codepen.io/paulknulst&quot;&gt;@paulknulst&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;setting-up-the-project&quot;&gt;&lt;strong&gt;Setting Up the Project&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Assuming you are working with UNIX system (or have Git BASH on Windows) you can create all three files that are necessary to build a video player in JavaScript with this command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mkdir video-player&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cd video-player&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;touch index.html script.js style.css&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To add a simple video player to our application, we have to add the following code to our &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;!DOCTYPE html&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;html lang=&quot;en&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;head&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;meta charset=&quot;UTF-8&quot; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;title&gt;How to build a video player in Javascript&amp;#x3C;/title&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/head&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;body&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;div class=&quot;player&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;video class=&quot;video&quot; controls&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                &amp;#x3C;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    src=&quot;&amp;#x3C;https://ftp.f1nalboss.de/data/imgly/videoplayer/testvideo.mp4&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    type=&quot;video/mp4&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                &amp;#x3C;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    src=&quot;&amp;#x3C;https://ftp.f1nalboss.de/data/imgly/videoplayer/testvideo.mp4&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    type=&quot;video/webm&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                &amp;#x3C;p&gt;No HTML5 video supported&amp;#x3C;/p&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;/video&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;/div&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;script src=&quot;script.js&quot;&gt;&amp;#x3C;/script&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/body&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;/html&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Within the above code, the &lt;code&gt;&amp;#x3C;video&gt;&lt;/code&gt; element uses a remote video from my FTP. You can either use my default video or add any video from your local computer by adjusting the &lt;code&gt;src&lt;/code&gt; attribute. HTML5 specification supports three different video formats, and the snippet used multiple &lt;code&gt;&amp;#x3C;source&gt;&lt;/code&gt; tags to make the videos available in MP4 and WebM. Furthermore, the &lt;code&gt;&amp;#x3C;p&gt;&lt;/code&gt; tag is used to display pre-defined content to user agents that do not support the &lt;code&gt;video&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;The HTML5 &lt;code&gt;&amp;#x3C;video&gt;&lt;/code&gt; tag accepts several native attributes. For example, the &lt;code&gt;controls&lt;/code&gt; attribute displays the standard player controls when added or set to true. You can find out more about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-controls&quot;&gt;all video attributes here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before continuing, you should apply all styles that are needed within this tutorial by populating your &lt;code&gt;style.css&lt;/code&gt; with all styles &lt;a href=&quot;https://codepen.io/paulknulst/pen/qBYNxxa&quot;&gt;from this CodePen&lt;/a&gt;. Save and open your &lt;code&gt;index.html&lt;/code&gt; and load it within the browser to see the embedded video player as seen below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;This is what the embedded video player should look like in your index.html file.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 805px) 805px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;805&quot; height=&quot;544&quot; src=&quot;https://img.ly/_astro/build-video-player-with-javascript_ZBugbA.webp&quot; srcset=&quot;/_astro/build-video-player-with-javascript_Z2soYbu.webp 640w, /_astro/build-video-player-with-javascript_ZnTDYb.webp 750w, /_astro/build-video-player-with-javascript_ZBugbA.webp 805w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;customize-the-video-player-with-javascript&quot;&gt;&lt;strong&gt;Customize the Video Player With JavaScript&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;To customize the video player, you first have to remove the &lt;code&gt;controls&lt;/code&gt; attribute that displays &lt;code&gt;Play&lt;/code&gt;, &lt;code&gt;Pause&lt;/code&gt;, &lt;code&gt;Volume&lt;/code&gt;, etc. because you will implement your own custom controls within this tutorial. Now, check your browser, you will recognize that the controls are gone, and you cannot play the video anymore.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 815px) 815px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;815&quot; height=&quot;540&quot; src=&quot;https://img.ly/_astro/build-video-player-with-javascript_2_Z1Exl3w.webp&quot; srcset=&quot;/_astro/build-video-player-with-javascript_2_27jRL3.webp 640w, /_astro/build-video-player-with-javascript_2_Z2tYMIW.webp 750w, /_astro/build-video-player-with-javascript_2_Z1Exl3w.webp 815w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;add-play-and-pause&quot;&gt;&lt;strong&gt;Add Play and Pause&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;To enable play and pause the video, you have to add a new button to the &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;div class=&quot;controls&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;button&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            class=&quot;controls__btn playPauseBtn&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            title=&quot;Toggle Play&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ►&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/button&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Afterward, open your &lt;code&gt;script.js&lt;/code&gt; and enable functionality by adding this code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const videoContainer = document.querySelector(&quot;.video-container&quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const playPauseBtn = document.querySelector(&quot;.playPauseBtn&quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function togglePlay() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if (videoContainer.paused || videoContainer.ended) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    videoContainer.play();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } else {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    videoContainer.pause();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function updatePlayBtn() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  playPauseBtn.innerHTML = videoContainer.paused ? &quot;►&quot; : &quot;❚❚&quot;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;playPauseBtn.addEventListener(&quot;click&quot;, togglePlay);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;videoContainer.addEventListener(&quot;click&quot;, togglePlay);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;videoContainer.addEventListener(&quot;play&quot;, updatePlayBtn);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;videoContainer.addEventListener(&quot;pause&quot;, updatePlayBtn);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Within this javascript code, first, the &lt;code&gt;video-container&lt;/code&gt; element and the &lt;code&gt;playPauseBtn&lt;/code&gt; is selected (Line 1 and 2). Then two functions are defined: &lt;code&gt;togglePlay()&lt;/code&gt; and &lt;code&gt;updatePlayBtn()&lt;/code&gt;. &lt;code&gt;togglePlay()&lt;/code&gt; is used to stop and start the video based on its actual state. &lt;code&gt;updatePlayBtn&lt;/code&gt; is used to switch between the Icon which is shown within the video player.&lt;/p&gt;
&lt;p&gt;In the last part of the snippet, a click event listener is added to the &lt;code&gt;playPauseBtn&lt;/code&gt; that executes the &lt;code&gt;togglePlay()&lt;/code&gt; function. Next, three click event listeners are added to the &lt;code&gt;videoContainer&lt;/code&gt; that executes &lt;code&gt;togglePlay()&lt;/code&gt; on mouse click and also executes &lt;code&gt;updatePlayBtn&lt;/code&gt; based on the video’s state.&lt;/p&gt;
&lt;p&gt;Now you can reload your &lt;code&gt;index.html&lt;/code&gt; and should be able to play and pause the video by either clicking the video or the button:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;You can now pause and play your video.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 803px) 803px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;803&quot; height=&quot;526&quot; src=&quot;https://img.ly/_astro/javascript-video-player_c0OvI.webp&quot; srcset=&quot;/_astro/javascript-video-player_Z2mALHv.webp 640w, /_astro/javascript-video-player_2aoUuJ.webp 750w, /_astro/javascript-video-player_c0OvI.webp 803w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;add-progress-bar&quot;&gt;Add Progress Bar&lt;/h3&gt;
&lt;p&gt;Next, a progress bar will be implemented to show the current timestamp of the video when played. First, add a &lt;code&gt;div&lt;/code&gt; tag to the &lt;code&gt;index.html&lt;/code&gt; which will act as the progress bar:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;div class=&quot;controls&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;div class=&quot;progress&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    	&amp;#x3C;div class=&quot;progress__filled&quot;&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/div&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // ..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then open the &lt;code&gt;script.js&lt;/code&gt; and add the following snippet:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const progress = document.querySelector(&quot;.progress&quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const progressBar = document.querySelector(&quot;.progress__filled&quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function handleProgress() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const progressPercentage = (videoContainer.currentTime / videoContainer.duration) * 100;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  progressBar.style.flexBasis = `${progressPercentage}%`;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function jump(e) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const position = (e.offsetX / progress.offsetWidth) * videoContainer.duration;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoContainer.currentTime = position;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;videoContainer.addEventListener(&quot;timeupdate&quot;, handleProgress);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;progress.addEventListener(&quot;click&quot;, jump);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let mousedown = false;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;progress.addEventListener(&quot;mousedown&quot;, () =&gt; (mousedown = true));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;progress.addEventListener(&quot;mousemove&quot;, (e) =&gt; mousedown &amp;#x26;&amp;#x26; jump(e));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;progress.addEventListener(&quot;mouseup&quot;, () =&gt; (mousedown = false));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this snippet, the &lt;code&gt;progress&lt;/code&gt; container and the &lt;code&gt;progress__filled&lt;/code&gt; element will be selected, and two functions will be added: &lt;code&gt;handleProgress()&lt;/code&gt; and &lt;code&gt;jump(e)&lt;/code&gt;. &lt;code&gt;handleProgress()&lt;/code&gt; will be responsible for updating the progress bar. The &lt;code&gt;jump(e)&lt;/code&gt; function is used to enable clicking on the progress bar to jump to the position within the video.&lt;/p&gt;
&lt;p&gt;The last part contains all event listeners that are needed for the progress bar. The &lt;code&gt;handleProgress()&lt;/code&gt; will be called on every &lt;code&gt;timeupdate&lt;/code&gt; event. Also, clicking anywhere on the progress bar will call the &lt;code&gt;jump(e)&lt;/code&gt; method and the video will jump to the position. Additionally, &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mousemove&lt;/code&gt;, and &lt;code&gt;mouseup&lt;/code&gt; will be used to enable &lt;em&gt;sliding&lt;/em&gt; through the video while holding the mouse button down on the progress bar.&lt;/p&gt;
&lt;h2 id=&quot;closing-notes&quot;&gt;&lt;strong&gt;Closing Notes&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Congratulations! If you followed the tutorial, you learned how to implement your own video player and add custom controls using JavaScript. Now, you can use &lt;a href=&quot;https://codepen.io/paulknulst/pen/qBYNxxa&quot;&gt;my CodePen&lt;/a&gt; and start implementing more controls like &lt;strong&gt;volume control&lt;/strong&gt;, &lt;strong&gt;keyboard shortcuts&lt;/strong&gt;, or &lt;strong&gt;skip controls&lt;/strong&gt; to build your own customized video player.&lt;/p&gt;
&lt;p&gt;If your app goes beyond merely displaying video, and you want to allow your users to also edit video or create video based templates in the browser, check out our &lt;a href=&quot;https://img.ly/use-cases/video-for-web&quot;&gt;Video Editor for Web&lt;/a&gt;!&lt;/p&gt;</content:encoded><dc:creator>Paul</dc:creator><media:content url="https://blog.img.ly/2022/09/video-player-javascript_tutorial.png" medium="image"/><category>How-To</category><category>Video Editor</category><category>Video Player</category><category>JavaScript</category><category>Web Development</category><category>Web Application</category><category>Tutorial</category></item><item><title>How to Crop and Trim Videos in Flutter</title><link>https://img.ly/blog/how-to-crop-and-trim-videos-in-flutter/</link><guid isPermaLink="true">https://img.ly/blog/how-to-crop-and-trim-videos-in-flutter/</guid><description>Create your own video app in Flutter with the free-to-use and open source solution FFmpeg.</description><pubDate>Tue, 27 Sep 2022 08:45:16 GMT</pubDate><content:encoded>&lt;p&gt;If you are looking for a package that crops and trims videos in Flutter, you must have already come across the &lt;a href=&quot;https://pub.dev/packages/video_trimmer&quot;&gt;video_trimmer&lt;/a&gt; Flutter package. This package can trim videos but does not provide video cropping (at least not out-of-the-box). In fact, none of the packages on pub.dev, as of today, allow cropping a video in Flutter. If you have dug deeper, you might have come across FFmpeg — a powerful video editing command line tool, that is not the easiest to get started with. See the &lt;a href=&quot;https://img.ly/blog/ultimate-guide-to-ffmpeg/&quot;&gt;Ultimate Guide to FFmpeg&lt;/a&gt; for help.In this article we will use the FFmpeg library to crop and trim a video in a Flutter project.&lt;/p&gt;
&lt;p&gt;Here is a list of packages that we will be using; &lt;a href=&quot;https://pub.dev/packages/ffmpeg_kit_flutter&quot;&gt;ffmpeg_kit_flutter&lt;/a&gt; package for cropping and trimming videos, the &lt;a href=&quot;https://pub.dev/packages/path_provider&quot;&gt;path_provider&lt;/a&gt; package to get the path to the application or external directory where the video files will be stored, and the &lt;a href=&quot;https://pub.dev/packages/video_player&quot;&gt;video_player&lt;/a&gt; package to play the video preview.&lt;/p&gt;
&lt;p&gt;This article will not cover building any UI for cropping and trimming. But, it will discuss in brief how to crop the video using the video_trimmer library as well. If you want to package this workflow for production, check out our guide on &lt;a href=&quot;https://img.ly/blog/how-to-run-ffmpeg-inside-a-docker-container/&quot;&gt;running FFmpeg inside a Docker container&lt;/a&gt;. Also, you can try out the code used in this article from this &lt;a href=&quot;https://github.com/numerative/flutter_crop_and_trim_video&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;get-started&quot;&gt;Get Started&lt;/h2&gt;
&lt;p&gt;The end result of this tutorial will be a simple app that would look like the following screenshot.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Create a Flutter app to trim and crop videos easily.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 323px) 323px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;323&quot; height=&quot;700&quot; src=&quot;https://img.ly/_astro/resized_Z1EVmRl.webp&quot; srcset=&quot;/_astro/resized_Z1EVmRl.webp 323w&quot;&gt;&lt;/p&gt;
&lt;p&gt;When you tap the &lt;strong&gt;Save Video&lt;/strong&gt;, the preview will refresh with the cropped and trimmed video replacing the original video. Follow the instructions in this article, and you will be able to develop a similar Flutter app.&lt;/p&gt;
&lt;p&gt;First, let us start by adding dependencies to a new Flutter project.&lt;/p&gt;
&lt;h3 id=&quot;add-dependencies&quot;&gt;Add Dependencies&lt;/h3&gt;
&lt;p&gt;In your project’s &lt;code&gt;pubspec.yaml&lt;/code&gt; file add the following 3 dependencies.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ffmpeg_kit_flutter&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;^4.5.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  path_provider&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;^2.0.11&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  video_player&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;^2.4.6&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, execute &lt;code&gt;flutter pub get&lt;/code&gt; command from the project folder root.&lt;/p&gt;
&lt;h3 id=&quot;set-minimum-sdk-version-and-platform-version&quot;&gt;Set Minimum SDK Version and Platform Version&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;ffmpeg_kit_flutter&lt;/code&gt; plugin runs on Android SDK API level 24+ and iOS SDK 12.1+. Therefore, modify the module level &lt;code&gt;build.gradle&lt;/code&gt; file to declare the &lt;code&gt;minSdkVersion&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;groovy&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;android {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  defaultConfig {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ..&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    minSdkVersion &lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ..&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, modify the &lt;code&gt;Podfile&lt;/code&gt; to declare the minimum global platform.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Uncomment this line to define a global platform for your project&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;platform &lt;/span&gt;&lt;span&gt;:ios&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;12.1&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;add-a-video-asset&quot;&gt;Add a Video Asset&lt;/h3&gt;
&lt;p&gt;For simplicity, we will be using a video asset instead of implementing a file picker. Choose a video file you would like to work with or &lt;a href=&quot;https://github.com/numerative/flutter_crop_and_trim_video/raw/main/assets/file1.mp4&quot;&gt;download&lt;/a&gt; this sample video file. Next, copy the video file to a new directory named &lt;code&gt;assets&lt;/code&gt; at the root of your project folder.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Copy your video of choice to your assets folder at the root of your project folder.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 318px) 318px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;318&quot; height=&quot;240&quot; src=&quot;https://img.ly/_astro/file1-mp4-placement_ZVFQb9.webp&quot; srcset=&quot;/_astro/file1-mp4-placement_ZVFQb9.webp 318w&quot;&gt;&lt;/p&gt;
&lt;p&gt;And then reference the video file from the &lt;code&gt;pubspec.yaml&lt;/code&gt; file.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;flutter&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  assets&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    - &lt;/span&gt;&lt;span&gt;assets/file1.mp4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Execute &lt;code&gt;flutter pub get&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;Having added the required dependencies, let us move on to coding.&lt;/p&gt;
&lt;h3 id=&quot;implement-video-crop-and-trim&quot;&gt;Implement Video Crop and Trim&lt;/h3&gt;
&lt;p&gt;Replace the code in your &lt;code&gt;main.dart&lt;/code&gt; file with the following code in the code block. This will be our starter code.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;dart&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;package:flutter/material.dart&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  runApp&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; MyApp&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; MyApp&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; StatelessWidget&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; MyApp&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; key}) &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; super&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // This widget is the root of your application.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  @override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Widget&lt;/span&gt;&lt;span&gt; build&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;BuildContext&lt;/span&gt;&lt;span&gt; context) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; MaterialApp&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &apos;Crop and Trim Demo&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      home&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; const&lt;/span&gt;&lt;span&gt; MyHomePage&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; MyHomePage&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; StatefulWidget&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; MyHomePage&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; key}) &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; super&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  @override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  State&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;MyHomePage&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;createState&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; _MyHomePageState&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; _MyHomePageState&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; State&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;MyHomePage&lt;/span&gt;&lt;span&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  @override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Widget&lt;/span&gt;&lt;span&gt; build&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;BuildContext&lt;/span&gt;&lt;span&gt; context) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; Scaffold&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      appBar&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; AppBar&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Text&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Flutter Crop and Trim&quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      body&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Column&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      ),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;initialize-the-input-player&quot;&gt;Initialize the Input Player&lt;/h3&gt;
&lt;p&gt;Add the following code to the &lt;code&gt;_MyHomePageState&lt;/code&gt; class.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;dart&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;dart:io&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;package:flutter/services.dart&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;package:path_provider/path_provider.dart&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;package:video_player/video_player.dart&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; _MyHomePageState&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; State&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;MyHomePage&lt;/span&gt;&lt;span&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  late&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;span&gt; inputPath;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  VideoPlayerController&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; controller;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  String&lt;/span&gt;&lt;span&gt; outputPath &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  @override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  void&lt;/span&gt;&lt;span&gt; initState&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    super&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;initState&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    copyVideoToApplicationDirectory&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;((path) &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      inputPath &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; path;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      controller &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VideoPlayerController&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;(inputPath));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      await&lt;/span&gt;&lt;span&gt; controller&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;initialize&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      await&lt;/span&gt;&lt;span&gt; controller&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;play&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setState&lt;/span&gt;&lt;span&gt;(() {});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      outputPath &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; getOutputPath&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ///Copy input file to ApplicationStorage Directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ///returns path to copied video&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Future&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;copyVideoToApplicationDirectory&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; filename &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;file1.mp4&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    var&lt;/span&gt;&lt;span&gt; bytes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; rootBundle.&lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;assets/file1.mp4&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    String&lt;/span&gt;&lt;span&gt; dir &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; getApplicationDocumentsDirectory&lt;/span&gt;&lt;span&gt;()).path;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    writeToFile&lt;/span&gt;&lt;span&gt;(bytes, &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;dir&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;filename&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; &apos;&lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;dir&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;filename&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ///Write to Path.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Future&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;writeToFile&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ByteData&lt;/span&gt;&lt;span&gt; data, &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; path) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    final&lt;/span&gt;&lt;span&gt; buffer &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; data.buffer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; File&lt;/span&gt;&lt;span&gt;(path).&lt;/span&gt;&lt;span&gt;writeAsBytes&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        buffer.&lt;/span&gt;&lt;span&gt;asUint8List&lt;/span&gt;&lt;span&gt;(data.offsetInBytes, data.lengthInBytes));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;copyVideoToApplicationDirectory&lt;/code&gt; method is copying the video from Assets to the Application directory on the phone’s file system. The resulting path is then stored in the &lt;code&gt;inputPath&lt;/code&gt; variable which is then supplied to the FFmpeg command. For large‑scale workloads, you can move this FFmpeg command to &lt;a href=&quot;https://img.ly/blog/how-to-run-ffmpeg-on-aws-spot-instances-for-scalable-low-cost-video-processing/&quot;&gt;AWS Spot Instances&lt;/a&gt;; our AWS guide shows how to configure a cloud environment for scalable video processing.&lt;/p&gt;
&lt;p&gt;Next, add the &lt;code&gt;VideoPlayer&lt;/code&gt; widget to the &lt;code&gt;Column&lt;/code&gt; widget.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;dart&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Column&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  children&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    (controller &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ?&lt;/span&gt;&lt;span&gt; AspectRatio&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        aspectRatio&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; controller&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;.value.aspectRatio,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        child&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; VideoPlayer&lt;/span&gt;&lt;span&gt;(controller&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        :&lt;/span&gt;&lt;span&gt; const&lt;/span&gt;&lt;span&gt; SizedBox&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run the app and the video should start playing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;You can now play your video.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 323px) 323px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;323&quot; height=&quot;700&quot; src=&quot;https://img.ly/_astro/resized_screen_2sxrDY.webp&quot; srcset=&quot;/_astro/resized_screen_2sxrDY.webp 323w&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the next step, we will add the FFmpeg command, but before that add the following 2 more methods to the &lt;code&gt;_MyHomePageState&lt;/code&gt; class.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;dart&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;package:ffmpeg_kit_flutter/ffmpeg_kit.dart&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;package:ffmpeg_kit_flutter/log.dart&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &apos;package:ffmpeg_kit_flutter/return_code.dart&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; _MyHomePageState&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; State&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;MyHomePage&lt;/span&gt;&lt;span&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  /// Output path with a file name where the result will be stored.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Future&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;getOutputPath&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    final&lt;/span&gt;&lt;span&gt; appDirectory &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Platform&lt;/span&gt;&lt;span&gt;.isAndroid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ?&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; getExternalStorageDirectory&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        :&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; getApplicationDocumentsDirectory&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    final&lt;/span&gt;&lt;span&gt; externalPath &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;appDirectory&lt;/span&gt;&lt;span&gt;?.&lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;/out_file.mp4&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; externalPath;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ///Executes the FFMPEG &lt;/span&gt;&lt;span&gt;[command]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ///Note: Green bar on the right is a Flutter issue. &amp;#x3C;https://github.com/flutter/engine/pull/24888&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ///Should get fixed in a 3.1.0+ stable release &amp;#x3C;https://github.com/flutter/engine/pull/24888#issuecomment-1212374010&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Future&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;ffmpegExecute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; command) &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    final&lt;/span&gt;&lt;span&gt; session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; FFmpegKit&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;(command);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    final&lt;/span&gt;&lt;span&gt; returnCode &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getReturnCode&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;ReturnCode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;isSuccess&lt;/span&gt;&lt;span&gt;(returnCode)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Success&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      //Replace the preview video&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      await&lt;/span&gt;&lt;span&gt; controller&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;pause&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      await&lt;/span&gt;&lt;span&gt; controller&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dispose&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      controller &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; VideoPlayerController&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;(outputPath));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      await&lt;/span&gt;&lt;span&gt; controller&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;initialize&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      await&lt;/span&gt;&lt;span&gt; controller&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;play&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      setState&lt;/span&gt;&lt;span&gt;(() {});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;ReturnCode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;isCancel&lt;/span&gt;&lt;span&gt;(returnCode)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Cancel&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Error&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      final&lt;/span&gt;&lt;span&gt; failStackTrace &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getFailStackTrace&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      print&lt;/span&gt;&lt;span&gt;(failStackTrace);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      List&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Log&lt;/span&gt;&lt;span&gt;&gt; logs &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getLogs&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; element &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; logs) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        print&lt;/span&gt;&lt;span&gt;(element.&lt;/span&gt;&lt;span&gt;getMessage&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;getOutputPath&lt;/code&gt; method provides the path where the resulting video will be saved. The &lt;code&gt;outputPath&lt;/code&gt; will be passed to the FFmpeg command whereas the &lt;code&gt;ffmpegExecute&lt;/code&gt; method is where the FFmpeg magic takes place.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ffmpegExecute&lt;/code&gt; method expects a valid FFmpeg &lt;code&gt;String&lt;/code&gt; command. The &lt;code&gt;String&lt;/code&gt; command is then passed to the &lt;code&gt;FFmpegKit.execute&lt;/code&gt; method which returns an instance of &lt;code&gt;FFMpegSession&lt;/code&gt; . It will tell us whether our command was executed successfully or not. If it was not executed successfully, we can extract error logs from it.&lt;/p&gt;
&lt;h3 id=&quot;ffmpeg-execute-command&quot;&gt;FFmpeg Execute Command&lt;/h3&gt;
&lt;p&gt;Add a &lt;code&gt;TextButton&lt;/code&gt; from where the FFmpeg command shall be sent.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;dart&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;TextButton&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  child&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Text&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Save Video&apos;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  onPressed&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    //TODO: Call FFMPEG Execute&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, call the following &lt;code&gt;ffmpegExecute&lt;/code&gt; method from the &lt;code&gt;onPressed&lt;/code&gt; property.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;dart&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ffmpegExecute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;-ss 0:00:15 -to 0:00:45 -y -i &lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;inputPath&lt;/span&gt;&lt;span&gt; -filter:v &quot;crop=320:150&quot; -c:a copy &lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;outputPath&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run the app and tap the &lt;strong&gt;Save Video&lt;/strong&gt; button. You will notice that the player is now playing the new cropped and trimmed video.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;You can now play your cropped and trimmed video!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 323px) 323px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;323&quot; height=&quot;700&quot; src=&quot;https://img.ly/_astro/flutter_video_app_crop_trim_screen_ZP5gb4.webp&quot; srcset=&quot;/_astro/flutter_video_app_crop_trim_screen_ZP5gb4.webp 323w&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you were able to successfully follow the instructions up till here, it is time to dig a little deeper into the FFmpeg command that we just ran earlier.&lt;/p&gt;
&lt;h3 id=&quot;understanding-the-ffmpeg-command&quot;&gt;Understanding the FFmpeg Command&lt;/h3&gt;
&lt;p&gt;Because command FFmpeg is a command line tool, it expects string-only commands. For this reason, we do not have any dart Classes, Methods, or Parameters to work with that we usually get when working with a dart plugin. Let us dissect the above command line command that is helping us crop and trim a video.&lt;/p&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Command&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;-ss 0:00:15&lt;/td&gt;&lt;td&gt;Seeks to position on the input video. The trim starts from this position.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;-to 0:00:45&lt;/td&gt;&lt;td&gt;Stops reading at the position in the input video. The trim stops at this position. The total length of the video is 0:02:05.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;-y&lt;/td&gt;&lt;td&gt;Overwrite output files. Helpful when the Save Video button is tapped more than once.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;-i $inputPath&lt;/td&gt;&lt;td&gt;Input file location. This is the file on which the crop and trim are applied.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;-filter:v&lt;/td&gt;&lt;td&gt;Apply a filter to the video stream.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;”crop=320:150”&lt;/td&gt;&lt;td&gt;Apply a crop filter from the center of the video that is 320 pixels wide and 150 pixels tall. The original dimensions of the video were 320 x 240.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;-c:a copy $outputPath&lt;/td&gt;&lt;td&gt;Specifies the codec with which the output file must be encoded. Here, copy is a special value to indicate the stream is not to be re-encoded. The a after the colon is a stream specifier for the audio stream.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;That will be either the application directory or the external directory of the application, depending on whether the app is running on iOS or Android.&lt;/p&gt;
&lt;p&gt;You can check out the app’s code and play with it by downloading it from this &lt;a href=&quot;https://github.com/numerative/flutter_crop_and_trim_video&quot;&gt;GitHub Repository&lt;/a&gt;. This project allows you to tweak the duration of the trim and dimensions of the crop, so it has more code, but at the heart of it, it still uses the above FFmpeg command.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Download this app code from the GitHub Repository.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 378px) 378px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;378&quot; height=&quot;700&quot; src=&quot;https://img.ly/_astro/flutter_video_app_crop_trim_info_Z2pzU1G.webp&quot; srcset=&quot;/_astro/flutter_video_app_crop_trim_info_Z2pzU1G.webp 378w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;cropping-using-the-video_trimmer-plugin&quot;&gt;Cropping Using the video_trimmer Plugin&lt;/h2&gt;
&lt;p&gt;As a bonus, here is a tip on how to use the video_trimmer plugin for cropping videos.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://pub.dev/packages/video_trimmer&quot;&gt;video_trimmer&lt;/a&gt; plugin also uses FFmpeg at its core and allows us to pass on an FFmpeg command while saving the video. For this reason, it is an easy task for us to apply the crop to a video using the video_trimmer plugin.&lt;/p&gt;
&lt;p&gt;To do this, pass the following command to the &lt;code&gt;saveTrimmedVideo&lt;/code&gt; method’s &lt;code&gt;ffmpegCommand&lt;/code&gt; parameter as shown in the code block below. The video_trimmer package expects the &lt;code&gt;customVideoFormat&lt;/code&gt; parameter argument when the &lt;code&gt;ffmpegCommand&lt;/code&gt; parameter is used.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;ruby&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;await &lt;/span&gt;&lt;span&gt;_trimmer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;saveTrimmedVideo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        startValue:&lt;/span&gt;&lt;span&gt; _startValue&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        endValue:&lt;/span&gt;&lt;span&gt; _endValue&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ffmpegCommand:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &apos;-filter:v &quot;crop=320:150&quot;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        customVideoFormat:&lt;/span&gt;&lt;span&gt; &apos;.mp4&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;((value) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  setState&lt;/span&gt;&lt;span&gt;(() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    _value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;limitations-of-this-approach&quot;&gt;Limitations of this Approach&lt;/h2&gt;
&lt;p&gt;The crop that we are applying is from the center of the frame. The present command would also need starting coordinates to crop a non-center frame.&lt;/p&gt;
&lt;p&gt;The project will need a refined UI for cropping and trimming videos to offer a complete app experience to users. The current approach is miles away from creating that experience.&lt;/p&gt;
&lt;p&gt;But perhaps the most significant limitation is FFmpeg’s &lt;strong&gt;licensing&lt;/strong&gt;. FFmpeg is available with both LGPL and GPL licenses, so you must ensure your project is compatible with those licenses. For many commercial projects, this is a non-starter. Alternatively, you can &lt;a href=&quot;https://img.ly/blog/ffmpeg-on-google-cloud-platform-guide/&quot;&gt;run FFmpeg on Google Cloud Platform&lt;/a&gt;; our GCP tutorial walks you through setup.&lt;/p&gt;
&lt;h2 id=&quot;commercial-alternative&quot;&gt;Commercial Alternative&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/docs/vesdk/flutter/getting-started/integration/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;VideoEditor SDK (VE.SDK)&lt;/a&gt; from &lt;a href=&quot;https://img.ly&quot;&gt;IMG.LY&lt;/a&gt; provides powerful video editing features, including cropping and trimming videos in a Flutter project. You will receive staples of video editing, including straightening videos, filters, brightness, color adjustments, and more. Follow our guide to learn how to integrate IMG.LY’s &lt;a href=&quot;https://img.ly/blog/a-modern-video-editor-sdk-for-your-flutter-app/&quot;&gt;video editor for Flutter&lt;/a&gt; into your app.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;While still a complex topic, video manipulation is more attainable to implement on Flutter than on native Android. Nevertheless, FFmpeg is the only open-source, free-to-use option to edit videos on Flutter right now. To automate cropping and trimming across many files or build a transcoding server, see our article on &lt;a href=&quot;https://img.ly/blog/building-a-production-ready-batch-video-processing-server-with-ffmpeg/&quot;&gt;building a production‑ready batch video processing server.&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Michael H.</dc:creator><media:content url="https://blog.img.ly/2022/09/trim_videos_with_flutter_tutorial.png" medium="image"/><category>How-To</category><category>Flutter</category><category>Video Editor</category><category>App Development</category><category>FFmpeg</category><category>Tutorial</category></item><item><title>PE.SDK and VE.SDK 10 for Android and 11 for iOS Release</title><link>https://img.ly/blog/photo-editor-video-editor-sdk-v_10-11-release-notes/</link><guid isPermaLink="true">https://img.ly/blog/photo-editor-video-editor-sdk-v_10-11-release-notes/</guid><description>This major update brings Background Removal and more to PhotoEditor SDK and VideoEditor SDK.</description><pubDate>Wed, 04 May 2022 12:46:21 GMT</pubDate><content:encoded>&lt;p&gt;We are thrilled to announce the release of PhotoEditor SDK and VideoEditor SDK 10 for Android and 11 for iOS. This new major version is packed with features and improvements.&lt;/p&gt;
&lt;p&gt;This release is adding:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Custom Watermarks&lt;/li&gt;
&lt;li&gt;Background Removal for Photos&lt;/li&gt;
&lt;li&gt;Background Removal for Stickers&lt;/li&gt;
&lt;li&gt;Custom Sticker Libraries&lt;/li&gt;
&lt;li&gt;Giphy Integration&lt;/li&gt;
&lt;li&gt;And More Updates for Android and iOS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;custom-watermarks&quot;&gt;Custom Watermarks&lt;/h2&gt;
&lt;p&gt;With our new support for custom watermarks, you can add your company logo or any other image to photo and video exports. You can place your watermark in either corner or the center of your photo and video. Additionally, you can specify the size of the watermark and determine its distance from the outline if you choose to place it near a corner. Your users will not be able to remove nor modify the watermark.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Set your Custom Watermark for all exports.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 277px) 277px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;277&quot; height=&quot;600&quot; src=&quot;https://img.ly/_astro/watermark-video-editor-custom-sdk_Z12Y3l4.webp&quot; srcset=&quot;/_astro/watermark-video-editor-custom-sdk_Z12Y3l4.webp 277w&quot;&gt;&lt;/p&gt;
&lt;p&gt;For more details on Custom Watermarks, take a look at our documentation for &lt;a href=&quot;https://img.ly/docs/pesdk/android/customization/watermark/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes&quot;&gt;Android&lt;/a&gt; or &lt;a href=&quot;https://img.ly/docs/pesdk/ios/customization/watermark/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes&quot;&gt;iOS&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;background-removal-for-photos&quot;&gt;Background Removal for Photos&lt;/h2&gt;
&lt;p&gt;You have unwaveringly requested this feature: we are excited to offer the automatic removal of backgrounds for static content! Background Removal is fully running &lt;strong&gt;on-device&lt;/strong&gt; and currently specializes in images containing a person only. PE.SDK enables this feature exclusively when it detects a person in the photo.&lt;/p&gt;
&lt;p&gt;The removed background will turn transparent if your selected output supports transparency, such as PNG. In other cases, such as JPG, your background removal will be tinted black.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Integrate Background Removal into your application.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 277px) 277px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;277&quot; height=&quot;600&quot; src=&quot;https://img.ly/_astro/background-removal-photo-editor-app-pe-sdk-1_2jocg8.webp&quot; srcset=&quot;/_astro/background-removal-photo-editor-app-pe-sdk-1_2jocg8.webp 277w&quot;&gt;&lt;/p&gt;
&lt;p&gt;This feature is available on Android and iOS 15.0 and higher only. Easily enable Background Removal for Photos with our &lt;a href=&quot;https://img.ly/docs/pesdk/android/features/background_removal/&quot;&gt;Android guide&lt;/a&gt; or &lt;a href=&quot;https://img.ly/docs/pesdk/ios/features/background_removal/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes&quot;&gt;iOS guide&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;background-removal-for-stickers&quot;&gt;Background Removal for Stickers&lt;/h2&gt;
&lt;p&gt;A more common use case for automatic background removal is with stickers, so we’ve also added this functionality. Select a sticker including a person and tap the &lt;em&gt;Remove BG&lt;/em&gt; button. Simple!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Let your users create beautiful visuals with Sticker Background Removal.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 277px) 277px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;277&quot; height=&quot;600&quot; src=&quot;https://img.ly/_astro/background-removal-photo-editor-app-pe-sdk-video_2nmAzB.webp&quot; srcset=&quot;/_astro/background-removal-photo-editor-app-pe-sdk-video_2nmAzB.webp 277w&quot;&gt;&lt;/p&gt;
&lt;p&gt;This feature is available on Android and iOS 15.0 and higher only. Easily enable Background Removal for Stickers with our &lt;a href=&quot;https://img.ly/docs/vesdk/android/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#background-removal&quot;&gt;Android documentation&lt;/a&gt; or &lt;a href=&quot;https://img.ly/docs/vesdk/ios/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#background-removal&quot;&gt;iOS documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;custom-sticker-libraries&quot;&gt;Custom Sticker Libraries&lt;/h2&gt;
&lt;p&gt;We wanted to make it easier for you to provide your users with more sticker tool content. So far, you were able to create multiple sticker categories with different stickers that could either be part of your app or stored on a server. Additionally, you could &lt;a href=&quot;https://img.ly/docs/pesdk/ios/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#personal-stickers&quot;&gt;enable our personal stickers feature on iOS&lt;/a&gt; or &lt;a href=&quot;https://img.ly/docs/pesdk/ios/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#personal-stickers&quot;&gt;Android&lt;/a&gt;), giving your users the option to select stickers from their camera roll.&lt;/p&gt;
&lt;p&gt;We have now added more ways to provide your users with stickers.&lt;/p&gt;
&lt;h3 id=&quot;android&quot;&gt;Android&lt;/h3&gt;
&lt;p&gt;You can now create sticker categories that do not present our sticker selection interface, but will instead load any arbitrary Fragment. That gives you complete control over the sticker selection screen, and you can use it to load and display any content. When the user selects any of your stickers, all you have to do is pass it back to the SDK with a callback. Get started with your &lt;a href=&quot;https://img.ly/docs/vesdk/android/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#adding-custom-stickers&quot;&gt;Custom Sticker Library with our Android documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;ios&quot;&gt;iOS&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;You can now create sticker categories that do not present our sticker selection interface, but will instead load any arbitrary view controller that conforms to the &lt;code&gt;StickerCollection&lt;/code&gt; protocol. That gives you complete control over the sticker selection screen, and you can use it to load and display any content. When the user selects any of your stickers, simply pass it back to the SDK using a delegate method.&lt;/li&gt;
&lt;li&gt;Additionally, we’ve created a new &lt;code&gt;StickerProviderCategory&lt;/code&gt; that you can pass any object conforming to the &lt;code&gt;StickerProvider&lt;/code&gt; protocol. This category provides most of the features required to interact with sticker content providers, such as search and pagination. You can use this category to very quickly integrate any sticker service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Find more information on &lt;a href=&quot;https://img.ly/docs/vesdk/ios/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#custom-sticker-view-controller&quot;&gt;Custom Sticker Libraries in the iOS documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;giphy-integration&quot;&gt;GIPHY Integration&lt;/h2&gt;
&lt;p&gt;This online database and search engine for funny GIFs and beautiful animations is a staple in many social applications. Easily integrate GIPHY into your app:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 277px) 277px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;277&quot; height=&quot;600&quot; src=&quot;https://img.ly/_astro/integrate-giphy-video-editor-photo-sdk_ZNfYn8.webp&quot; srcset=&quot;/_astro/integrate-giphy-video-editor-photo-sdk_ZNfYn8.webp 277w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;android-1&quot;&gt;Android&lt;/h3&gt;
&lt;p&gt;Using our new Custom Sticker Library, we’ve also created an integration for GIPHY on Android. All you have to do is head over to &lt;a href=&quot;https://developers.giphy.com&quot;&gt;GIPHY&lt;/a&gt;, create your API key, pass it to your &lt;code&gt;GiphySettings&lt;/code&gt; and create a &lt;code&gt;GiphyStickerCategoryItem&lt;/code&gt;. Your users will then immediately have access to all the content GIPHY has to offer.&lt;/p&gt;
&lt;p&gt;For more details, visit our &lt;a href=&quot;https://img.ly/docs/vesdk/android/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#adding-giphy&quot;&gt;documentation on adding GIPHY&lt;/a&gt; for Android.&lt;/p&gt;
&lt;h3 id=&quot;ios-1&quot;&gt;iOS&lt;/h3&gt;
&lt;p&gt;Using the new &lt;code&gt;StickerProviderCategory&lt;/code&gt;, we added GIPHY support on iOS. All you have to do is head over to &lt;a href=&quot;https://developers.giphy.com&quot;&gt;GIPHY&lt;/a&gt;, create your API key, and pass this to the GIPHY sticker category. Your users will then immediately have access to all the content GIPHY has to offer.&lt;/p&gt;
&lt;p&gt;For more details, visit our documentation &lt;a href=&quot;https://img.ly/docs/vesdk/ios/features/stickers/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#giphy&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;more-updates-for-android&quot;&gt;More Updates for Android&lt;/h2&gt;
&lt;p&gt;Additionally, we have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increased the minimum API level for PhotoEditor SDK from 16 (Android 4) to 21 (Android 5), which ensures support for 98% of all phones in use.&lt;/li&gt;
&lt;li&gt;Added support for headless video exporting.&lt;/li&gt;
&lt;li&gt;Increased video playback stability.&lt;/li&gt;
&lt;li&gt;Fixed a number of issues with degraded audio quality in videos.&lt;/li&gt;
&lt;li&gt;And added the ability to choose a theme at runtime.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;more-updates-for-ios&quot;&gt;More Updates for iOS&lt;/h2&gt;
&lt;p&gt;Additionally, we have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increased our deployment target from iOS 9 to iOS 13.&lt;/li&gt;
&lt;li&gt;Migrated all usage of OpenGL to Metal.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/vesdk/ios/introduction/migration/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes&quot;&gt;Added a better result API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/vesdk/ios/introduction/getting_started/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes#swiftui&quot;&gt;Added support for SwiftUI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Enhanced our video export to display a progress indicator and the option to cancel the export.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;thanks-for-reading-let-us-know-what-you-think-on-twitter-or-stay-in-the-loop-with-our-newsletter&quot;&gt;Thanks for reading! Let us know what you think on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt;, or stay in the loop with our &lt;a href=&quot;https://photoeditorsdk.us13.list-manage.com/subscribe?u=dc9f652839dbb620d14d6d28d&amp;#x26;id=04a306e4b2&quot;&gt;Newsletter&lt;/a&gt;.&lt;/h3&gt;</content:encoded><dc:creator>Sascha</dc:creator><media:content url="https://blog.img.ly/2022/05/photo-editor-sdk-video-editor-sdk-background-removal.png" medium="image"/><category>Release Notes</category><category>Photo Editor</category><category>Video Editor</category><category>Android App Development</category><category>iOS App Development</category><category>App Development</category></item><item><title>How to Make Videos from Still Images with AVFoundation and Swift</title><link>https://img.ly/blog/how-to-make-videos-from-still-images-with-avfoundation-and-swift/</link><guid isPermaLink="true">https://img.ly/blog/how-to-make-videos-from-still-images-with-avfoundation-and-swift/</guid><description>Convert still images into video files with two strategies.</description><pubDate>Thu, 10 Feb 2022 15:35:45 GMT</pubDate><content:encoded>&lt;p&gt;Whether making a slide show or breaking up video tracks with title scenes, inserting still images into a video file can be tricky. This tutorial will show you how to convert still images into standard Quicktime video files so you can work with them further in your favorite video editor. This tutorial was created and tested with Xcode 13 and Swift 5. This tutorial will discuss two strategies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;convert each image to a separate movie and stitch them together later (this is best suited for times you want to interleave the images and other video files using some other editing workflow)&lt;/li&gt;
&lt;li&gt;create a “blank” video and use the &lt;code&gt;applyingCIFiltersWithHandler&lt;/code&gt; variation to overlay the images (this is best suited for times you want to make a quick slide show with no further editing)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As with most &lt;code&gt;AVFoundation&lt;/code&gt; code, the Xcode simulator is not always the best platform for running the code. Test on an actual device if you can. A demo project with this code (and some extra goodies) can be found on &lt;a href=&quot;https://github.com/waltertyree/static-image-slideshow&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-problem-with-an-image&quot;&gt;The Problem with an Image&lt;/h2&gt;
&lt;p&gt;The basic models that are used in &lt;code&gt;AVFoundation&lt;/code&gt; for making video files are &lt;code&gt;AVAsset&lt;/code&gt; and &lt;code&gt;AVAssetTrack&lt;/code&gt;. You can compose multiple tracks and assets together to make a single video file. All tracks must have some media data and a duration. Static image files don’t have a duration. This is the primary problem you have to overcome when you want to add static images to video.&lt;br&gt;
Fortunately, you can use many of the same &lt;code&gt;AVFoundation&lt;/code&gt; tools that are used for video capture and frame manipulation. However instead of using a &lt;code&gt;CADisplayLink&lt;/code&gt; and &lt;code&gt;AVPlayerItemVideoOutput&lt;/code&gt; or an &lt;code&gt;AVCaptureDevice&lt;/code&gt; to provide frame buffers to save, you will create the frame buffers manually. Then you can use &lt;code&gt;AVAssetWriter&lt;/code&gt; to convert the frame buffers into a video file.&lt;/p&gt;
&lt;p&gt;Some items to consider before you actually generate the video file are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What framerate to use? Because the image doesn’t have any motion, you can use a very low frame rate to create smaller file sizes. However, this might cause issues if you are interleaving it with regular video, which usually has a frame rate of 30 or 60 fps (or higher, for slow motion video)&lt;/li&gt;
&lt;li&gt;What dimensions will the final video have? It is easy to resize an image and add padding using &lt;code&gt;CoreImage&lt;/code&gt; or some image editing software before it becomes a video. As the image becomes a video and moves through different steps in an &lt;code&gt;AVFoundation&lt;/code&gt; pipeline, the different classes in &lt;code&gt;AVFoundation&lt;/code&gt; will resize or crop the images in different ways when the input dimensions and output dimension don’t match.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;writing-buffers-using-avassetwriter&quot;&gt;Writing Buffers using &lt;code&gt;AVAssetWriter&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;AVAssetWriter&lt;/code&gt; exists to encode media to a file on disk. Though this tutorial will use a single video input &lt;code&gt;AVAssetWriter&lt;/code&gt; supports multiple inputs of different kinds (audio, video, metadata). It is quite similar to &lt;code&gt;AVAssetExportSession&lt;/code&gt;. The difference is that &lt;code&gt;AVAssetWriter&lt;/code&gt; uses multiple inputs and each input is a single track where the &lt;code&gt;AVAssetExportSession&lt;/code&gt; takes a single &lt;code&gt;AVAsset&lt;/code&gt; as an input. The result of both is a single file.&lt;/p&gt;
&lt;p&gt;As indicated above, our basic strategy will be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a pixel buffer that is the correct color space and size to hold the image&lt;/li&gt;
&lt;li&gt;Render the image into the pixel buffer&lt;/li&gt;
&lt;li&gt;Create an &lt;code&gt;AVAssetWriter&lt;/code&gt; with a single video input&lt;/li&gt;
&lt;li&gt;Decide how many frames will be required to create a video of the desired duration&lt;/li&gt;
&lt;li&gt;Make a loop, and each time through the loop, append the pixel buffer&lt;/li&gt;
&lt;li&gt;Clean up&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;create-the-pixel-buffer&quot;&gt;Create the Pixel Buffer&lt;/h3&gt;
&lt;p&gt;The code below creates a &lt;code&gt;CIImage&lt;/code&gt; from an image file. Then it creates a pixel buffer the same size as the image and uses a standard color space. Finally, a &lt;code&gt;CIContext&lt;/code&gt; renders the image into the pixel buffer.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create a CIImage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;guard&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; uikitImage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UIImage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;named&lt;/span&gt;&lt;span&gt;: imageName), &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; staticImage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CIImage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: uikitImage) &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  throw&lt;/span&gt;&lt;span&gt; ConstructionError.invalidImage &lt;/span&gt;&lt;span&gt;//this is an error type I made up&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create a variable to hold the pixelBuffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; pixelBuffer: CVPixelBuffer&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//set some standard attributes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; attrs &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [kCVPixelBufferCGImageCompatibilityKey&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; kCFBooleanTrue,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     kCVPixelBufferCGBitmapContextCompatibilityKey&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; kCFBooleanTrue] &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; CFDictionary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create the width and height of the buffer to match the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; width:&lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Int&lt;/span&gt;&lt;span&gt;(staticImage.extent.&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;.width)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; height:&lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Int&lt;/span&gt;&lt;span&gt;(staticImage.extent.&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;.height)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create a buffer (notice it uses an in/out parameter for the pixelBuffer variable)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;CVPixelBufferCreate&lt;/span&gt;&lt;span&gt;(kCFAllocatorDefault,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    width,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    height,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    kCVPixelFormatType_32BGRA,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    attrs,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    &amp;#x26;&lt;/span&gt;&lt;span&gt;pixelBuffer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create a CIContext&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; context &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CIContext&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//use the context to render the image into the pixelBuffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;context.&lt;/span&gt;&lt;span&gt;render&lt;/span&gt;&lt;span&gt;(staticImage, &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt;: pixelBuffer&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Though we generally think of &lt;code&gt;CIImage&lt;/code&gt; as an image, Apple is clear that it is not an image by itself. &lt;code&gt;CIImage&lt;/code&gt; needs a context for rendering. This is where a lot of the power of CoreImage and filters and GPU rendering come from, the fact that &lt;code&gt;CIImage&lt;/code&gt; is just the instructions for creating an image. Note: You can also use &lt;code&gt;CGImage&lt;/code&gt; and the &lt;code&gt;CoreGraphics&lt;/code&gt; framework to create pixel buffers. I find it easier to use the &lt;code&gt;CoreImage&lt;/code&gt; framework.&lt;/p&gt;
&lt;h3 id=&quot;configure-avassetwriter&quot;&gt;Configure AVAssetWriter&lt;/h3&gt;
&lt;p&gt;Now with a buffer created, you can configure the &lt;code&gt;AVAssetWriter&lt;/code&gt;. It will take several parameters as a dictionary to determine the dimensions and format of the outputs. You can either set them individually or else Apple provides presets.&lt;br&gt;
One of the most important settings is the output dimension. If the output dimension matches the original image, the video file will show no distortion or letterboxing. However, if the output is smaller, it will compress the image until it fits. If the output is larger, the image will expand until its width or height matches the output size and then will letterbox. Note: if an image expands too much, it will appear grainy. The image below shows different output sizes for a 640 x 480 input image.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;output-sizes&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 766px) 766px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;766&quot; height=&quot;738&quot; src=&quot;https://img.ly/_astro/output-sizes_ZiCM8f.webp&quot; srcset=&quot;/_astro/output-sizes_kVhrb.webp 640w, /_astro/output-sizes_Z1186Wa.webp 750w, /_astro/output-sizes_ZiCM8f.webp 766w&quot;&gt;&lt;/p&gt;
&lt;p&gt;To create your settings for the &lt;code&gt;AVAssetWriter&lt;/code&gt; first create a dictionary containing the different values. The example here sets an output dimension of 400 x 400 and provides for &lt;code&gt;.h264&lt;/code&gt; encoding.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; assetWriterSettings &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [AVVideoCodecKey&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; AVVideoCodecType.h264, AVVideoWidthKey &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 400&lt;/span&gt;&lt;span&gt;, AVVideoHeightKey&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 400&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; : &lt;/span&gt;&lt;span&gt;Any&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To use one of the presets, use the &lt;code&gt;AVOutputSettingsAssistant&lt;/code&gt;. You can read about the different settings in the &lt;a href=&quot;https://developer.apple.com/documentation/avfoundation/avoutputsettingsassistant&quot;&gt;Apple documentation&lt;/a&gt;. An example to create 1080p video output would look like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; settingsAssistant &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVOutputSettingsAssistant&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;preset&lt;/span&gt;&lt;span&gt;: .preset1920x1080)&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.videoSettings&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;write-the-pixel-buffer-to-the-video-file&quot;&gt;Write the pixel buffer to the video file&lt;/h3&gt;
&lt;p&gt;With the settings configured, the asset writer can loop through and append the contents of the pixel buffer to create each frame of the video. Something important to notice in the code below is that &lt;code&gt;AVFoundation&lt;/code&gt; has a philosophy to preserve data. So, it will make copies, and it will generally not overwrite files. That is why you have to delete any old files before you can create the new &lt;code&gt;AVAssetWriter&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//generate a file url to store the video. some_image.jpg becomes some_image.mov&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;guard&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; imageNameRoot &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; imageName.&lt;/span&gt;&lt;span&gt;split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;separator&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;.&quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; outputMovieURL &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; FileManager.default.&lt;/span&gt;&lt;span&gt;urls&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt;: .documentDirectory, &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;: .userDomainMask).&lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;appendingPathComponent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\(imageNameRoot)&lt;/span&gt;&lt;span&gt;.mov&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  throw&lt;/span&gt;&lt;span&gt; ConstructionError.invalidURL &lt;/span&gt;&lt;span&gt;//an error i made up&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//delete any old file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;do&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  try&lt;/span&gt;&lt;span&gt; FileManager.default.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;at&lt;/span&gt;&lt;span&gt;: outputMovieURL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Could not remove file &lt;/span&gt;&lt;span&gt;\(error.&lt;/span&gt;&lt;span&gt;localizedDescription&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create an assetwriter instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;guard&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; assetwriter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; try?&lt;/span&gt;&lt;span&gt; AVAssetWriter&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;outputURL&lt;/span&gt;&lt;span&gt;: outputMovieURL, &lt;/span&gt;&lt;span&gt;fileType&lt;/span&gt;&lt;span&gt;: .mov) &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  abort&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//generate 1080p settings&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; settingsAssistant &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVOutputSettingsAssistant&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;preset&lt;/span&gt;&lt;span&gt;: .preset1920x1080)&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.videoSettings&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create a single video input&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; assetWriterInput &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVAssetWriterInput&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;mediaType&lt;/span&gt;&lt;span&gt;: .video, &lt;/span&gt;&lt;span&gt;outputSettings&lt;/span&gt;&lt;span&gt;: settingsAssistant)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//create an adaptor for the pixel buffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; assetWriterAdaptor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVAssetWriterInputPixelBufferAdaptor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;assetWriterInput&lt;/span&gt;&lt;span&gt;: assetWriterInput, &lt;/span&gt;&lt;span&gt;sourcePixelBufferAttributes&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//add the input to the asset writer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;assetwriter.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(assetWriterInput)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//begin the session&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;assetwriter.&lt;/span&gt;&lt;span&gt;startWriting&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;assetwriter.&lt;/span&gt;&lt;span&gt;startSession&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;atSourceTime&lt;/span&gt;&lt;span&gt;: CMTime.zero)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//determine how many frames we need to generate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; framesPerSecond &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 30&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//duration is the number of seconds for the final video&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; totalFrames &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; duration &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; framesPerSecond&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; frameCount &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; frameCount &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; totalFrames {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; assetWriterInput.isReadyForMoreMediaData {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let&lt;/span&gt;&lt;span&gt; frameTime &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CMTimeMake&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Int64&lt;/span&gt;&lt;span&gt;(frameCount), &lt;/span&gt;&lt;span&gt;timescale&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Int32&lt;/span&gt;&lt;span&gt;(framesPerSecond))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    //append the contents of the pixelBuffer at the correct time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    assetWriterAdaptor.&lt;/span&gt;&lt;span&gt;append&lt;/span&gt;&lt;span&gt;(pixelBuffer&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;withPresentationTime&lt;/span&gt;&lt;span&gt;: frameTime)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    frameCount&lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//close everything&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;assetWriterInput.&lt;/span&gt;&lt;span&gt;markAsFinished&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;assetwriter.&lt;/span&gt;&lt;span&gt;finishWriting&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  pixelBuffer &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //outputMovieURL now has the video&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Logger&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Finished video location: &lt;/span&gt;&lt;span&gt;\(outputMovieURL)&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, your image has become a Quicktime video of whatever duration you specified and is ready for use as any other video file! You can now continue with the like of &lt;a href=&quot;https://img.ly/products/video-sdk&quot;&gt;VideoEditor SDK&lt;/a&gt; to &lt;a href=&quot;https://img.ly/blog/new-force-trim-function-for-videoeditor-sdk/&quot;&gt;trim videos&lt;/a&gt;, and &lt;a href=&quot;https://img.ly/blog/how-to-apply-filter-effects-to-video-using-videffects-on-android/&quot;&gt;add filters&lt;/a&gt; or &lt;a href=&quot;https://img.ly/blog/how-to-add-overlays-to-a-video-in-react-native/&quot;&gt;overlays&lt;/a&gt;. You might also want to combine the video with &lt;a href=&quot;https://img.ly/blog/combine-video-clips-into-a-new-file-in-ios-with-swift/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;other video files to make a new creation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Say hi to my dog! A plain video from still images&lt;/p&gt;
&lt;h2 id=&quot;creating-a-blank-video&quot;&gt;Creating a Blank Video&lt;/h2&gt;
&lt;p&gt;The previous example created a single &lt;code&gt;.mov&lt;/code&gt; file for each of your images. The most robust way to get these images into a video with sound, transitions, etc., is to use &lt;code&gt;AVMutableComposition&lt;/code&gt; with multiple tracks and layer instructions. However, for a quick slideshow with just a few elementary transitions, a strategy is to create a blank movie and then use &lt;code&gt;AVVideoComposition&lt;/code&gt; with &lt;code&gt;(asset: AVAsset, applyingCIFiltersWithHandler applier: @escaping (AVAsynchronousCIImageFilteringRequest) -&gt; Void)&lt;/code&gt;. That will let you use &lt;code&gt;CIImage&lt;/code&gt; and &lt;code&gt;CIFilter&lt;/code&gt; to paint each frame of the blank movie with images.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Our basic strategy for this method will be:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a pixel buffer that is the right color space and size and fill it with a solid color&lt;/li&gt;
&lt;li&gt;Create an &lt;code&gt;AVAssetWriter&lt;/code&gt; with a single video input&lt;/li&gt;
&lt;li&gt;Decide how many frames will be required to create a video of the desired duration&lt;/li&gt;
&lt;li&gt;Make a loop and each time through the loop append the pixel buffer&lt;/li&gt;
&lt;li&gt;Create an &lt;code&gt;AVVideoComposition&lt;/code&gt; to add the images to the individual frames of the video&lt;/li&gt;
&lt;li&gt;Let &lt;code&gt;AVPlayer&lt;/code&gt; combine the video and the composition&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the first strategy, you started by making a pixel buffer and using an &lt;code&gt;AVAssetWriter&lt;/code&gt; to create the video file using this code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;guard&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; uikitImage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UIImage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;named&lt;/span&gt;&lt;span&gt;: imageName), &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; staticImage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CIImage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: uikitImage) &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  throw&lt;/span&gt;&lt;span&gt; ConstructionError.invalidImage &lt;/span&gt;&lt;span&gt;//this is an error type I made up&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, this time, instead of using a source image, you create a &lt;code&gt;CIImage&lt;/code&gt; that is a single color.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; staticImage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CIImage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;color&lt;/span&gt;&lt;span&gt;: bgColor).&lt;/span&gt;&lt;span&gt;cropped&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;CGRect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;width&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;960&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;height&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;540&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;CIImage(color:)&lt;/code&gt; initializer creates an image that is of infinite size and is just a single color. Using the &lt;code&gt;.cropped(to:)&lt;/code&gt; modifier lets you make it the same size as the &lt;code&gt;AVAssetWriter&lt;/code&gt; output so that there won’t be any letterboxing. The rest of the code is the same as before and the end result will be a video file that is just the single color.&lt;/p&gt;
&lt;h3 id=&quot;adding-a-composition&quot;&gt;Adding a Composition&lt;/h3&gt;
&lt;p&gt;Once the video file has been created and saved to disk, load it as an asset, then create an &lt;code&gt;AVVideoComposition&lt;/code&gt;. This allows you to generate individual frames. The function below uses the &lt;code&gt;request&lt;/code&gt; property of the composition. This has a &lt;code&gt;CIImage&lt;/code&gt; representation of the current frame as well as the timestamp of when this frame will appear. The &lt;code&gt;.fetchSlide(forTime:)&lt;/code&gt; is a helper function in the demo app that returns the appropriate &lt;code&gt;CIImage&lt;/code&gt; for the slide to display. Then the &lt;code&gt;.sourceOverCompositing&lt;/code&gt; filter combines the original frame image with the slide. Using a &lt;code&gt;CGAffineTransform&lt;/code&gt; moves the slide across the screen as the video plays.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; createComposition&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt; asset: AVAsset) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  let&lt;/span&gt;&lt;span&gt; slideshowComposition &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVVideoComposition&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;asset&lt;/span&gt;&lt;span&gt;: asset) {[&lt;/span&gt;&lt;span&gt;weak&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;span&gt;] request &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    guard&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;span&gt; else&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let&lt;/span&gt;&lt;span&gt; slide &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;fetchSlide&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;forTime&lt;/span&gt;&lt;span&gt;: request.compositionTime)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let&lt;/span&gt;&lt;span&gt; compose &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CIFilter.&lt;/span&gt;&lt;span&gt;sourceOverCompositing&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;//filter to join two images&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    compose.backgroundImage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; request.sourceImage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    compose.inputImage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; slide&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;transformed&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;by&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;CGAffineTransform&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;translationX&lt;/span&gt;&lt;span&gt;: request.compositionTime.seconds &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; 50&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    //always finish with the last output of the pipeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    request.&lt;/span&gt;&lt;span&gt;finish&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt;: compose.outputImage&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  self&lt;/span&gt;&lt;span&gt;.outputSlideshow &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; slideshowComposition&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because the creation of the video is done asynchronously, you can composite images over the original frame and add filters without the danger of impacting the final frame rate. Recall that &lt;code&gt;CIFilter&lt;/code&gt; works as a pipeline, each &lt;code&gt;CIFilter&lt;/code&gt; has an &lt;code&gt;.outputImage&lt;/code&gt; and most have &lt;code&gt;.inputImage&lt;/code&gt; and some configuration settings. Feeding the output from one filter to the input of the next will let you build complex compositions. Once a composition has been created, &lt;code&gt;AVPlayer&lt;/code&gt; can join the original video with the composition for playback or export.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; item &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVPlayerItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;asset&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.outputMovie&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;item.videoComposition &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; outputSlideshow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.player &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVPlayer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;playerItem&lt;/span&gt;&lt;span&gt;: item)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code above might generate a video like this one.&lt;/p&gt;
&lt;p&gt;As with the first video, the final video is a plain &lt;code&gt;.mov&lt;/code&gt; file.&lt;/p&gt;
&lt;h2 id=&quot;going-further&quot;&gt;Going Further&lt;/h2&gt;
&lt;p&gt;In this tutorial, you saw two ways to convert static images into &lt;code&gt;.mov&lt;/code&gt; files that you can then edit with any video editor. The sample project also has some code for exporting your creation as a &lt;code&gt;.mov&lt;/code&gt; file and code for adding sound to the creation.&lt;/p&gt;
&lt;p&gt;These are not the only ways to go about solving this problem. For example, instead of creating a blank video and overlaying the images, using a stock video of waves at the beach and overlaying the images might work better for your project. Conversely, because the initial pixel buffer is created from a &lt;code&gt;CIImage&lt;/code&gt;, there is no reason that the &lt;code&gt;CIImage&lt;/code&gt; cannot be the end of a long pipeline of &lt;code&gt;CIFilters&lt;/code&gt;. This way the composition is done at the beginning, and the &lt;code&gt;AVAssetWriter&lt;/code&gt; is the only tool needed. The best strategy is the one that makes sense to you and that works with the kinds of media you have.&lt;/p&gt;
&lt;p&gt;Thanks for reading! We hope that you found this tutorial helpful. Feel free to reach out to us on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt; with any questions, comments, or suggestions!&lt;/p&gt;
&lt;p&gt;Looking to integrate video capabilities into your app? Check out our &lt;a href=&quot;https://img.ly/products/video-sdk&quot;&gt;Video Editor SDK&lt;/a&gt;, &lt;a href=&quot;https://img.ly/use-cases/story-reels-short-video-creation&quot;&gt;Short Video Creation&lt;/a&gt;, and &lt;a href=&quot;https://img.ly/products/camera-sdk&quot;&gt;Camera SDK&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To stay in the loop with our latest articles and case studies, subscribe to our &lt;a href=&quot;https://img.us13.list-manage.com/subscribe?u=dc9f652839dbb620d14d6d28d&amp;#x26;id=04a306e4b2&quot;&gt;Newsletter&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Walter</dc:creator><media:content url="https://blog.img.ly/2022/02/still-image-to-video-code.png" medium="image"/><category>Video Editing</category><category>Video Editor</category><category>Mobile App Development</category><category>App Development</category><category>Swift</category><category>How-To</category><category>Tech</category><category>Tutorial</category></item><item><title>May the Force Trim be with you: A New Feature in VE.SDK</title><link>https://img.ly/blog/new-force-trim-function-for-videoeditor-sdk/</link><guid isPermaLink="true">https://img.ly/blog/new-force-trim-function-for-videoeditor-sdk/</guid><description>Set the minimum and maximum duration of videos with our latest update.</description><pubDate>Tue, 14 Dec 2021 15:01:31 GMT</pubDate><content:encoded>&lt;p&gt;It has been a fantastic year for video editing – the &lt;a href=&quot;https://img.ly/blog/video-composition-audio-support/&quot;&gt;video composition tool and audio support&lt;/a&gt; enhanced our VideoEditor SDK offerings, enabling developers to bring more high-quality features right into your products and apps. Today, we deliver another feature to enhance your developer experience.&lt;/p&gt;
&lt;h2 id=&quot;force-trim&quot;&gt;Force Trim&lt;/h2&gt;
&lt;p&gt;The VideoEditor SDK trim tool allows your users to determine the start and end frame of a video clip, and thus change the duration of their footage. Now you are also able to &lt;strong&gt;enforce a minimum and maximum duration&lt;/strong&gt; of videos.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Set a minimum and/or a maximum duration for users.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1086px) 1086px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1086&quot; height=&quot;1139&quot; src=&quot;https://img.ly/_astro/min-max-length-videos-app-1_30n9P.webp&quot; srcset=&quot;/_astro/min-max-length-videos-app-1_Z2qfAdT.webp 640w, /_astro/min-max-length-videos-app-1_ZikVdt.webp 750w, /_astro/min-max-length-videos-app-1_1qCbwr.webp 828w, /_astro/min-max-length-videos-app-1_ZftVuf.webp 1080w, /_astro/min-max-length-videos-app-1_30n9P.webp 1086w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Additionally, the update allows configuring the &lt;strong&gt;startup behavior&lt;/strong&gt; of your editor. Possible values are &lt;code&gt;always&lt;/code&gt;, &lt;code&gt;ifNeeded&lt;/code&gt;, and &lt;code&gt;silent&lt;/code&gt; (the default).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;always&lt;/code&gt; will always automatically present the composition tool or the trim tool after opening the editor and force your users to change the length of the video(s).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ifNeeded&lt;/code&gt; will only present&lt;br&gt;
 a) the composition tool, if your initial composition is longer than the maximum duration or shorter than the minimum duration, or&lt;br&gt;
 b) the trim tool, if your initial video is longer than the maximum duration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;silent&lt;/code&gt; will automatically trim the video to the maximum duration without opening any tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Find the right set-up for your use-case in our official &lt;strong&gt;documentation&lt;/strong&gt; for &lt;a href=&quot;https://img.ly/docs/vesdk/ios/guides/trim/force-trim/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes&quot;&gt;iOS&lt;/a&gt; and &lt;a href=&quot;https://img.ly/docs/vesdk/android/features/trim#how-to-enforce-a-minimum-or-maximum-video-length/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=releasenotes&quot;&gt;Android&lt;/a&gt;. Once the trim tool is part of your subscription, you are ready to enhance your user experience.&lt;/p&gt;
&lt;h3 id=&quot;frameworks&quot;&gt;Frameworks&lt;/h3&gt;
&lt;p&gt;Of course, our &lt;a href=&quot;https://img.ly/docs/vesdk/quickstarts/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=announcements&quot;&gt;wrappers&lt;/a&gt; for &lt;strong&gt;Flutter, Cordova&lt;/strong&gt; and &lt;strong&gt;React Native&lt;/strong&gt; have been updated to support force trim.&lt;/p&gt;
&lt;h3 id=&quot;built-to-build&quot;&gt;Built to Build&lt;/h3&gt;
&lt;p&gt;Force Trim will come in handy for use cases, such as social media stories and posts, that have been popularly limited to bite size 15 or 60 seconds by widely loved apps – see TikTok or Instagram. Adopting a ready-to-use solution like &lt;a href=&quot;https://img.ly/video-sdk/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=announcements&quot;&gt;VideoEditor SDK&lt;/a&gt; will set you straight onto your path of creating equally beautiful apps by saving you resources and streamlining your process.&lt;/p&gt;
&lt;h3 id=&quot;a-sleek-user-experience&quot;&gt;A Sleek User Experience&lt;/h3&gt;
&lt;p&gt;Newly in is the interactive and animated timeline, that now elegantly adjusts to the trimming process.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Runs like butter: an interactive and animated timeline&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1280px) 1280px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1280&quot; height=&quot;720&quot; src=&quot;https://img.ly/_astro/video-editor-SDK-timeline-trim_Zq9FTB.webp&quot; srcset=&quot;/_astro/video-editor-SDK-timeline-trim_hFCNo.webp 640w, /_astro/video-editor-SDK-timeline-trim_v09gO.webp 750w, /_astro/video-editor-SDK-timeline-trim_Z1NV0b.webp 828w, /_astro/video-editor-SDK-timeline-trim_Zgg9YQ.webp 1080w, /_astro/video-editor-SDK-timeline-trim_Zq9FTB.webp 1280w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Aware of how time-consuming and costly app development can be for you, our team is committed to delivering more features to enhance your developer experience. &lt;strong&gt;Feel free to reach out to us on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt; with any questions, comments, or suggestions!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thank you for reading, and happy development!&lt;/p&gt;</content:encoded><dc:creator>Neslihan</dc:creator><media:content url="https://blog.img.ly/2021/12/trim-videos-app-videoapp.png" medium="image"/><category>Release Notes</category><category>Video Editor</category><category>App Development</category><category>Social Media</category><category>Videos</category><category>Company</category></item><item><title>How To Add Text to Video in Swift</title><link>https://img.ly/blog/add-text-to-video-in-swift/</link><guid isPermaLink="true">https://img.ly/blog/add-text-to-video-in-swift/</guid><description>Use Swift and AVMutableVideoComposition to add a text overlay to a video clip!</description><pubDate>Fri, 15 Oct 2021 15:05:59 GMT</pubDate><content:encoded>&lt;p&gt;In this article, you will see how to use Swift and AVMutableVideoComposition to add a text overlay to a video clip. The code in this article uses Swift 5. Clone &lt;a href=&quot;https://github.com/waltertyree/text-video&quot;&gt;this repository&lt;/a&gt; for a Swift Playground with the example code.&lt;/p&gt;
&lt;h2 id=&quot;setting-up&quot;&gt;Setting up&lt;/h2&gt;
&lt;p&gt;To access the &lt;code&gt;AVFoundation&lt;/code&gt; and &lt;code&gt;CoreImage&lt;/code&gt; objects, be sure to add these imports to your code&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; AVFoundation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CoreImage&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CIFilterBuiltins&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Importing the &lt;code&gt;CIFilterBuiltins&lt;/code&gt; lets you use autocompletion when working with &lt;code&gt;CIFilters&lt;/code&gt;. Otherwise, just import &lt;code&gt;CoreImage&lt;/code&gt;. But then you will need to access the filter properties using strings.&lt;/p&gt;
&lt;p&gt;When working with video clips and movie files, the basic starting point is the &lt;code&gt;AVAsset&lt;/code&gt; class. This class combines all of the timed video and audio tracks that make up a movie. Additionally there may be subtitles and timed metadata or captions.&lt;/p&gt;
&lt;h2 id=&quot;creating-a-video-composition&quot;&gt;Creating a Video Composition&lt;/h2&gt;
&lt;p&gt;After you create a video composition for an asset, you can apply it to an &lt;code&gt;AVPlayerItem&lt;/code&gt; to display on screen or to an &lt;code&gt;AVAssetExportSession&lt;/code&gt; to write to a file. The composition for this tutorial will use the &lt;code&gt;init(asset:applyingCIFiltersWithHandler:)&lt;/code&gt; initializer. Then you can apply &lt;code&gt;CIFilter&lt;/code&gt;s to each frame of the video.&lt;/p&gt;
&lt;p&gt;First, load a movie file as an &lt;code&gt;AVAsset&lt;/code&gt; using its URL.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Fetch a URL for the movie from the bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; waterfallURL &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Bundle.main.&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;forResource&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;waterfall&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;withExtension&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;mov&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Create an AVAsset with the url&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; waterfallAsset &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVAsset&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;: waterfallURL&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can create a &lt;code&gt;AVMutableVideoComposition&lt;/code&gt; with the asset&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; titleComposition &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVMutableVideoComposition&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;asset&lt;/span&gt;&lt;span&gt;: waterfallAsset) {request &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//apply filters here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;request.&lt;/span&gt;&lt;span&gt;finish&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt;: request.sourceImage, &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code above passes the video frame unaltered. The &lt;code&gt;request&lt;/code&gt; is the current video frame. It is an &lt;code&gt;AVAsynchronousCIImageFilteringRequest&lt;/code&gt; object. The &lt;code&gt;request&lt;/code&gt; object has three properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;sourceImage&lt;/code&gt; which is the video frame as a &lt;code&gt;CIImage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;renderSize&lt;/code&gt; which is the size of the video frame&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compositionTime&lt;/code&gt; which is the timestamp of the current frame&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code in the handler will run once for each frame of the video clip.&lt;/p&gt;
&lt;h2 id=&quot;generating-a-text-image&quot;&gt;Generating a Text Image&lt;/h2&gt;
&lt;p&gt;Because the &lt;code&gt;sourceImage&lt;/code&gt; is a &lt;code&gt;CIImage&lt;/code&gt;, you can use any of the over 200 &lt;code&gt;CIFilter&lt;/code&gt; objects that Core Image provides. There are two text generator filters: &lt;code&gt;CIAttributedTextImageGenerator&lt;/code&gt; and &lt;code&gt;CITextImageGenerator&lt;/code&gt;. Either of these will render a string as a &lt;code&gt;CIImage&lt;/code&gt;. This tutorial will use the Attributed Text version so you can modify the color and add a shadow.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;waterfall-text&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 642px) 642px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;642&quot; height=&quot;198&quot; src=&quot;https://img.ly/_astro/waterfall-text_Zf0kjo.webp&quot; srcset=&quot;/_astro/waterfall-text_9L6EH.webp 640w, /_astro/waterfall-text_Zf0kjo.webp 642w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Start by creating a shadow and then creating a dictionary of attributes to apply to the string.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; whiteShadow &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; NSShadow&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;whiteShadow.shadowBlurRadius &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;whiteShadow.shadowColor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UIColor.white&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; attributes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  NSAttributedString.&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;.foregroundColor &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; UIColor.blue,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  NSAttributedString.&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;.font &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; UIFont&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Marker Felt&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;36.0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  NSAttributedString.&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;.shadow &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; whiteShadow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create the attributed string by combining the string and the attributes&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; waterfallText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; NSAttributedString&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Waterfall!&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;attributes&lt;/span&gt;&lt;span&gt;: attributes)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Provide the attributed string and a scale factor to the filter to generate an image like the one shown above.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; textFilter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CIFilter.&lt;/span&gt;&lt;span&gt;attributedTextImageGenerator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;textFilter.&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; waterfallText&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;textFilter.scaleFactor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 4.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;textFilter.outputImage&lt;/code&gt; will be the image of the rendered text with the attributes applied. The &lt;code&gt;extent&lt;/code&gt; of the &lt;code&gt;outputImage&lt;/code&gt; will be a rectangle that is large enough to encompass the text. The text will render on a single line, it doesn’t wrap using this method.&lt;/p&gt;
&lt;p&gt;If you were to place the text on the video image at this point, the bottom-left of the text would be at the bottom-left of the video. Unlike &lt;code&gt;UIView&lt;/code&gt; objects, the origin point (0,0) is at the bottom-left, not the top-left. To center the text and move it off of the bottom, you can apply a standard &lt;code&gt;CGAffineTransform&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; centerHorizontal &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (request.renderSize.width &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; textFilter.outputImage&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;.extent.width)&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; moveTextTransform &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CGAffineTransform&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;translationX&lt;/span&gt;&lt;span&gt;: centerHorizontal, &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; positionedText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; textFilter.outputImage&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;transformed&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;by&lt;/span&gt;&lt;span&gt;: moveTextTransform)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now finish the pipeline by composing the new text image over the original source image.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;positionedText.&lt;/span&gt;&lt;span&gt;composited&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;over&lt;/span&gt;&lt;span&gt;: request.sourceImage)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All together, the original composition now becomes&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; titleComposition &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVMutableVideoComposition&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;asset&lt;/span&gt;&lt;span&gt;: waterfallAsset) { request &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Create a white shadow for the text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; whiteShadow &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; NSShadow&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;whiteShadow.shadowBlurRadius &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;whiteShadow.shadowColor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UIColor.white&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; attributes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  NSAttributedString.&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;.foregroundColor &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; UIColor.blue,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  NSAttributedString.&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;.font &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; UIFont&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Marker Felt&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;36.0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  NSAttributedString.&lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt;.shadow &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; whiteShadow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Create an Attributed String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; waterfallText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; NSAttributedString&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Waterfall!&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;attributes&lt;/span&gt;&lt;span&gt;: attributes)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Convert attributed string to a CIImage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; textFilter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CIFilter.&lt;/span&gt;&lt;span&gt;attributedTextImageGenerator&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;textFilter.&lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; waterfallText&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;textFilter.scaleFactor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 4.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Center text and move 200 px from the origin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//source image is 720 x 1280&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; positionedText &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; textFilter.outputImage&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;transformed&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;by&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;CGAffineTransform&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;translationX&lt;/span&gt;&lt;span&gt;: (request.renderSize.width &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; textFilter.outputImage&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;.extent.width)&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Compose text over video image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;request.&lt;/span&gt;&lt;span&gt;finish&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt;: positionedText.&lt;/span&gt;&lt;span&gt;composited&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;over&lt;/span&gt;&lt;span&gt;: request.sourceImage), &lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;displaying-the-finished-video&quot;&gt;Displaying The Finished Video&lt;/h2&gt;
&lt;p&gt;With an &lt;code&gt;AVAsset&lt;/code&gt; and an &lt;code&gt;AVMutableVideoComposition&lt;/code&gt; you can now combine the two into an &lt;code&gt;AVPlayer&lt;/code&gt; to display in an &lt;code&gt;AVPlayerViewController&lt;/code&gt; or in your own &lt;code&gt;UIViewController&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; waterFallItem &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVPlayerItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;asset&lt;/span&gt;&lt;span&gt;: waterfallAsset)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;waterFallItem.videoComposition &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; titleComposition&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; player &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; AVPlayer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;playerItem&lt;/span&gt;&lt;span&gt;: waterFallItem)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;finished-image&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 300px) 300px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;300&quot; height=&quot;536&quot; src=&quot;https://img.ly/_astro/finished-image_Z2bm57U.webp&quot; srcset=&quot;/_astro/finished-image_Z2bm57U.webp 300w&quot;&gt;&lt;/p&gt;
&lt;p&gt;As stated above, you can also combine the asset and the composition and write them to a new movie file using an &lt;code&gt;AVAssetExportSession&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;going-further&quot;&gt;Going Further&lt;/h2&gt;
&lt;p&gt;The method in this tutorial is suitable for adding watermark or title text to videos. If you want to give users the ability to add custom text, there is more work to do. You will need to create font and color pickers as well as code to position the text in the frame.&lt;/p&gt;
&lt;p&gt;You can use an editor such as &lt;a href=&quot;https://img.ly/products/video-sdk?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;VideoEditorSDK&lt;/a&gt; to allow your users to add annotations, text and filters to their clips. They can even add audio or combine clips to make a great creation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;finished&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 852px) 852px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;852&quot; height=&quot;900&quot; src=&quot;https://img.ly/_astro/finished_xNz1m.webp&quot; srcset=&quot;/_astro/finished_tD2vg.webp 640w, /_astro/finished_ZcPb1r.webp 750w, /_astro/finished_959NM.webp 828w, /_astro/finished_xNz1m.webp 852w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;In this article, you saw how to use &lt;code&gt;AVMutableVideoComposition&lt;/code&gt; to add text to a video clip. Further, you saw how using an SDK such as &lt;a href=&quot;https://img.ly/products/video-sdk?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;VideoEditorSDK&lt;/a&gt; allows you to annotate and enhance your clips before sharing. Including typography, audio support and video composition, IMG.LY provides a comprehensive solution for mobile video editing – find the documentation &lt;a href=&quot;https://img.ly/docs/vesdk/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Looking for more video capabilities? Check out our solutions for &lt;a href=&quot;https://img.ly/use-cases/story-reels-short-video-creation&quot;&gt;Short Video Creation&lt;/a&gt;, and &lt;a href=&quot;https://img.ly/products/camera-sdk&quot;&gt;Camera SDK&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading! We hope that you found this tutorial helpful. Feel free to reach out to us on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt; with any questions, comments, or suggestions!&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Walter</dc:creator><media:content url="https://blog.img.ly/2021/10/add-text-to-video-swift.jpg" medium="image"/><category>Video Editing</category><category>Video Editor</category><category>Swift</category><category>App Development</category><category>Developer Tools</category><category>How-To</category><category>Tutorial</category></item></channel></rss>