<?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>Eray – IMG.LY Blog</title><description>High on code. Co-founder of @9elements and @imgly</description><link>https://img.ly/blog/author/eray/</link><language>en-us</language><image><url>https://img.ly/apple-touch-icon.png</url><title>Eray – IMG.LY Blog</title><link>https://img.ly/blog/author/eray/</link></image><atom:link href="https://img.ly/blog/author/eray/rss.xml" rel="self" type="application/rss+xml"/><generator>Astro</generator><lastBuildDate>Fri, 12 Jun 2026 10:10:21 GMT</lastBuildDate><ttl>60</ttl><item><title>Build in a Day: AI Video Clipping with CE.SDK</title><link>https://img.ly/blog/build-in-a-day-ai-video-clipping-with-ce-sdk/</link><guid isPermaLink="true">https://img.ly/blog/build-in-a-day-ai-video-clipping-with-ce-sdk/</guid><description>Build a client-side AI video editor that turns long videos into short highlights using CE.SDK and AI.</description><pubDate>Thu, 05 Feb 2026 12:17:28 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;We built a video shortener in a single day using Claude Code and CE.SDK. It extracts 3-4 short clips from long-form video, handles transcription, identifies the best moments via AI, detects speakers, and outputs vertical/horizontal/square formats—all running in the browser.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extracts 3-4 clips per video (highlights, summaries, or cleaned-up edits)&lt;/li&gt;
&lt;li&gt;Outputs 9:16 (vertical), 16:9 (landscape), or 1:1 (square)&lt;/li&gt;
&lt;li&gt;Detects speakers and maps them to faces with user confirmation&lt;/li&gt;
&lt;li&gt;Auto-crops to follow the active speaker&lt;/li&gt;
&lt;li&gt;Adds captions and text hooks&lt;/li&gt;
&lt;li&gt;Non-destructive: change aspect ratio or template without re-processing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Best suited for:&lt;/strong&gt; Videos with speech/dialogue (podcasts, interviews, presentations, vlogs)&lt;/p&gt;
&lt;h2 id=&quot;why-client-side&quot;&gt;Why Client-Side?&lt;/h2&gt;
&lt;p&gt;CE.SDK’s CreativeEngine runs in the browser via WebAssembly. Video decoding, timeline manipulation, effects, and preview all happen on the user’s device.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No upload/download wait — edits preview instantly&lt;/li&gt;
&lt;li&gt;Non-destructive — switch aspect ratio or template without rendering&lt;/li&gt;
&lt;li&gt;Lower infrastructure costs — your costs don’t scale with video length or user count&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tech-stack&quot;&gt;Tech Stack&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; Next.js + React&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Video Engine:&lt;/strong&gt; CE.SDK (CreativeEngine)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transcription:&lt;/strong&gt; ElevenLabs Scribe v2&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI Analysis:&lt;/strong&gt; Google Gemini&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;architecture-overview&quot;&gt;Architecture Overview&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;High-Level Flow&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;AI Video Shortener&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 818px) 818px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;818&quot; height=&quot;841&quot; src=&quot;https://img.ly/_astro/ai-video-processing-build-a-video-shortener_20dJmS.webp&quot; srcset=&quot;/_astro/ai-video-processing-build-a-video-shortener_1wQnGV.webp 640w, /_astro/ai-video-processing-build-a-video-shortener_Z2vwzkB.webp 750w, /_astro/ai-video-processing-build-a-video-shortener_20dJmS.webp 818w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Required API Keys&lt;/strong&gt;&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Service&lt;/th&gt;&lt;th&gt;Purpose&lt;/th&gt;&lt;th&gt;Environment Variable&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;CE.SDK&lt;/td&gt;&lt;td&gt;Video editing engine&lt;/td&gt;&lt;td&gt;&lt;code&gt;NEXT_PUBLIC_CESDK_LICENSE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ElevenLabs&lt;/td&gt;&lt;td&gt;Speech-to-text transcription&lt;/td&gt;&lt;td&gt;&lt;code&gt;ELEVENLABS_API_KEY&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Gemini (via OpenRouter or direct)&lt;/td&gt;&lt;td&gt;AI highlight detection&lt;/td&gt;&lt;td&gt;&lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt; or &lt;code&gt;GEMINI_API_KEY&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;setting-up-cesdk&quot;&gt;Setting Up CE.SDK&lt;/h2&gt;
&lt;h3 id=&quot;what-is-cesdk&quot;&gt;What is CE.SDK?&lt;/h3&gt;
&lt;p&gt;CE.SDK (CreativeEngine SDK) is a browser-based engine for video, image, and design editing—a programmable video editor you can embed in your app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Engine:&lt;/strong&gt; The runtime that manages the editing session&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scene:&lt;/strong&gt; The document/project containing all elements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blocks:&lt;/strong&gt; Individual elements (video clips, text, shapes, audio)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeline:&lt;/strong&gt; Time-based arrangement of blocks for video editing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&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;h3 id=&quot;initializing-the-creativeengine&quot;&gt;Initializing the CreativeEngine&lt;/h3&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; CreativeEngine &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;const&lt;/span&gt;&lt;span&gt; engine&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; CreativeEngine.&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  license: process.env.&lt;/span&gt;&lt;span&gt;NEXT_PUBLIC_CESDK_LICENSE&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&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; scene&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.scene.&lt;/span&gt;&lt;span&gt;createVideo&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;// Get the page (timeline container)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; pages&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.scene.&lt;/span&gt;&lt;span&gt;getPages&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; page&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; pages[&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Configure page dimensions for your target aspect ratio&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setWidth&lt;/span&gt;&lt;span&gt;(page, &lt;/span&gt;&lt;span&gt;1080&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// 9:16 vertical&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setHeight&lt;/span&gt;&lt;span&gt;(page, &lt;/span&gt;&lt;span&gt;1920&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;uploading-video-to-cesdk&quot;&gt;Uploading Video to CE.SDK&lt;/h3&gt;
&lt;p&gt;CE.SDK works with video through a fill-based system. The graphic block is the container, while the video fill holds the actual media source and playback properties.&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;// Create a video block&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; videoBlock&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;graphic&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; videoFill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;createFill&lt;/span&gt;&lt;span&gt;(&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Set the video source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setString&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoFill,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &apos;fill/video/fileURI&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoUrl &lt;/span&gt;&lt;span&gt;// Can be a blob URL or remote 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 class=&quot;line&quot;&gt;&lt;span&gt;// Apply fill to block&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setFill&lt;/span&gt;&lt;span&gt;(videoBlock, videoFill);&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;// Add to timeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;appendChild&lt;/span&gt;&lt;span&gt;(page, videoBlock);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;extracting-audio-for-transcription&quot;&gt;Extracting Audio for Transcription&lt;/h3&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;// Configure audio-only export&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; mimeType&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;audio/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 class=&quot;line&quot;&gt;&lt;span&gt;// Export just the audio track&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; audioBlob&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;export&lt;/span&gt;&lt;span&gt;(page, mimeType, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  targetWidth: &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;  targetHeight: &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;});&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;// audioBlob can now be sent to transcription API&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setting both dimensions to 0 tells CE.SDK to skip video encoding entirely, making this export much faster than exporting the full video.&lt;/p&gt;
&lt;h3 id=&quot;getting-video-metadata&quot;&gt;Getting Video Metadata&lt;/h3&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;// Get video duration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; duration&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getDuration&lt;/span&gt;&lt;span&gt;(videoBlock);&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;// Get dimensions from the fill&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; videoFill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getFill&lt;/span&gt;&lt;span&gt;(videoBlock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; sourceWidth&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getSourceWidth&lt;/span&gt;&lt;span&gt;(videoFill);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; sourceHeight&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getSourceHeight&lt;/span&gt;&lt;span&gt;(videoFill);&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;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`Video: ${&lt;/span&gt;&lt;span&gt;sourceWidth&lt;/span&gt;&lt;span&gt;}x${&lt;/span&gt;&lt;span&gt;sourceHeight&lt;/span&gt;&lt;span&gt;}, ${&lt;/span&gt;&lt;span&gt;duration&lt;/span&gt;&lt;span&gt;}s`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;ai-powered-transcription--highlight-detection&quot;&gt;AI-Powered Transcription &amp;#x26; Highlight Detection&lt;/h2&gt;
&lt;h3 id=&quot;the-pipeline&quot;&gt;The Pipeline&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Audio → Transcription:&lt;/strong&gt; Send extracted audio to ElevenLabs Scribe&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transcription → Analysis:&lt;/strong&gt; Feed word-level transcript to Gemini&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analysis → Timestamps:&lt;/strong&gt; Map AI suggestions back to precise video times&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;transcription-with-speaker-diarization&quot;&gt;Transcription with Speaker Diarization&lt;/h3&gt;
&lt;p&gt;ElevenLabs Scribe v2 provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Word-level timestamps (start/end time for each word)&lt;/li&gt;
&lt;li&gt;Speaker diarization (which speaker said what)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The output is a structured transcript where each word has a precise timestamp, enabling frame-accurate editing.&lt;/p&gt;
&lt;h3 id=&quot;ai-highlight-detection-with-gemini&quot;&gt;AI Highlight Detection with Gemini&lt;/h3&gt;
&lt;p&gt;The prompt structure matters. Here’s what works:&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;You are analyzing a video transcript to identify segments for short-form content.&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;TRANSCRIPT:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[Word-by-word transcript with timestamps]&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;TASK:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Identify 3-4 segments that work as standalone short videos. For each segment:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1. Find the exact starting and ending words&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2. Ensure clean sentence boundaries (no mid-sentence cuts)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;3. Aim for 30-60 second segments&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;OUTPUT FORMAT (JSON):&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;  &quot;concepts&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;      &quot;id&quot;: &quot;concept_1&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &quot;title&quot;: &quot;Hook title&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &quot;description&quot;: &quot;Why this segment works as a standalone clip&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &quot;trimmed_text&quot;: &quot;The exact transcript text to keep...&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &quot;estimated_duration_seconds&quot;: 45&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;span class=&quot;line&quot;&gt;&lt;span&gt;CRITERIA FOR SELECTION:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- Strong hooks (surprising statements, questions, bold claims)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- Complete thoughts (don&apos;t cut mid-explanation)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- Emotional peaks (humor, insight, controversy)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- Standalone value (makes sense without context)&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;Before finalizing each segment, ask: &quot;If someone started watching here,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;would they understand what&apos;s being discussed?&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;mapping-back-to-timestamps&quot;&gt;Mapping Back to Timestamps&lt;/h3&gt;
&lt;p&gt;Once Gemini returns the &lt;code&gt;trimmed_text&lt;/code&gt;, we match it against our word-level transcript to find exact timestamps:&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;AI returns:     &quot;The secret to success is actually quite simple...&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Transcript has: [{ word: &quot;The&quot;, start: 45.2 }, { word: &quot;secret&quot;, start: 45.4 }, ...]&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;Result:         Trim video from 45.2s to 52.8s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This text-matching approach is more reliable than asking the AI to output timestamps directly. LLMs can hallucinate timestamps or miscalculate offsets, but they’re excellent at identifying the right words—so we let the transcript data provide the ground truth for timing.&lt;/p&gt;
&lt;h2 id=&quot;working-with-the-cesdk-timeline&quot;&gt;Working with the CE.SDK Timeline&lt;/h2&gt;
&lt;h3 id=&quot;understanding-blocks&quot;&gt;Understanding Blocks&lt;/h3&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;// Video/Image content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; graphic&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;graphic&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;// Audio track&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; audio&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;audio&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;// Text overlay&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; text&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;text&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;// Each block can be positioned on the timeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setTimeOffset&lt;/span&gt;&lt;span&gt;(block, startTimeInSeconds);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setDuration&lt;/span&gt;&lt;span&gt;(block, durationInSeconds);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;manipulating-trim-points&quot;&gt;Manipulating Trim Points&lt;/h3&gt;
&lt;p&gt;Trimming controls which portion of the source media is shown:&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;const&lt;/span&gt;&lt;span&gt; videoFill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getFill&lt;/span&gt;&lt;span&gt;(videoBlock);&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;// Set where in the source video to start (in seconds)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setTrimOffset&lt;/span&gt;&lt;span&gt;(videoFill, &lt;/span&gt;&lt;span&gt;45.2&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;// Set how long to play from that point&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setTrimLength&lt;/span&gt;&lt;span&gt;(videoFill, &lt;/span&gt;&lt;span&gt;30.0&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;// Also update the block&apos;s duration to match&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setDuration&lt;/span&gt;&lt;span&gt;(videoBlock, &lt;/span&gt;&lt;span&gt;30.0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;working-with-fills-and-their-timing&quot;&gt;Working with Fills and Their Timing&lt;/h3&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;// Get the fill (contains the actual media)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getFill&lt;/span&gt;&lt;span&gt;(block);&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;// Fills have their own timing properties&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; trimStart&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getTrimOffset&lt;/span&gt;&lt;span&gt;(fill);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; trimDuration&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getTrimLength&lt;/span&gt;&lt;span&gt;(fill);&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;// The block&apos;s duration should typically match the fill&apos;s trim length&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setDuration&lt;/span&gt;&lt;span&gt;(block, trimDuration);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Think of the fill as the media source (which part of the original video to use) and the block as the timeline placement (when and how long it appears). Both need to be updated together for clean edits.&lt;/p&gt;
&lt;h3 id=&quot;creating-time-based-edits-from-transcript-words&quot;&gt;Creating Time-Based Edits from Transcript Words&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; TranscriptWord&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  word&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  start&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  end&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  speaker_id&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;
&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;function&lt;/span&gt;&lt;span&gt; applyTranscriptTrim&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  engine&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; CreativeEngine&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoBlock&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  words&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; TranscriptWord&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;  if&lt;/span&gt;&lt;span&gt; (words.&lt;/span&gt;&lt;span&gt;length&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;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 class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; startTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; words[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].start;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; endTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; words[words.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt; -&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;].end;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; duration&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; endTime &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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getFill&lt;/span&gt;&lt;span&gt;(videoBlock);&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;  engine.block.&lt;/span&gt;&lt;span&gt;setTrimOffset&lt;/span&gt;&lt;span&gt;(fill, startTime);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  engine.block.&lt;/span&gt;&lt;span&gt;setTrimLength&lt;/span&gt;&lt;span&gt;(fill, duration);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  engine.block.&lt;/span&gt;&lt;span&gt;setDuration&lt;/span&gt;&lt;span&gt;(videoBlock, duration);&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;generating-speaker-thumbnails&quot;&gt;Generating Speaker Thumbnails&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; generateSpeakerThumbnail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  engine&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; CreativeEngine&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoBlock&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  timestampSeconds&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  size&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 128&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; Promise&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getFill&lt;/span&gt;&lt;span&gt;(videoBlock);&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;  // Seek to the specific timestamp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  engine.block.&lt;/span&gt;&lt;span&gt;setTrimOffset&lt;/span&gt;&lt;span&gt;(fill, timestampSeconds);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  engine.block.&lt;/span&gt;&lt;span&gt;setTrimLength&lt;/span&gt;&lt;span&gt;(fill, &lt;/span&gt;&lt;span&gt;0.1&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// Just a single frame&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 as image&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;export&lt;/span&gt;&lt;span&gt;(videoBlock, &lt;/span&gt;&lt;span&gt;&apos;image/jpeg&apos;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    targetWidth: size,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    targetHeight: size,&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; 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;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We sample multiple timestamps throughout each speaker’s talk time to show different facial angles and expressions—this helps users identify the right person even if they’re looking away or mid-gesture in one frame.&lt;/p&gt;
&lt;h2 id=&quot;speaker-detection--face-tracking&quot;&gt;Speaker Detection &amp;#x26; Face Tracking&lt;/h2&gt;
&lt;h3 id=&quot;why-semi-automatic&quot;&gt;Why Semi-Automatic?&lt;/h3&gt;
&lt;p&gt;Fully automatic speaker detection fails often enough that we added a confirmation step. Users verify detected faces against speaker names from the transcript—takes a few seconds and prevents bad crops on the entire video.&lt;/p&gt;
&lt;h3 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Sample frames throughout the video&lt;/li&gt;
&lt;li&gt;Detect &amp;#x26; cluster faces using face-api.js (runs in browser, no server needed)&lt;/li&gt;
&lt;li&gt;User confirms speaker identities via thumbnails&lt;/li&gt;
&lt;li&gt;Correlate with transcript diarization to map speakers → face locations&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This gives us verified speaker-to-face mapping for dynamic cropping and picture-in-picture layouts.&lt;/p&gt;
&lt;h2 id=&quot;multi-speaker-templates--dynamic-switching&quot;&gt;Multi-Speaker Templates &amp;#x26; Dynamic Switching&lt;/h2&gt;
&lt;h3 id=&quot;the-concept&quot;&gt;The Concept&lt;/h3&gt;
&lt;p&gt;When a video has multiple speakers, we can create layouts that show:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The active speaker prominently&lt;/li&gt;
&lt;li&gt;Other speakers in smaller picture-in-picture views&lt;/li&gt;
&lt;li&gt;Dynamic switching as the conversation flows&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;creating-picture-in-picture-with-cesdk&quot;&gt;Creating Picture-in-Picture with CE.SDK&lt;/h3&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;// Duplicate the video block for each speaker slot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; pipBlock&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;duplicate&lt;/span&gt;&lt;span&gt;(originalVideoBlock);&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;// Position and size the PiP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setWidth&lt;/span&gt;&lt;span&gt;(pipBlock, &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;engine.block.&lt;/span&gt;&lt;span&gt;setHeight&lt;/span&gt;&lt;span&gt;(pipBlock, &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;engine.block.&lt;/span&gt;&lt;span&gt;setPositionX&lt;/span&gt;&lt;span&gt;(pipBlock, &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// 20px from left&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setPositionY&lt;/span&gt;&lt;span&gt;(pipBlock, &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// 20px from top&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;// Enable cropping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setClipped&lt;/span&gt;&lt;span&gt;(pipBlock, &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;engine.block.&lt;/span&gt;&lt;span&gt;setContentFillMode&lt;/span&gt;&lt;span&gt;(pipBlock, &lt;/span&gt;&lt;span&gt;&apos;Cover&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;key-technique-muting-duplicate-audio&quot;&gt;Key Technique: Muting Duplicate Audio&lt;/h3&gt;
&lt;p&gt;When duplicating video blocks for multi-speaker layouts, each copy has its own audio track. We must mute all but one. The &lt;code&gt;setMuted&lt;/code&gt; API operates on the video fill, not the block itself:&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;// For each speaker slot after the first, mute the video fill&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (slotIndex &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;  const&lt;/span&gt;&lt;span&gt; videoFill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;getFill&lt;/span&gt;&lt;span&gt;(duplicatedBlock);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; (videoFill) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    engine.block.&lt;/span&gt;&lt;span&gt;setMuted&lt;/span&gt;&lt;span&gt;(videoFill, &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;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;dynamic-speaker-switching&quot;&gt;Dynamic Speaker Switching&lt;/h3&gt;
&lt;p&gt;As the active speaker changes throughout the video, we:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Detect which speaker is talking (from transcript diarization)&lt;/li&gt;
&lt;li&gt;Swap speaker positions in the template&lt;/li&gt;
&lt;li&gt;Keep the active speaker in the prominent position&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The layout updates automatically as the conversation switches between speakers. We apply different trim offsets to each duplicated block based on the transcript timing—so the main speaker slot shows the person currently talking while PiP slots show the listeners.&lt;/p&gt;
&lt;h2 id=&quot;preview-playback--export&quot;&gt;Preview, Playback &amp;#x26; Export&lt;/h2&gt;
&lt;h3 id=&quot;setting-up-the-canvas&quot;&gt;Setting Up the Canvas&lt;/h3&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;const&lt;/span&gt;&lt;span&gt; container&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; document.&lt;/span&gt;&lt;span&gt;getElementById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;cesdk-canvas&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.element.&lt;/span&gt;&lt;span&gt;attachTo&lt;/span&gt;&lt;span&gt;(container);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;playback-controls&quot;&gt;Playback Controls&lt;/h3&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;engine.player.&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;engine.player.&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;engine.player.&lt;/span&gt;&lt;span&gt;setPlaybackTime&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;30.5&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// seek to 30.5 seconds&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; currentTime&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.player.&lt;/span&gt;&lt;span&gt;getPlaybackTime&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; isPlaying&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.player.&lt;/span&gt;&lt;span&gt;isPlaying&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;syncing-ui-state&quot;&gt;Syncing UI State&lt;/h3&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;engine.player.&lt;/span&gt;&lt;span&gt;onPlaybackTimeChanged&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; time&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.player.&lt;/span&gt;&lt;span&gt;getPlaybackTime&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  updateTimeDisplay&lt;/span&gt;&lt;span&gt;(time);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  updateProgressBar&lt;/span&gt;&lt;span&gt;(time &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; totalDuration);&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;engine.player.&lt;/span&gt;&lt;span&gt;onPlaybackStateChanged&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;  updatePlayButton&lt;/span&gt;&lt;span&gt;(engine.player.&lt;/span&gt;&lt;span&gt;isPlaying&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;export-options&quot;&gt;Export Options&lt;/h3&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;const&lt;/span&gt;&lt;span&gt; exportOptions&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;  targetWidth: &lt;/span&gt;&lt;span&gt;1080&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  targetHeight: &lt;/span&gt;&lt;span&gt;1920&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  framerate: &lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  videoBitrate: &lt;/span&gt;&lt;span&gt;8_000_000&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;// 8 Mbps&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; 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;export&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  page,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&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;  exportOptions,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  (&lt;/span&gt;&lt;span&gt;progress&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; updateProgressBar&lt;/span&gt;&lt;span&gt;(progress &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&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Trigger download&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;shortened-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;/code&gt;&lt;/pre&gt;
&lt;p&gt;For longer videos, consider showing estimated time remaining or allowing background export. Browser export is single-threaded and blocks the tab—a 5-minute export of a 60-second clip isn’t unusual on average hardware, so user feedback is critical.&lt;/p&gt;
&lt;h2 id=&quot;the-finished-app&quot;&gt;The Finished App&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The user flow:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Upload&lt;/strong&gt; → Drop a long-form video into the browser&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure&lt;/strong&gt; → Pick output mode (highlights/summary/cleanup) and aspect ratio (9:16, 16:9, 1:1)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify speakers&lt;/strong&gt; → Match detected faces to transcript speaker names&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review clips&lt;/strong&gt; → Browse the 3-4 AI-suggested segments, adjust if needed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose template&lt;/strong&gt; → Solo speaker, sidecar, stacked, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preview&lt;/strong&gt; → Scrub through the timeline, see exactly what you’ll get&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Export&lt;/strong&gt; → Download the final video directly from the browser&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h2&gt;
&lt;h3 id=&quot;ideas-for-extension&quot;&gt;Ideas for Extension&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Caption style controls:&lt;/strong&gt; Custom fonts, animations, and positioning for subtitles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;B-roll insertion:&lt;/strong&gt; Automatically add relevant stock footage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music &amp;#x26; sound effects:&lt;/strong&gt; AI-selected background audio&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brand templates:&lt;/strong&gt; Custom overlays, intros, outros&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Batch processing:&lt;/strong&gt; Process multiple videos in sequence&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;taking-it-server-side&quot;&gt;Taking It Server-Side&lt;/h3&gt;
&lt;p&gt;Client-side processing for large files strains browser memory, and users must keep the tab open during export. A hybrid approach works better for production—upload in the background while users edit, then render on a server. You can also offload just the export step—let users build their edits in the browser, then send the CE.SDK scene JSON to your backend for faster, background rendering.&lt;/p&gt;
&lt;p&gt;CE.SDK runs server-side with the same API. For batch processing, background jobs, or offloading rendering from user devices, see the &lt;a href=&quot;https://img.ly/docs/cesdk/renderer/cesdk-renderer-overview-7f3e9a/&quot;&gt;CE.SDK Renderer&lt;/a&gt; for creative automation.&lt;/p&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/&quot;&gt;CE.SDK Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/node/create-video-c41a08/&quot;&gt;CE.SDK Video Editing Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/imgly/videoclipper&quot;&gt;GitHub: Video Shortener Source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://elevenlabs.io/docs/api-reference&quot;&gt;ElevenLabs API Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ai.google.dev/gemini-api/docs&quot;&gt;Gemini API Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Made by &lt;a href=&quot;https://img.ly/&quot;&gt;IMG.LY&lt;/a&gt; with &lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CE.SDK&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Eray</dc:creator><media:content url="https://blog.img.ly/2026/01/Gemini_Generated_Image_qj8gi7qj8gi7qj8g.png" medium="image"/><category>AI</category><category>Insights</category><category>Video Editing</category></item><item><title>One SDK to Power Them All: Announcing IMG.LY SDK</title><link>https://img.ly/blog/one-sdk-to-power-them-all-announcing-img-ly-sdk/</link><guid isPermaLink="true">https://img.ly/blog/one-sdk-to-power-them-all-announcing-img-ly-sdk/</guid><description>We’re consolidating our Photo and Video Editor SDKs under the Creative Editor SDK (CE.SDK) umbrella to simplify development and accelerate innovation. PE.SDK and VE.SDK will enter long-term support this year, with CE.SDK (soon branded IMG.LY SDK) becoming our single, future-ready solution.</description><pubDate>Tue, 19 Aug 2025 10:25:44 GMT</pubDate><content:encoded>&lt;p&gt;From day one, IMG.LY has been driven by a singular mission: &lt;strong&gt;to empower creativity at scale&lt;/strong&gt;. By embedding our technology directly into apps, websites, and workflows, we have helped hundreds of customers from social networks to e-commerce platforms to deliver rich, media-powered experiences to millions of users. We started out by offering two specialized SDKs, the Photo Editor SDK and the Video Editor SDK, later on, we introduced the Creative Editor SDK (CE.SDK) as a more flexible, all-in-one creative editing solution.&lt;/p&gt;
&lt;p&gt;As CE.SDK has matured into a foundation for all creative workflows including photo and video editing, we’re taking the next step in our evolution. Later this year, we’ll unify our offerings under a single brand:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IMG.LY SDK&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For existing customers of PE.SDK and VE.SDK, rest assured, both products will continue to receive long-term support. We’ll explain what that means below.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;from-fragmentation-to-unification&quot;&gt;From Fragmentation to Unification&lt;/h2&gt;
&lt;p&gt;Over the years, our Photo Editor SDK (PE.SDK) and Video Editor SDK (VE.SDK) have enabled customers to deliver creative editing for a specific domain (photo and video). While both excelled within their specific use cases, maintaining separate SDKs brought growing complexity from divergent feature sets across platforms to duplicated codebases and asynchronous upgrade paths. Not only did our customers’ use cases expand, driving demand for more custom editing solutions, this fragmentation ultimately limited our ability to move fast, innovate, and serve this growing demand.&lt;/p&gt;
&lt;p&gt;That’s why we introduced Creative Editor SDK (CE.SDK): a unified foundation designed from the ground up to scale across creative domains and workflows. At its core is a single, shared engine capable of handling image, video, layout, text, and audio processing paired with native UI components for every major platform. With each release, CE.SDK has steadily absorbed functionality from both PE.SDK and VE.SDK, making it our most capable and extensible offering yet.&lt;/p&gt;
&lt;p&gt;But as this convergence progressed, it also introduced a new kind of complexity: customers were often unsure which SDK to choose. By bringing everything into one consistent, cross-platform solution where every feature is developed in sync for web and mobile, CE.SDK eliminates that uncertainty and simplifies the path forward.&lt;/p&gt;
&lt;h2 id=&quot;one-sdk-to-power-them-all&quot;&gt;One SDK to Power Them All&lt;/h2&gt;
&lt;p&gt;Beyond the engine, the SDK now includes prebuilt &lt;strong&gt;solutions&lt;/strong&gt; tailored to common use cases, for example &lt;a href=&quot;https://img.ly/docs/cesdk/js/prebuilt-solutions/photo-editor-42ccb2/&quot;&gt;&lt;strong&gt;photo&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a href=&quot;https://img.ly/docs/cesdk/js/prebuilt-solutions/video-editor-9e533a/&quot;&gt;&lt;strong&gt;video&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; or &lt;a href=&quot;https://img.ly/docs/cesdk/js/prebuilt-solutions/ai-editor-5409b9/&quot;&gt;&lt;strong&gt;AI-powered design tooling&lt;/strong&gt;&lt;/a&gt;. These solutions help teams get started faster without compromising on customization or scalability.&lt;/p&gt;
&lt;p&gt;As we move forward, the IMG.LY SDK will be the sole focus of our platform investments. That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Regular updates&lt;/strong&gt; and new features delivered consistently across all supported platforms.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Turnkey solutions&lt;/strong&gt; will provide an even simpler integration path, requiring only a few lines of code for set up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugin support&lt;/strong&gt; and a modular architecture for maximum extensibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation and Headless Mode&lt;/strong&gt; for powerful backend or non-UI-driven workflows.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;unified API surface&lt;/strong&gt;: one learning curve, one integration, fewer surprises.&lt;/li&gt;
&lt;li&gt;And for new prospects and existing partners alike, a clear and confident message: &lt;strong&gt;IMG.LY SDK is the future.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;long-term-support-for-pe-and-vesdk&quot;&gt;Long-Term Support for PE. and VE.SDK&lt;/h2&gt;
&lt;p&gt;As part of this transition, PE.SDK and VE.SDK are now in &lt;strong&gt;long-term support mode&lt;/strong&gt; (LTS). This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They remain actively supported by a dedicated team.&lt;/li&gt;
&lt;li&gt;They are no longer sold to new customers.&lt;/li&gt;
&lt;li&gt;We encourage current users to begin exploring CE.SDK — soon branded as IMG.LY SDK — as the future-ready path forward.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re currently using PE.SDK or VE.SDK, rest assured: we’ve got you covered. But for faster innovation and access to our latest AI-powered features, we strongly recommend evaluating IMG.LY SDK.&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next?&lt;/h2&gt;
&lt;p&gt;Of course, the journey doesn’t stop here. The unification of our SDKs paves the road for many more exciting capabilities, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Improve Developer Experience&lt;/strong&gt;&lt;br&gt;
Simpler setup, smarter defaults, and faster time-to-interaction, so teams can go from idea to integration in record time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build for Agentic AI&lt;/strong&gt;&lt;br&gt;
Designed for agent-driven workflows: responsive canvases, multimodal orchestration, and APIs tailored for autonomous actions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better Serve Designers &amp;#x26; Teams&lt;/strong&gt;&lt;br&gt;
Our upcoming Studio offering will include project dashboards, version control, and multi-user permissions for collaborative work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personalization at Scale&lt;/strong&gt;&lt;br&gt;
While we already support for variables and templating, we are exploring how to leverage AI to effortlessly create smart variation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customizable UI &amp;#x26; Fast Workflow Building&lt;/strong&gt;&lt;br&gt;
We’re making it easier than ever to adapt the editor to your needs whether you’re modifying the UI, embedding your own logic, or orchestrating custom creative workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now is the perfect time to connect with our team, share your roadmap, test-drive upcoming modules, and plan your migration. Your feedback will help shape the future of IMG.LY SDK.&lt;/p&gt;</content:encoded><dc:creator>Eray</dc:creator><dc:creator>Daniel</dc:creator><media:content url="https://blog.img.ly/2025/08/imglysdkcover.png" medium="image"/><category>Company</category></item><item><title>IMG.LY x AI</title><link>https://img.ly/blog/img-ly-x-ai-future-of-ai-powered-creative-workflows/</link><guid isPermaLink="true">https://img.ly/blog/img-ly-x-ai-future-of-ai-powered-creative-workflows/</guid><description>Shaping the Future of Creative Workflows</description><pubDate>Mon, 30 Jun 2025 13:18:14 GMT</pubDate><content:encoded>&lt;p&gt;Over the past two years, one question has consistently emerged in conversations with customers: “What about AI?”&lt;br&gt;
While AI promises to disrupt many industries, it remains difficult to grasp how this technology will reshape creative workflows.&lt;/p&gt;
&lt;p&gt;Our customers look to us for guidance: What is IMG.LY’s vision? How will our SDK help them harness this wave of innovation?&lt;br&gt;
Last month, we took our first significant step by launching an &lt;a href=&quot;https://img.ly/use-cases/ai-editor&quot;&gt;initial suite of generative AI-powered features for our web SDK&lt;/a&gt;. We’ve embedded these tools deeply into photo, video, and design editing workflows and the response from customers and prospects was overwhelmingly positive.&lt;/p&gt;
&lt;p&gt;And this is just the beginning. An immense opportunity lies ahead for both IMG.LY and our customers to drive transformation in the creative domain through our SDK. In this post, I want to share our vision for the future of creative tools powered by AI and our SDK.&lt;/p&gt;
&lt;p&gt;Going forward, we’re focusing on three central goals:&lt;/p&gt;
&lt;h3 id=&quot;1-deep-integration-of-ai-capabilities-into-editing-workflows&quot;&gt;1. Deep Integration of AI Capabilities into Editing Workflows&lt;/h3&gt;
&lt;p&gt;The pace of AI innovation continues to be remarkably fast. New models and configurations emerge almost daily, some as APIs, others open-sourced on platforms like Hugging Face. While some offer generalist features, others provide specialized, industry-specific capabilities, such as automatically obscuring license plates, blurring faces or replacing skies for property exteriors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The true value of these AI tools emerges not in isolation, but when they’re seamlessly combined within existing workflows&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That’s why we built a &lt;strong&gt;plugin system&lt;/strong&gt; for CE.SDK.&lt;br&gt;
The CE.SDK plugin system has fundamentally changed how quickly we, and our customers, can integrate new capabilities. We’ve created a way to bring AI models and agents directly into connected workflows within the editor, making AI feel native rather than bolted on.&lt;/p&gt;
&lt;p&gt;A recent example is &lt;a href=&quot;https://img.ly/blog/ai-first-visual-editor-for-gpt-4o-image-gen/&quot;&gt;our integration of OpenAI’s gpt-image-1 API&lt;/a&gt;, which we implemented in just a few days after its release. We used it to build a visual prompting workflow that takes into account all elements of a page, text, images, and annotations, to generate results based on the complete layout context.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/imgly-ai/visualprompt_05.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;These early successes are encouraging us to ship even faster and bring new features to our customers.&lt;/p&gt;
&lt;p&gt;We’re now partnering with &lt;a href=&quot;https://fal.ai/&quot;&gt;fal.ai&lt;/a&gt; to provide a nearly out-of-the-box experience to use any new generative AI model through their platform (more on this soon). Fal.ai excels at speed—when exciting new models emerge, they offer API access within days. This partnership ensures our users can quickly access new AI capabilities with minimal effort. More partnerships and integrations are on the horizon, bringing world-class AI APIs with intuitive interfaces directly into the editor.&lt;/p&gt;
&lt;h3 id=&quot;2-enabling-ai-agents-as-creative-collaborators&quot;&gt;2. Enabling AI Agents as Creative Collaborators&lt;/h3&gt;
&lt;p&gt;AI agents, like humans, leverage tools to accomplish tasks efficiently. CE.SDK occupies a unique position as a highly adaptable, multi-platform technology for editing various media types—including a fully documented headless version that’s perfect for programmatic control.&lt;/p&gt;
&lt;p&gt;Thanks to CE.SDK’s fully documented API and headless architecture, AI agents can be created to navigate and operate the editor programmatically. This opens the door to agents that act as powerful scaffolders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generating initial designs and layouts based on brief descriptions&lt;/li&gt;
&lt;li&gt;Automatically aligning content with brand guidelines&lt;/li&gt;
&lt;li&gt;Transforming static designs into dynamic videos with a single command&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://img.ly/blog/how-to-build-a-short-video-generator-using-ce-sdk-2/&quot;&gt;Creating engaging short video content from prompts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Adapting existing designs to new formats and dimensions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Crucially, everything an AI agent creates remains &lt;strong&gt;fully editable&lt;/strong&gt; by human users. You can refine, add nuance, and perfect the results through collaboration. AI provides the scaffolding, humans remain the tastemakers, adding the creative spark that makes designs truly exceptional.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/imgly-ai/shortyroll.mp4&quot; controls loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-ai-powered-sdk-configuration-and-customization&quot;&gt;3. AI-Powered SDK Configuration and Customization&lt;/h3&gt;
&lt;p&gt;AI agents are already actively involved in building, refining, and optimizing software tools—a trend that’s accelerating rapidly. This shift directly impacts developer experience and points to an exciting future where our SDK serves not just human developers, but AI agents as well.&lt;/p&gt;
&lt;p&gt;To facilitate this interaction, we’ve already taken steps like making our documentation available in LLM-friendly formats. But this is just the beginning of our journey toward radically improving the experience for both developers and AI agents.&lt;/p&gt;
&lt;p&gt;Our ultimate goal is conversational configuration. Imagine describing your requirements in plain language, and having an AI agent handle the rest:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configuring the SDK’s visual aesthetics to match your brand&lt;/li&gt;
&lt;li&gt;Setting up custom functionality and workflows&lt;/li&gt;
&lt;li&gt;Integrating media libraries and plugins&lt;/li&gt;
&lt;li&gt;Optimizing performance for specific use cases&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This isn’t just about making development faster. It’s about democratizing access to powerful creative tools, allowing anyone to build sophisticated editing experiences—regardless of technical expertise.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/imgly-ai/vibe-coding-design-ads-visuals-editor.mp4&quot; controls loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h2 id=&quot;looking-forward&quot;&gt;Looking Forward&lt;/h2&gt;
&lt;p&gt;We believe that AI collaboration represents a transformative shift in creative technology, empowering users and developers to achieve extraordinary outcomes. At IMG.LY, we’re committed to being at the forefront of this exciting journey. Our vision extends beyond simply adding AI features, we’re reimagining how creative tools are built, configured, and used in an AI-augmented world.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Stay ahead with us: &lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i?ref=img.ly&quot;&gt;subscribe&lt;/a&gt; to our newsletter for exclusive updates.&lt;/p&gt;</content:encoded><dc:creator>Eray</dc:creator><media:content url="https://blog.img.ly/2025/06/creative-editor-sdk-1-53--1-.png" medium="image"/><category>AI</category><category>Company</category></item><item><title>AI-first Visual Editor using GPT-4o’s gpt-image-1 Model</title><link>https://img.ly/blog/ai-first-visual-editor-for-gpt-4o-image-gen/</link><guid isPermaLink="true">https://img.ly/blog/ai-first-visual-editor-for-gpt-4o-image-gen/</guid><description>We embedded OpenAI’s gpt-image-1 API into our CreativeEditor SDK, enabling users to generate and refine images directly in their creative workflow—no tool switching. This brings multimodal AI into real-world design tasks with seamless prompting, editing, and visual iteration.</description><pubDate>Mon, 05 May 2025 20:58:07 GMT</pubDate><content:encoded>&lt;h2 id=&quot;what-we-built&quot;&gt;What We Built&lt;/h2&gt;
&lt;p&gt;We integrated OpenAI’s new &lt;code&gt;gpt-image-1&lt;/code&gt; API (from GPT-4o) directly into our fully functional visual editor, &lt;strong&gt;CreativeEditor SDK (CE.SDK)&lt;/strong&gt;, enabling generation, editing, and refinement of images without ever leaving your creative workflow.&lt;/p&gt;
&lt;div class=&quot;cta-button-wrapper&quot;&gt;&lt;a href=&quot;https://cdn.img.ly/demo/gpt-image-1/v1/&quot; target=&quot;_blank&quot; class=&quot;cta-button&quot;&gt;Open AI Editor Demo Page&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&quot;from-simple-image-generation-to-visual-prompting-on-a-canvas&quot;&gt;From Simple Image Generation to Visual Prompting on a Canvas&lt;/h3&gt;
&lt;p&gt;Inside the editor, users can now:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generate Images&lt;/strong&gt;&lt;br&gt;
Use prompts to generate images from scratch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generate Images from Visual Prompts&lt;/strong&gt;&lt;br&gt;
Turn full compositions—images, text, and annotations—into fresh visual content. Just select your page and let AI handle the rest, as shown in the video.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/imgly-ai/visualprompt_05.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reimagine Images &amp;#x26; Text&lt;/strong&gt;&lt;br&gt;
Edit existing images and text with prompts to iterate faster and create &lt;strong&gt;variants&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/imgly-ai/variants_02.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create Incredible Compositions&lt;/strong&gt;&lt;br&gt;
Combine generated and uploaded images into complex compositions.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/imgly-ai/combine.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Each step builds on the last, evolving from basic generation into true visual prompting powered by multiple input modes, all within one canvas. Check out the live demo &lt;a href=&quot;https://cdn.img.ly/demo/gpt-image-1/v1/index.rc6.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-we-built-it&quot;&gt;How We Built It&lt;/h2&gt;
&lt;p&gt;We built this integration using our &lt;strong&gt;CE.SDK&lt;/strong&gt; and its flexible &lt;strong&gt;plugin&lt;/strong&gt; system, designed from the ground up to support AI-first creative workflows.&lt;/p&gt;
&lt;p&gt;This approach lets developers plug in any model or API—text, image, video, or audio—and run them all in one seamless editing flow. Whether you’re using OpenAI, Stability, or an in-house model, CE.SDK gives you the tools to bring it into the visual workflow natively.&lt;/p&gt;
&lt;p&gt;🔗 Check out our &lt;a href=&quot;https://img.ly/use-cases/ai-editor&quot;&gt;AI Editor&lt;/a&gt;.&lt;br&gt;
📘 Learn how to &lt;a href=&quot;https://img.ly/docs/cesdk/js/user-interface/ai-integration-5aa356/&quot;&gt;integrate AI into CE.SDK&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;/h2&gt;
&lt;p&gt;Generative AI’s full potential isn’t unlocked by prompting alone, it’s unlocked when embedded into real-world creative workflows.&lt;/p&gt;
&lt;p&gt;Designers, marketers, and content teams don’t just need outputs; they need &lt;strong&gt;control&lt;/strong&gt;, &lt;strong&gt;iteration&lt;/strong&gt;, and &lt;strong&gt;context&lt;/strong&gt;. By bringing AI directly into the canvas where assets are created and edited, we turn generative models into tools for actual production, not just ideation.&lt;/p&gt;
&lt;p&gt;This shift enables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Creative work in context&lt;/strong&gt;: No switching between ChatGPT and design tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-time augmentation&lt;/strong&gt;: Prompt, edit, refine &lt;em&gt;in place&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalable content generation&lt;/strong&gt;: Automate localization, personalization, and variants.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multimodal orchestration&lt;/strong&gt;: Use visuals, layouts, and annotations as inputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s a step toward making multimodal AI usable for &lt;strong&gt;real design workflows&lt;/strong&gt;, not just concept generation.&lt;/p&gt;
&lt;h2 id=&quot;integration--feedback&quot;&gt;Integration &amp;#x26; Feedback&lt;/h2&gt;
&lt;p&gt;This linked demo is &lt;strong&gt;rate-limited&lt;/strong&gt;, if you would like to test more extensively or if you are interested in giving the AI editor a spin inside your own app, you can get started with our &lt;a href=&quot;https://img.ly/docs/cesdk/js/user-interface/ai-integration-5aa356/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We’d love your feedback, any thoughts, questions, and ideas are welcome!&lt;br&gt;
&lt;a href=&quot;mailto:ai@img.ly&quot;&gt;Reach out&lt;/a&gt; to us.&lt;/p&gt;
&lt;hr&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>Eray</dc:creator><media:content url="https://blog.img.ly/2025/05/cesdk-2025-05-12T08_58_58.284Z.png" medium="image"/><category>AI</category><category>gpt-4o</category></item><item><title>How to Build a Short Video Generator Using CE.SDK</title><link>https://img.ly/blog/how-to-build-a-short-video-generator-using-ce-sdk-2/</link><guid isPermaLink="true">https://img.ly/blog/how-to-build-a-short-video-generator-using-ce-sdk-2/</guid><description>Build an AI-powered video generator that creates editable, high-quality videos in the browser—no server-side processing needed.</description><pubDate>Tue, 04 Mar 2025 12:57:47 GMT</pubDate><content:encoded>&lt;p&gt;In the following, I’m presenting a simple cookbook for building an AI-based video generator app, as described in &lt;a href=&quot;https://img.ly/blog/how-to-build-short-video-generator-ai-creative-sdk/&quot;&gt;my previous blog post&lt;/a&gt;. We’re using a combination of different APIs to generate text, audio, and images and will compose &amp;#x26; render the final video using the headless &lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CreativeEditor SDK&lt;/a&gt;. We also call it the Creative Engine.&lt;/p&gt;
&lt;p&gt;This cookbook showcases the powerful capabilities of our client-side Creative Engine. The engine enables real-time video generation directly in the browser, eliminating the need for server-side processing. What sets this approach apart is its ability to produce editable source files that can then be opened with CreativeEditor SDK.&lt;/p&gt;
&lt;p&gt;This approach is giving users complete control over every aspect of your video–from text and images to animations and overall composition. This means your users can refine and perfect your content even after the initial generation.&lt;/p&gt;
&lt;p&gt;Get the &lt;a href=&quot;https://github.com/imgly/ai-video-creator&quot;&gt;complete code on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;scope&quot;&gt;Scope&lt;/h2&gt;
&lt;p&gt;This tutorial focuses on building an app with a simple UX:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Input your keywords/topics&lt;/li&gt;
&lt;li&gt;Choose between landscape or portrait format&lt;/li&gt;
&lt;li&gt;Generate and preview your video&lt;/li&gt;
&lt;li&gt;Edit the video in the CE.SDK video editor&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The app flow we will create:&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/how-to/er-ai2/workflow.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;The post-editing we will get with CE.SDK:&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/how-to/er-ai2/editing-with-ce-sdk.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h2 id=&quot;technical-overview&quot;&gt;Technical Overview&lt;/h2&gt;
&lt;p&gt;The app follows three major steps to generate the video.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A script is generated based on User input, the output is a structured XML file.&lt;/li&gt;
&lt;li&gt;The XML script is parsed to extract text and image information. The extracted data will then be used to generate audio &amp;#x26; image files through third-party APIs&lt;/li&gt;
&lt;li&gt;All assets are loaded into the creative engine. This is where the composition, including animation and effects, takes place. The Creative Engine then exports a video and scene file, which can be edited with the Creative Editor.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;p&gt;We’ll use a boilerplate with Next.js, React, Typescript &amp;#x26; Tailwind. Make sure you retrieve all necessary keys:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.anthropic.com/&quot;&gt;Anthropic&lt;/a&gt; (LLM)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://elevenlabs.io/&quot;&gt;ElevenLabs&lt;/a&gt; (text to speech)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fal.ai/&quot;&gt;fal.ai&lt;/a&gt; (text to image)&lt;/li&gt;
&lt;li&gt;IMG.LY CE.SDK – Retrieve a &lt;a href=&quot;https://img.ly/forms/free-trial&quot;&gt;free trial key&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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;// Required environment variables&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;NEXT_PUBLIC_ANTHROPIC_API_KEY&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; your_claude_api_key;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;NEXT_PUBLIC_FAL_API_KEY&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; your_fal_ai_key;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;NEXT_PUBLIC_ELEVEN_LABS_KEY&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; your_eleven_labs_key;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;NEXT_PUBLIC_IMG_LY_KEY&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; your_img_ly_key;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;
&lt;h3 id=&quot;1-generate-the-script&quot;&gt;1. Generate The Script&lt;/h3&gt;
&lt;p&gt;In this step, we’ll focus on generating the initial prompt and then passing it to the Anthropic API.&lt;/p&gt;
&lt;p&gt;As with many things with LLM, there are many different strategies for structuring the initial prompt. From experience, the best result comes from providing examples of the desired output. We’ve decided to use an XML document; this can be easily parsed later on and is less error-prone compared to a JSON.&lt;/p&gt;
&lt;p&gt;We now define the structure of how information should be saved in the XML.&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;&amp;#x3C;&lt;/span&gt;&lt;span&gt;video&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;group&lt;/span&gt;&lt;span&gt; part&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;intro&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;element&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;text&lt;/span&gt;&lt;span&gt; voiceId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50YSQEDPA2vlOxhCseP4&quot;&lt;/span&gt;&lt;span&gt; style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;0.2&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        Did you know these fascinating facts about pyramids?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;text&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;image&lt;/span&gt;&lt;span&gt;&gt;Ancient Egyptian pyramid at sunset&amp;#x3C;/&lt;/span&gt;&lt;span&gt;image&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;element&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;group&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;group&lt;/span&gt;&lt;span&gt; part&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;content&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;element&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;text&lt;/span&gt;&lt;span&gt; voiceId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50YSQEDPA2vlOxhCseP4&quot;&lt;/span&gt;&lt;span&gt; style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;0.2&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        The Great Pyramid was the tallest structure for over 3,800 years!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;text&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;image&lt;/span&gt;&lt;span&gt;&gt;Great Pyramid comparison to modern buildings&amp;#x3C;/&lt;/span&gt;&lt;span&gt;image&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;element&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;group&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;group&lt;/span&gt;&lt;span&gt; part&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;outro&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;element&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;text&lt;/span&gt;&lt;span&gt; voiceId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50YSQEDPA2vlOxhCseP4&quot;&lt;/span&gt;&lt;span&gt; style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;0.4&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        The pyramids continue to reveal their secrets to this day...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;text&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;image&lt;/span&gt;&lt;span&gt;&gt;A giant 3D question mark hovering over the pyramids&amp;#x3C;/&lt;/span&gt;&lt;span&gt;image&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;element&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;element&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;text&lt;/span&gt;&lt;span&gt; voiceId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;50YSQEDPA2vlOxhCseP4&quot;&lt;/span&gt;&lt;span&gt; style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;0.4&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        Stay curious - there&apos;s always more to discover!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;text&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;image&lt;/span&gt;&lt;span&gt;&gt;Pyramids under starry night sky&amp;#x3C;/&lt;/span&gt;&lt;span&gt;image&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;element&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;group&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;video&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this tutorial, we’ll focus on the format trivia only as shown in this example. For later iterations, however, I’m planning to implement different content formats (e.g., trivia, quiz, recipe, etc.). Each of these formats will have its example XML. Therefore, I’m nesting the XML in a simple format object to scale this up easily later.&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;interface&lt;/span&gt;&lt;span&gt; Format&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  name&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  example&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;
&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; formats&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Record&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Format&lt;/span&gt;&lt;span&gt;&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;  trivia: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span&gt;&apos;Trivia&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    example: &lt;/span&gt;&lt;span&gt;`&amp;#x3C;video&gt;&amp;#x3C;group&gt;...&amp;#x3C;/group&gt;&amp;#x3C;/video&gt;`&lt;/span&gt;&lt;span&gt; // Add example from above&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;Using this format object with the example, we can now generate the prompt.&lt;/p&gt;
&lt;p&gt;What do we need for this prompt?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Description of the task&lt;/li&gt;
&lt;li&gt;Description of the desired output, incl. an example for the specified format&lt;/li&gt;
&lt;li&gt;Topic as provided by the user&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The topic provided by the user is passed to the function as a string.&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;export&lt;/span&gt;&lt;span&gt; const&lt;/span&gt;&lt;span&gt; createVideoScriptPrompt&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;  topic&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  formatName&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; &apos;trivia&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&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; format&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; formats[formatName];&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;format) &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`Format ${&lt;/span&gt;&lt;span&gt;formatName&lt;/span&gt;&lt;span&gt;} not found`&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; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Format: ${&lt;/span&gt;&lt;span&gt;format&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Topic: ${&lt;/span&gt;&lt;span&gt;topic&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;Please write a detailed script for this short video, considering the specified format and topic.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Include an introduction, main content sections, and an outro. Each section should have an image.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Structure the script as an XML Document with clear sections, descriptions for the images.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;The image description should be written as a prompt. This prompt will be used to generate an image.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Put the description between the image tags. The video shouldn&apos;t be longer than 30 seconds.&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;Example format:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;example&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;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-generate-all-assets&quot;&gt;2. Generate All Assets&lt;/h3&gt;
&lt;p&gt;In the second step, we’ll parse through the LLM response, which should be the XML. We’ll create a simple parsing function to extract all text information that should be sent to text-to-speech and text-to-image AIs.&lt;/p&gt;
&lt;p&gt;Please note that all these steps can be easily streamlined by using AI-assisted coding. Just provide the example XML as input and your desired output.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API Calls&lt;/strong&gt;&lt;br&gt;
When finding text &amp;#x26; image tags in the XML, we’ll call API functions for text-to-speech and text-to-image. For this example, I’m using ElevenLabs &amp;#x26; fal APIs. You will find all API calls in the api.ts.&lt;/p&gt;
&lt;p&gt;Since the LLM generated a script that includes image prompts, make sure to pass them to the API.&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;export&lt;/span&gt;&lt;span&gt; async&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; generateImage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;prompt&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;:&lt;/span&gt;&lt;span&gt; Promise&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Generating image for prompt:&apos;&lt;/span&gt;&lt;span&gt;, prompt);&lt;/span&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; fal.&lt;/span&gt;&lt;span&gt;subscribe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;fal-ai/flux/dev&apos;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      input: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        prompt: prompt,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        size: &lt;/span&gt;&lt;span&gt;&apos;portrait_16_9&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;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; typedResult&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;images&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; string&lt;/span&gt;&lt;span&gt; }[] };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Image generation successful. URL:&apos;&lt;/span&gt;&lt;span&gt;, typedResult.images[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].url);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; typedResult.images[&lt;/span&gt;&lt;span&gt;0&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;catch&lt;/span&gt;&lt;span&gt; (error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Error generating image:&apos;&lt;/span&gt;&lt;span&gt;, error);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Timestamps&lt;/strong&gt;&lt;br&gt;
Last but not least, we need to come up with timestamps. What’s the duration of each segment? This is critical information for composing the video. Luckily, this is quite easy: Each scene is as long as the generated audio for each segment. This duration for the audio segments can be calculated: Most TTS like ElevenLabs provide timestamps along the audio file. These are typically character-based timestamps, so we first have to calculate the timestamps for each word and then the duration for the entire text section.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ready For The Next Steps&lt;/strong&gt;&lt;br&gt;
All Asset URLs that are generated will be saved in a &lt;code&gt;VideoBlock&lt;/code&gt; object for convenience. The duration of the VideoBlock is the duration of the audio, as calculated above.&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;interface&lt;/span&gt;&lt;span&gt; VideoBlock&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  text&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;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  imageUrl&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; null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  audioUrl&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; null&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; number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  duration&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  wordTimestamps&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Array&lt;/span&gt;&lt;span&gt;&amp;#x3C;{ &lt;/span&gt;&lt;span&gt;word&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;start&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&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; number&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;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-generate-the-video&quot;&gt;3. Generate The Video&lt;/h3&gt;
&lt;p&gt;We have everything together now: The completed XML with timestamps, duration, and all assets. It’s now time to generate the video using the creative engine.&lt;/p&gt;
&lt;p&gt;Let’s first add an empty container in our HTML that will be referenced for initiating the creative engine.&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;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  /* Add container for Creative Engine */&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; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;cesdk_container&quot;&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;invisible mt-8 rounded-lg bg-gray-100&quot;&lt;/span&gt;&lt;span&gt; /&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now initialize the engine. Use &lt;a href=&quot;https://img.ly/docs/cesdk/js/get-started/overview-e18f40/&quot;&gt;this code&lt;/a&gt; snippet from our documentation.&lt;/p&gt;
&lt;p&gt;We’ll then set up a function that creates a simple composition using the provided VideoBlocks. The engine requires you to first create a scene, append a page to the scene, and then create tracks within the page. The tracks are basically the layers in the timeline. I recommend setting one track as a background track using the following snippet:&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;// Set video track as a background track by connecting the page duration to the video track&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setAlwaysOnBottom&lt;/span&gt;&lt;span&gt;(videotrack, &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;engine.block.&lt;/span&gt;&lt;span&gt;setPageDurationSource&lt;/span&gt;&lt;span&gt;(page, videotrack);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Creative Engine provides powerful API calls to style &amp;#x26; manipulate blocks in many ways. Here is an example of how we can animate the images with a slow zoom effect:&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;const&lt;/span&gt;&lt;span&gt; imageZoomAnimation&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; engine.block.&lt;/span&gt;&lt;span&gt;createAnimation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;crop_zoom&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setInAnimation&lt;/span&gt;&lt;span&gt;(image, imageZoomAnimation);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setDuration&lt;/span&gt;&lt;span&gt;(imageZoomAnimation, block.duration);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;engine.block.&lt;/span&gt;&lt;span&gt;setBool&lt;/span&gt;&lt;span&gt;(imageZoomAnimation, &lt;/span&gt;&lt;span&gt;&apos;animation/crop_zoom/fade&apos;&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Export The Video &amp;#x26; Scene&lt;/strong&gt;&lt;br&gt;
Exporting the video is easy. Just pass the page to the export function. In our example, we’re also saving the scene file so we can edit the video later.&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;// Export video&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; progressCallback&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;  renderedFrames&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  encodedFrames&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  totalFrames&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&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;  console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`Progress: ${&lt;/span&gt;&lt;span&gt;Math&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;round&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;encodedFrames&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; totalFrames&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;);&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; 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;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  page,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&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;  progressCallback,&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;// Save scene to string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; sceneData&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; engine.scene.&lt;/span&gt;&lt;span&gt;saveToString&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;// Create scene blob&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; sceneBlob&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Blob&lt;/span&gt;&lt;span&gt;([sceneData], {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  type: &lt;/span&gt;&lt;span&gt;&apos;text/plain&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;4-add-a-video-editor&quot;&gt;4. Add A Video Editor&lt;/h3&gt;
&lt;p&gt;The last step is to add the video editor for post editing and pass the scene file. With CE.SDK, this effort is reduced to adding a few lines of code. In the &lt;code&gt;init&lt;/code&gt; function, we’re configuring the editor and adding callbacks for the export:&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;const&lt;/span&gt;&lt;span&gt; initEditor&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; 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;A-O53TWXK5bfyconUx7e53S5YU7DzjuGpMAH5vvKjLd0zBa6IhsoF7zChy1uCVbj&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;guides-user&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          theme: &lt;/span&gt;&lt;span&gt;&apos;dark&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          baseURL: &lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;https://cdn.img.ly/packages/imgly/cesdk-js/1.44.0/assets&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          role: &lt;/span&gt;&lt;span&gt;&apos;Creator&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          ui: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            elements: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              view: &lt;/span&gt;&lt;span&gt;&apos;default&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              panels: {&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;              navigation: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                position: &lt;/span&gt;&lt;span&gt;&apos;top&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                action: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                  save: &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;                  load: &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;                  close: &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;                  download: &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;                  export: &lt;/span&gt;&lt;span&gt;true&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;              dock: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                iconSize: &lt;/span&gt;&lt;span&gt;&apos;normal&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;// &apos;large&apos; or &apos;normal&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                hideLabels: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; // false or true&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;          callbacks: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onUpload: &lt;/span&gt;&lt;span&gt;&apos;local&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onSave&lt;/span&gt;&lt;span&gt;: (&lt;/span&gt;&lt;span&gt;scene&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;=&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; element&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;              const&lt;/span&gt;&lt;span&gt; base64Data&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; btoa&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;unescape&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;encodeURIComponent&lt;/span&gt;&lt;span&gt;(scene)))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              element.&lt;/span&gt;&lt;span&gt;setAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                &apos;href&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                `data:application/octet-stream;base64,${&lt;/span&gt;&lt;span&gt;base64Data&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;              element.&lt;/span&gt;&lt;span&gt;setAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                &apos;download&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                `video-${&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;toISOString&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;}.scene`&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;              element.style.display &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;none&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              document.body.&lt;/span&gt;&lt;span&gt;appendChild&lt;/span&gt;&lt;span&gt;(element)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              element.&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;              document.body.&lt;/span&gt;&lt;span&gt;removeChild&lt;/span&gt;&lt;span&gt;(element)&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;            onClose&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;              onClose&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;            onLoad: &lt;/span&gt;&lt;span&gt;&apos;upload&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onDownload: &lt;/span&gt;&lt;span&gt;&apos;download&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onExport: &lt;/span&gt;&lt;span&gt;&apos;download&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;By following this cookbook, you can streamline the process of AI-generated video creation, making it fast and efficient. This method is especially useful for content creators, educators, and marketers looking to automate video production while maintaining creative control.&lt;br&gt;
Next, try experimenting with video styles, refining AI scripts, or exploring advanced editing.&lt;br&gt;
Feel free to &lt;a href=&quot;https://github.com/imgly/ai-video-creator&quot;&gt;GitHub&lt;/a&gt; repo and share your creations &lt;a href=&quot;https://x.com/imgly&quot;&gt;with us on X&lt;/a&gt;. Happy creating!&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>Eray</dc:creator><media:content url="https://blog.img.ly/2025/03/AI-video-generator-tutorial-1.jpg" medium="image"/><category>AI</category><category>CE.SDK</category><category>How-To</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>Unleash Creativity with CE.SDK’s New Plugin System</title><link>https://img.ly/blog/img-ly-sdk-plugin-system/</link><guid isPermaLink="true">https://img.ly/blog/img-ly-sdk-plugin-system/</guid><description>Teaser: Our new Plugin System empowers customization and creativity with one-click features, smart design tools, and generative AI.</description><pubDate>Mon, 03 Jun 2024 08:42:25 GMT</pubDate><content:encoded>&lt;p&gt;At IMG.LY, we have always believed that a superb design editor should be effortlessly customizable and extensible. We are thrilled to roll out a brand-new Plugin system for CE.SDK in the upcoming months—to take creative editing and feature development to the next level.&lt;/p&gt;
&lt;p&gt;Starting with one-click features like background removal or vectorizers, smart design tools like QR codes or subtitle generators, and deeply interactive features like generative AI for text and images; all these tools can be used or built by customers soon.&lt;/p&gt;
&lt;p&gt;Additionally, our upcoming Plugin system will bring you unparalleled autonomy by making feature development for our SDK accessible and offering extensive options to reconfigure our editor’s UI.&lt;/p&gt;
&lt;p&gt;Start exploring our Plugin System rollout now to immediately benefit from upcoming features.&lt;/p&gt;
&lt;h2 id=&quot;built-for-modification&quot;&gt;Built for Modification&lt;/h2&gt;
&lt;p&gt;Let’s dive deep into some of the opportunities CE.SDK plugins help unlock.&lt;/p&gt;
&lt;h3 id=&quot;unlocking-the-ai-revolution&quot;&gt;Unlocking the AI Revolution&lt;/h3&gt;
&lt;p&gt;While the AI transformation is already fully underway, much of the tech is still not very accessible to product builders, often requiring deep technical knowledge to get started. At the same time, AI features become significantly more valuable when integrated with other editing functionalities in workflows or automation. With our plugins, we aim to make it effortless to leverage innovation and put it to use.&lt;/p&gt;
&lt;h3 id=&quot;boosting-customer-autonomy&quot;&gt;Boosting Customer Autonomy&lt;/h3&gt;
&lt;p&gt;Key to our success is providing maximum flexibility and autonomy to our customers about product decisions. Ultimately, you shouldn’t depend on our product roadmap; rather, you should be able to add features when you like. While our SDKs are already highly configurable, plugins allow tailoring the whole user experience not only on a look &amp;#x26; feel level but through custom functionalities and editing experiences.&lt;/p&gt;
&lt;h3 id=&quot;accelerate-product-expansion&quot;&gt;Accelerate Product Expansion&lt;/h3&gt;
&lt;p&gt;Many ecosystems witnessed explosive growth in added value to the user after releasing plugin mechanisms. Currently, only IMG.LY core developers can contribute to the SDK. We have started to extend this to solution engineers and even designers on our team who don’t have much knowledge of the inner workings of the SDK. Ultimately, we will push this more and more into a community of contributors, making the community’s innovation accessible to everyone.&lt;/p&gt;
&lt;h2 id=&quot;key-concepts&quot;&gt;Key Concepts&lt;/h2&gt;
&lt;p&gt;Three important concepts have driven the development of our Plugins:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Customizable Menu Bars&lt;/strong&gt;&lt;br&gt;
We are extending our API so that it allows easy hooking into various parts of the UI. Our editor has key components like the inspector, toolbar, and on-canvas menu. These are now all accessible through an API, so you can hook your feature anywhere in the editor.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Easily hook your features anywhere in the editor.&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/key-concept-plugins-sdk-1_Z7C57k.webp&quot; srcset=&quot;/_astro/key-concept-plugins-sdk-1_Z1cMp6H.webp 640w, /_astro/key-concept-plugins-sdk-1_1mLpHS.webp 750w, /_astro/key-concept-plugins-sdk-1_1vy6cU.webp 828w, /_astro/key-concept-plugins-sdk-1_Z2cAeFG.webp 1080w, /_astro/key-concept-plugins-sdk-1_Z13AeBp.webp 1280w, /_astro/key-concept-plugins-sdk-1_2dEjpa.webp 1668w, /_astro/key-concept-plugins-sdk-1_Z7C57k.webp 1920w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UI Building Blocks to Provide Consistency&lt;/strong&gt;&lt;br&gt;
To reach a high level of consistency and speed up time for development, we will be providing out-of-the-box UI components such as buttons, sliders, text inputs, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Escape Hatches&lt;/strong&gt;&lt;br&gt;
From experience, we know that sometimes unique functionality needs unique solutions, so we have added escape hatches to add custom elements via HTML whenever needed.&lt;/p&gt;
&lt;h2 id=&quot;what-can-you-build-with-our-plugin-system&quot;&gt;What Can You Build with our Plugin System?&lt;/h2&gt;
&lt;p&gt;Let’s explore some potential use cases of the plugin system.&lt;/p&gt;
&lt;h3 id=&quot;custom-actions&quot;&gt;Custom Actions&lt;/h3&gt;
&lt;p&gt;Adding custom actions is a great option to make simple third-party APIs accessible within the editor. This can be &lt;strong&gt;one-click edits&lt;/strong&gt; such as background removal, vectorizers, or auto-enhancement for images. You can also add custom actions for text in combination with Large Language Models (LLM) to provide features like autocorrection and improved writing, etc.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/plugin-release/background-removal-plugin-sdk.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;custom-tools&quot;&gt;Custom Tools&lt;/h3&gt;
&lt;p&gt;Some custom functionality will require more than just a single button, e.g., to &lt;strong&gt;generate AI images&lt;/strong&gt;, background patterns, QR codes, or maps. In these cases, you’ll require sliders, text input, drop-downs, and many other UI elements. With plugins, you can easily create panels with your own UI to bring any custom tool to life.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/plugin-release/ai-generator-plugin-sdk.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;custom-assets--presets&quot;&gt;Custom Assets &amp;#x26; Presets&lt;/h3&gt;
&lt;p&gt;Apart from building custom tools, you can also bundle and group effects into presets and make them accessible in a custom panel. This is especially useful to simplify the design process or create standard design components: for example, providing beautiful text presets will enable your users to create instantly great text designs without any design knowledge.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bundle presets or sticker packs for a stylish, simple design process.&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/custom-bundles-sdk-s_Z2eX5Wk.webp&quot; srcset=&quot;/_astro/custom-bundles-sdk-s_wWPTG.webp 640w, /_astro/custom-bundles-sdk-s_WbFjy.webp 750w, /_astro/custom-bundles-sdk-s_Zx5C9.webp 828w, /_astro/custom-bundles-sdk-s_Z1MpguG.webp 1080w, /_astro/custom-bundles-sdk-s_1RCU0T.webp 1280w, /_astro/custom-bundles-sdk-s_Z1MVQn1.webp 1668w, /_astro/custom-bundles-sdk-s_Z2eX5Wk.webp 1920w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;custom-libraries&quot;&gt;&lt;strong&gt;Custom Libraries&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Integrate third-party libraries, such as Unsplash, Getty Images, Pexels, or your own.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/plugin-release/photo-library-sdk-unsplash.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;custom-editor-behavior&quot;&gt;Custom Editor Behavior&lt;/h3&gt;
&lt;p&gt;Some of our customers asked us how they could move a functionality from one place in the editor to another. Let’s say you wish to move the function ‘move to front’ from the inspector to the canvas menu. This is not a problem! You can do this by using the internal API endpoints of our editor.&lt;/p&gt;
&lt;p&gt;As for custom editor behavior, you can do far more than just move functionality. Here is a demo of layer lists we built as a plugin.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/plugin-release/layer-list-editor-sdk.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;custom-user-feedback&quot;&gt;Custom User Feedback&lt;/h3&gt;
&lt;p&gt;Additionally, you can enhance the canvas with overlays, which are useful for providing alerts, instructions, or feedback directly on the canvas.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Provide instant design feedback to users, such as cut-off text or images.&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/custom-user-notification-design-feedback-1_Z1dtpGM.webp&quot; srcset=&quot;/_astro/custom-user-notification-design-feedback-1_1qQrVb.webp 640w, /_astro/custom-user-notification-design-feedback-1_yfu3B.webp 750w, /_astro/custom-user-notification-design-feedback-1_Z2ctvGd.webp 828w, /_astro/custom-user-notification-design-feedback-1_1CxUVl.webp 1080w, /_astro/custom-user-notification-design-feedback-1_29zsPe.webp 1280w, /_astro/custom-user-notification-design-feedback-1_Z81FNb.webp 1668w, /_astro/custom-user-notification-design-feedback-1_Z1dtpGM.webp 1920w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h2&gt;
&lt;p&gt;We are now rolling out Plugins and building an initial set of features through Plugins ourselves—available for the web first, and mobile SDKs will follow. Keep your eyes peeled for our next releases and don’t hesitate to &lt;a href=&quot;https://img.ly/forms/contact-sales&quot;&gt;get in touch&lt;/a&gt; with us to learn more about plugins, and how your product benefits from integration without losing time and resources.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thank you for reading. Join 3,000+ creative professionals—&lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i&quot;&gt;subscribe&lt;/a&gt; to our newsletter for updates on new features, plugins, early access, and more!&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Daniel</dc:creator><dc:creator>Eray</dc:creator><media:content url="https://blog.img.ly/2024/05/plugin-sdk-design-img-ly-s.jpg" medium="image"/><category>Plugin</category><category>App Development</category><category>Design Editor</category><category>Company</category></item><item><title>Work Where You Work Best</title><link>https://img.ly/blog/work-where-you-work-best/</link><guid isPermaLink="true">https://img.ly/blog/work-where-you-work-best/</guid><description>Img.ly will now transition into a remote-first company. We won’t get back to the old normal, as we don’t believe in an old normal. Now, we’re figuring out what it means to make a temporary change permanent.</description><pubDate>Tue, 23 Jun 2020 13:01:57 GMT</pubDate><content:encoded>&lt;p&gt;When the coronavirus pandemic started spreading in Germany, our team started working from home, weeks before it became mandatory. This step seemed comparatively easy for us, like for many other tech-driven companies.&lt;/p&gt;
&lt;p&gt;From the get-go, img.ly has been a company of digital natives, and as such we are used to digital tools for day to day work. Everyone already worked with laptops instead of desktop computers, we used online collaboration tools in the majority of our time, communicated with tools like Slack, and relied on cloud services whenever possible. So when the pandemic hit, we were perfectly equipped to work from home.&lt;/p&gt;
&lt;p&gt;As for everyone, there were a few hiccups in the beginning. Many of our teammates missed day-to-day social contact. We all like to chit chat once in a while, enjoy a coffee break in our neighborhood or have lunch together in one of the many local restaurants.&lt;/p&gt;
&lt;p&gt;From day one, we added more video calls and played online games to compensate for the missing real-life interactions. We also tried to recreate our office atmosphere by introducing voice channels aside from our other communication channels.&lt;/p&gt;
&lt;p&gt;We realized that the newly introduced voice channels were used extensively in the first few weeks but became vacant later on. Instead, people relied on slack or zoom to hop on a call whenever necessary or wrote down problems to discuss with the team &lt;em&gt;asynchronously&lt;/em&gt; over time.&lt;/p&gt;
&lt;p&gt;After two to four weeks everything seemed to be back at what we would call normal operation. Everyone was back on track and we were making progress towards our goals.&lt;/p&gt;
&lt;p&gt;While it is obvious to us that the current situation is pretty special, we realized that it might be a good time to reassess how we work and what defines img.ly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How can we use the current situation to come out stronger when it’s over?&lt;/strong&gt;&lt;br&gt;
Somehow it bothered us how everyone talked about &lt;em&gt;things getting back to normal&lt;/em&gt;. Obviously, we want our social contacts back, go to restaurants, bars and meet with friends, but what about day-to-day work? Was it better before? Or maybe, does it feel better now?&lt;/p&gt;
&lt;h2 id=&quot;work-when-you-work-best&quot;&gt;Work when you work best&lt;/h2&gt;
&lt;p&gt;Before to this new situation, we always had flexible working hours and relied on everyone making their own decision &lt;em&gt;when&lt;/em&gt; to work best. While everyone started at different times during the day, we all came to the office eventually. Working from home was possible but only used as an exception when needed.&lt;/p&gt;
&lt;p&gt;The reason was simple: we preferred brief, sometimes spontaneous communication between teams and team members in the office during the day, which made us feel quick in our decision making. Over the years, with a growing team and office space, we sat together to discuss what “our” version of a good working environment was, eventually realizing that there is no one-size-fits-all solution, as everyone has their own needs. That’s why we always thought about different areas in the office that are built to amplify either trivial or deep work. The “virtual office” has similar requirements: We introduced Slack statuses like “Focus work” or “Out for a break” to communicate that they will be getting back later to other teammates if they have any questions. Eventually, everyone seemed to have more control over their own time while being productive, and some are being more productive than before.&lt;/p&gt;
&lt;h2 id=&quot;work-where-you-work-best&quot;&gt;Work where you work best&lt;/h2&gt;
&lt;p&gt;As said, some tensions came up. People were missing real-life contacts, and it seemed that communication between teams could be improved. While the first problem remains a challenge, the latter one got our attention quickly. Before jumping to conclusions, we asked ourselves if this was a new problem, only to realize that it had been there before, just mitigated by the daily run-ins in the office. This resulted in people feeling informed but eventually missing some important details. However, these occasional run-ins  in the office didn’t happen anymore, and as such, details would now easily get lost.&lt;/p&gt;
&lt;p&gt;Best practice would be to write down all information, record a video, or use other media that can be accessed asynchronously at any time by all team members. However, most saw this as a chore from the management, and as such, it was easily neglected or simply forgotten. Even if the information was written down, it just landed somewhere in our GoogleDrive, Asana, Jira, or some other tool. Principally available for everyone but found and looked at only by some.&lt;/p&gt;
&lt;p&gt;But now everyone needs this information as nobody has the occasional run-ins anymore, which creates a general urge to get more information. Instead of lengthy transcripts, people started sharing their results in Slack-channels and updating their daily to-dos in detail. Most importantly, it created awareness and partially converted a chore into something meaningful to the benefit of everyone. However, it is still far from perfect and we will continue to work on that.&lt;/p&gt;
&lt;h2 id=&quot;making-a-temporary-state-a-permanent-solution&quot;&gt;Making a temporary state a permanent solution&lt;/h2&gt;
&lt;p&gt;The taste of increased flexibility in your life and productivity at work leads us to consider making our temporary state a permanent solution.&lt;/p&gt;
&lt;p&gt;There are obvious strategic advantages for a tech company: The talent pool increases with a radically increased search radius. Also, we need less office space, a huge pain point we had recently.&lt;/p&gt;
&lt;p&gt;Still, there is a yin to the yang, and nothing comes on a silver platter. We now have to filter our talent pool for people that bring the right mindset in terms of expertise, structure, and seniority for remote work. Believe it or not, there are not so many left when applying such filters.&lt;/p&gt;
&lt;p&gt;We have to heavily invest in bringing our people together on a very regular basis because we are still a people business, and in-person interactions were key to our company’s success. We know about the perks of being an office-first company. According to &lt;a href=&quot;https://klinger.io/&quot;&gt;Andreas Klinger&lt;/a&gt;, “Head of Remote” at AngelList, remote work is great for iterations, while in-person meetings foster innovation. We can see that. It’s all solvable with the right process and mindset, but it’s important to be diligent about this.&lt;/p&gt;
&lt;p&gt;Thankfully, this topic has already been extensively covered with conferences, articles, and pioneer companies such as GitLab, Basecamp, and PSPDFKit. I can always recommend them as a reference when you start thinking about becoming a remote company. Of course, it’s easier when you’re a remote company from day one – nevertheless, we are convinced that this change is an opportunity for us to grow and thrive. So in the end, we made the best of the pandemic.&lt;/p&gt;</content:encoded><dc:creator>Daniel</dc:creator><dc:creator>Eray</dc:creator><media:content url="https://blog.img.ly/2020/06/DSC01546.jpg" medium="image"/><category>Company</category></item><item><title>Building the Creative Engine of the Digital World</title><link>https://img.ly/blog/building-the-creative-engine-of-the-world/</link><guid isPermaLink="true">https://img.ly/blog/building-the-creative-engine-of-the-world/</guid><description>With UBQ we are creating a platform for creative editing. We double down on our core belief that design can benefit a lot from technological advancements.</description><pubDate>Wed, 22 Apr 2020 12:42:48 GMT</pubDate><content:encoded>&lt;p&gt;Since releasing our first &lt;a href=&quot;https://img.ly/products/photo-sdk/&quot;&gt;Software Development Kit (&lt;strong&gt;SDK&lt;/strong&gt;) for photo editing&lt;/a&gt; in 2015, it quickly found its way into the hands of thousands of application developers. The demand allowed us to ramp up our efforts to expand our SDK to cover more platforms, add features and launch &lt;a href=&quot;https://img.ly/products/video-sdk/&quot;&gt;VideoEditor SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the same time, two very important things happened to us.&lt;/p&gt;
&lt;p&gt;First of all, we got experienced in building rendering engines, while learning in-depth about the requirements of processing photos for professional and semi-professional use-cases, on every platform. Our team leveled up big time, to a degree where we are confident there aren’t many teams with such a domain-specific expertise.&lt;/p&gt;
&lt;p&gt;Secondly, we gained critical insights into the visual creation process across many different industries, ranging from print services, social networks to marketing tools. In these processes, photo editing is only one part of the creative flow. There are topics like layouting, animation, generative design and many more, which go beyond the mere editing of an image, but are still essential to the business case.&lt;/p&gt;
&lt;p&gt;Our vision is to fill the obvious gap, providing a holistic solution that allows users to map entire creative flows into a tool. By leveraging our technology our customers will become a lot faster and more competitive in their markets.&lt;/p&gt;
&lt;p&gt;Six months ago, we decided to build the foundation for this vision and kicked off the development of &lt;strong&gt;UBQ,&lt;/strong&gt; an engine empowering a new generation of tools for creativity.&lt;/p&gt;
&lt;p&gt;It’s time to shed some light on our &lt;strong&gt;creative engine&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-creative-engine&quot;&gt;What is a Creative Engine?&lt;/h2&gt;
&lt;p&gt;Before we go forward, let’s establish what we mean by a &lt;strong&gt;creative engine&lt;/strong&gt;. In general, an engine is a platform that allows developers to create tools that support creators to perform specific tasks such as editing photos, creating visual appealing posters, or social media posts. From our perspective, a creative engine will ease the development of design tools for various niches and as such it must be easily adaptable for different usage and user requirements.&lt;/p&gt;
&lt;p&gt;To ensure that we don’t have to reinvent the wheel for each creative tool, a creative engine provides building blocks especially targeted to creative output. Some examples for these are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High-quality image adjustment, editing, filtering, and manipulation.&lt;/li&gt;
&lt;li&gt;Automated layouting of design elements on a canvas.&lt;/li&gt;
&lt;li&gt;High-quality text rendering and layout algorithms.&lt;/li&gt;
&lt;li&gt;Support for various industry-standard assets, image, and video formats.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, these are only some of the basic features – there are far more advanced things that a creative engine can provide.&lt;/p&gt;
&lt;p&gt;On the one hand, this may include scripting tools to ease the generation of generative art or automation for tedious design tasks via automated image segmentation.&lt;/p&gt;
&lt;p&gt;On the other hand, there are also tools that not only help the individual creator but ease the cooperation and collaboration between multiple creators and editors. The details may vary, but it can be as simple as defining formats to exchange assets and designs between creators or even allow the simultaneous editing of their creation.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;introducing-the-ubq-creative-engine&quot;&gt;Introducing the UBQ Creative Engine&lt;/h2&gt;
&lt;p&gt;With &lt;strong&gt;UBQ&lt;/strong&gt; we strive to lay the groundwork for modern visual and communication design.&lt;/p&gt;
&lt;p&gt;Believing that these days, a good design tool has to be there for you every step of the way – it has to be &lt;strong&gt;ub&lt;/strong&gt;i&lt;strong&gt;q&lt;/strong&gt;uitous**.** Let us explain what this means for us.&lt;/p&gt;
&lt;h3 id=&quot;usable-on-any-platform&quot;&gt;Usable on any Platform&lt;/h3&gt;
&lt;p&gt;In this sense, we want it to be easily accessible to everyone, and as such the &lt;strong&gt;UBQ&lt;/strong&gt; stands for its availability across multiple platforms. It is conceptionally &lt;strong&gt;web-&lt;/strong&gt; and &lt;strong&gt;mobile-first&lt;/strong&gt; but is also available for classic operating systems such as macOS, Linux, and Windows, while being easily portable across &lt;strong&gt;various platforms&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;unified-rendering-generative-and-inference-engine&quot;&gt;Unified Rendering, Generative, and Inference Engine&lt;/h3&gt;
&lt;p&gt;While our previous products focused on processing a single image or video, our scope is greatly extended with &lt;strong&gt;UBQ&lt;/strong&gt;. Besides being able to process multiple images, with effects such as filters, adjustments, and so forth, in &lt;strong&gt;UBQ&lt;/strong&gt; we generalized images to a concept we call &lt;strong&gt;Design Blocks&lt;/strong&gt;. As such, static images are not the only source of data. It can be anything, even code that generates the visual input. In turn allowing that generative patterns and complex generative art is processed directly in the engine.&lt;/p&gt;
&lt;p&gt;We put a lot of work in the last years into modern tools for automation to help creators get rid of time-consuming tasks such as image segmentation, color adjustments, and many others. Our foundation for this stems from modern machine learning and neural network advancements. As such &lt;strong&gt;UBQ&lt;/strong&gt; supports executing neural networks and inferring information. Thus basically allowing any neural network to be part of a design generalized in what we call &lt;strong&gt;Compute Blocks*&lt;/strong&gt;.*&lt;/p&gt;
&lt;h3 id=&quot;collaboration--interact-in-realtime-with-other-creators&quot;&gt;Collaboration – Interact in Realtime with other Creators&lt;/h3&gt;
&lt;p&gt;The cooperation and collaboration between multiple creators are dear to our hearts. Therefore, we believe that creation is not only the effort of an individual but of many.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UBQ&lt;/strong&gt; will enable multiple &lt;strong&gt;creators&lt;/strong&gt; to &lt;strong&gt;work together&lt;/strong&gt;. Thus, allowing a design team to work together, share thoughts and assets instantly. Consequently, this constributes in accelerating their workflows and enriching their creative process.&lt;/p&gt;
&lt;p&gt;All that is reinforced due to the &lt;strong&gt;multiplayer&lt;/strong&gt; approach to design as well as &lt;strong&gt;reusable design elements&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Creators shall be enabled to work together &lt;strong&gt;locally as well as&lt;/strong&gt; &lt;strong&gt;remotely&lt;/strong&gt; and &lt;strong&gt;interact on the same design at the same time&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;cooperation--ease-exchange-of-designs-with-your-peers&quot;&gt;Cooperation – Ease Exchange of Designs with your Peers&lt;/h3&gt;
&lt;p&gt;Besides the collaborative aspect, &lt;strong&gt;UBQ&lt;/strong&gt; is built around the interaction of creators and non-designers – which we refer to as editors.&lt;/p&gt;
&lt;p&gt;Editors will be enabled to take existing designs and adapt it to their needs, by either just giving instant feedback to the creators, changing color palettes to fit the needs of their corporate design guidelines or changing images and text passages to make a design appealing to their audience.&lt;/p&gt;
&lt;h3 id=&quot;design-blocks--smart-and-reusable-design-element&quot;&gt;Design Blocks – Smart and Reusable Design Element&lt;/h3&gt;
&lt;p&gt;Another important design decision is the ability to exchange and reuse design elements between several projects. Therefore, &lt;strong&gt;UBQ&lt;/strong&gt;s foundation is built around the concept of &lt;strong&gt;smart design elements&lt;/strong&gt; that we call &lt;strong&gt;blocks&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blocks&lt;/strong&gt; are reusable design elements that encapsulate complex and tedious design tasks.&lt;/p&gt;
&lt;p&gt;They currently come in two flavors, &lt;strong&gt;Design and Compute Blocks&lt;/strong&gt; ranging from simple predefined image adjustments settings to automated image segmentation as well as predefined adaptable design elements.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Design Block example showcasing automatic adaptable text layouts.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 5313px) 5313px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;5313&quot; height=&quot;3230&quot; src=&quot;https://img.ly/_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_Z1bm8Xz.webp&quot; srcset=&quot;/_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_2vz9rw.webp 640w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_1yLjN5.webp 750w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_1Ph6gR.webp 828w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_ZHWM9r.webp 1080w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_ZIwRrj.webp 1280w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_ZNRVRT.webp 1668w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_1YYsBS.webp 2048w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_Ze5EA7.webp 2560w, /_astro/2004_img.ly_Engine_Blogpost_Visual_Designblock--1-_Z1bm8Xz.webp 5313w&quot;&gt;&lt;/p&gt;
&lt;p&gt;From our point of view, creators should not have to spend their time with the recreation of preexisting designs. They should not have to watch tutorials just to get to the same output as someone else before. In &lt;strong&gt;UBQ&lt;/strong&gt;, these design blocks are the core foundation for building adaptable and interchangeable designs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Design blocks&lt;/strong&gt; respond to the available space, adapting their content accordingly and may include complex logical rules or just a combination of assets. &lt;strong&gt;UBQ&lt;/strong&gt; has all batteries included, providing a rich library of predefined blocks. By design, blocks can easily be built from a combination of other blocks or by using a scripting language similar to processing or p5.js to allow even generative and parametric design.&lt;/p&gt;
&lt;h3 id=&quot;final-words&quot;&gt;Final Words&lt;/h3&gt;
&lt;p&gt;As of April 2020, we are working on the &lt;strong&gt;UBQ&lt;/strong&gt; creative engine for almost half a year now incorporating knowledge from 5+ years developing our SDKs.&lt;/p&gt;
&lt;p&gt;We believe we can make an impact on how designs and design-tools are created, adapted and distributed. We are interested in your feedback and open to discussions, also we are looking for people who want to get involved as team members, early adopters or just want to play with it. Expect some demos during the end of summer showcasing what the &lt;strong&gt;UBQ&lt;/strong&gt; engine is capable of.&lt;/p&gt;
&lt;p&gt;Soon, we will get back to you with more exciting news.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;were-hiring&quot;&gt;We’re hiring!&lt;/h3&gt;
&lt;p&gt;Oh, and by the way, we’re hiring a Senior Frontend Developer at img.ly to reinforce our team and help shaping the frontend of our new design tool. Check out the job &lt;a href=&quot;https://img.ly/company/careers#job-openings&quot;&gt;here&lt;/a&gt; and drop us a line, if you are interested.&lt;/p&gt;</content:encoded><dc:creator>Daniel</dc:creator><dc:creator>Eray</dc:creator><media:content url="https://blog.img.ly/2020/04/2004_img.ly_Engine_Blogpost_Visual_Header--1-.png" medium="image"/><category>Design</category><category>Tech</category><category>Software Development</category><category>SaaS</category><category>How-To</category><category>Company</category></item><item><title>From 2D to 3D Photo Editing</title><link>https://img.ly/blog/from-2d-to-3d-photo-editing-948690b7b45e/</link><guid isPermaLink="true">https://img.ly/blog/from-2d-to-3d-photo-editing-948690b7b45e/</guid><pubDate>Tue, 26 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last November, we released Portrait, an iOS app that helps create amazing, stylized selfies and portraits instantly.&lt;/p&gt;
&lt;p&gt;With over a million downloads and many more portrait images created, we feel that the idea and vision of Portrait was more than confirmed. The central component of Portrait is an AI that is trained to clip portraits from the background, a technique we are eager to further improve and refine. In fact, Portrait helped us to explore a novel technique for image editing, as we were able to leverage a new powerful data set in photography: depth data.&lt;/p&gt;
&lt;p&gt;We began feeding our AI models with the depth data from the iPhone Xs TrueDepth camera and had one goal in mind: to infer depth information for portrait imagery, or bringing three-dimensionality into a two-dimensional photo. Along the way, we created a new architecture concept, that allows performance and memory improvements through modularizing and reusing neural networks.&lt;/p&gt;
&lt;p&gt;In the following article, we’d like to present some of our results along with the insights we made.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;An image and it’s corresponding depth map. (Source)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 600px) 600px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;600&quot; height=&quot;801&quot; src=&quot;https://img.ly/_astro/1-r23YFAfXu_OHchBqd4plKw_Z1KsEdA.webp&quot; srcset=&quot;/_astro/1-r23YFAfXu_OHchBqd4plKw_Z1KsEdA.webp 600w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-new-cool-depthdata&quot;&gt;The New Cool: Depth Data&lt;/h2&gt;
&lt;p&gt;The usage of depth data in image editing initially became available with the iPhone 7 Plus when Apple introduced ‘Portrait Mode’. By combining a depth map and face detection, the devices are able to blur our distant objects and backgrounds, mimicking a ‘bokeh’ or depth of field effect, which is well known from DSLRs cameras.&lt;/p&gt;
&lt;p&gt;While the actual implementation varies, all major manufacturers nowadays offer a similar mode by incorporating depth data into their image editing pipeline. This is either achieved through the conventional dual or even triple camera on the back of a phone, dual-pixel offset calculations combined with machine learning or dedicated sensors like Apples TrueDepth module. In fact, for a modern flagship phone, some sort of depth based portrait mode is almost a commodity.&lt;/p&gt;
&lt;p&gt;From a developers perspective, things look a little different: Depth data became a first-class citizen throughout the iOS APIs in iOS 11 and such data is now easily accessible on supported devices. Android users obviously have access to depth data as well, either by utilizing multiple cameras or by Googles dual-pixel based machine learning approach, seen in the newer Pixel 2 phones. But contrary to iOS, Android doesn’t yet offer a common developer interface to access such data. In fact, developers aren’t able to access any of the depth information Google or other manufacturers collected within their camera apps. This means developers would either need to implement the algorithm to infer depth from two images themselves or try to rebuild Googles sophisticated machine learning powered system. Neither of these options is practical and probably not even possible given the usual limitations to camera APIs.&lt;/p&gt;
&lt;p&gt;So although being quite common, depth data isn’t as easily accessible for developers as one might think. Right now you’re out of luck on Android, dependent on hardware on iOS and even then limited to the 1.000$ flagship if you’re interested in depth for images taken with the front camera. And last but not least, across all devices and platforms, there is no way for you to generate a depth map for an existing image.&lt;/p&gt;
&lt;h2 id=&quot;deep-possibilities&quot;&gt;Deep Possibilities&lt;/h2&gt;
&lt;p&gt;Despite the restrictions, we decided to first explore the power of depth for image editing, as depth data provides many new exciting creative possibilities:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A depth map visualized in 3D space. (Source)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1000px) 1000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1000&quot; height=&quot;433&quot; src=&quot;https://img.ly/_astro/1-UyLhWSDUQdKU-0wfKcYPgg_2cc62N.webp&quot; srcset=&quot;/_astro/1-UyLhWSDUQdKU-0wfKcYPgg_1RzFAE.webp 640w, /_astro/1-UyLhWSDUQdKU-0wfKcYPgg_1jHR91.webp 750w, /_astro/1-UyLhWSDUQdKU-0wfKcYPgg_1y3t3X.webp 828w, /_astro/1-UyLhWSDUQdKU-0wfKcYPgg_2cc62N.webp 1000w&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we have a depth map for a given image, our editing possibilities are increased dramatically. Instead of a 2D image, a flat plane of color values, we suddenly have a depth value for each individual pixel, which translates into a 3D landscape highlighting distinct objects in the foreground and a clear indication of background.&lt;/p&gt;
&lt;h3 id=&quot;depth-aware-editing&quot;&gt;Depth-aware Editing&lt;/h3&gt;
&lt;p&gt;Instead of relying on color and texture differences to determine fore- and background, one could literally edit these regions individually. This allows adjustments like darkening the background while lightening the foreground, which makes portraits ‘pop’. If we’d be able to generate a high-resolution depth map, we could easily replace the AI currently used in Portrait and would allow even more sophisticated creatives. Thanks to the new APIs, there are already some awesome iOS apps available that specialize in depth based editing. One famous example is Darkroom with their “depth-aware filters”:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Darkrooms ‘depth-aware’ filters. (Source)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1000px) 1000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1000&quot; height=&quot;450&quot; src=&quot;https://img.ly/_astro/1-RP-bR21xfOyDciBNgiQovQ_e4d4z.webp&quot; srcset=&quot;/_astro/1-RP-bR21xfOyDciBNgiQovQ_1k66MV.webp 640w, /_astro/1-RP-bR21xfOyDciBNgiQovQ_H7L4v.webp 750w, /_astro/1-RP-bR21xfOyDciBNgiQovQ_chxWN.webp 828w, /_astro/1-RP-bR21xfOyDciBNgiQovQ_e4d4z.webp 1000w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;depth-of-fieldeffects&quot;&gt;Depth of Field Effects&lt;/h3&gt;
&lt;p&gt;As a depth of field or bokeh effect was the initial motivation for Apple to incorporate depth sensing technology, it is one of the most obvious applications. Depth is crucial for such an effect, as the amount of bluriness of any given region directly depends on its distance to the camera lens.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 450px) 450px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;450&quot; height=&quot;600&quot; src=&quot;https://img.ly/_astro/1-t-iuevsvhcRZK1krCv4GVw_wkaR3.webp&quot; srcset=&quot;/_astro/1-t-iuevsvhcRZK1krCv4GVw_wkaR3.webp 450w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Artificial Depth of Field (Source) and 3D asset placement examples.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 800px) 800px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;800&quot; height=&quot;599&quot; src=&quot;https://img.ly/_astro/1-Uj0A37iDdBj7qljbO8tKEA_1bOpp5.webp&quot; srcset=&quot;/_astro/1-Uj0A37iDdBj7qljbO8tKEA_Blyk2.webp 640w, /_astro/1-Uj0A37iDdBj7qljbO8tKEA_Z1oLE5s.webp 750w, /_astro/1-Uj0A37iDdBj7qljbO8tKEA_1bOpp5.webp 800w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;3d-asset-placement&quot;&gt;3D Asset Placement&lt;/h3&gt;
&lt;p&gt;As mentioned above, a depth map gives us a 3D understanding of the image. We’re able to tell if subject A is positioned in front of or behind subject B. This allows placement of digital assets like stickers or text in a ‘depth-aware’ fashion, but could also be used to apply ‘intelligent’ depth of field, e.g. a bokeh effect that ensures all faces are in focus.&lt;/p&gt;
&lt;h2 id=&quot;enter-deeplearning&quot;&gt;Enter Deep Learning&lt;/h2&gt;
&lt;p&gt;Motivated by the possibilities enabled by depth maps, we were wondering if we could bring this magic to any type of portrait image. We consulted existing literature on depth inference and found various papers¹ and articles on the topic, some of which even presented results that seemed sufficient for our use cases. In our case, we didn’t need accurate, as in ‘this pixel is 30cm in front of the camera’, results, but we were only interested in getting the general distance relations correct. For us, knowing that region A was slightly behind but definitely way in front of region B was enough to generate a visually pleasing effect and by constraining our domain to portrait imagery, we were able to further reduce the tasks complexity.&lt;/p&gt;
&lt;p&gt;Given our experience with deep learning and our current focus on introducing machine learning powered features to the &lt;a href=&quot;https://img.ly/products/photo-sdk/&quot;&gt;PhotoEditor SDK&lt;/a&gt;, we immediately decided to tackle the new challenge with deep learning or more specifically convolutional neural networks. Having a huge dataset of image and depth map pairs available, made this choice even easier. We stuck to a system similar to our previous segmentation model but decided to put more emphasis on allowing the reuse of individual parts, as this would come in handy when adding additional features in the future. To achieve this, we created a new modularized neural network approach named Hydra, which will be presented in an upcoming blog post.&lt;/p&gt;
&lt;p&gt;During development, we followed our tried and tested workflow of starting with a complex custom model, which is then tweaked and refined to match our performance requirements while maintaining the prediction quality we need. Once that was done, we had a fast and small model, trained on thousands of iPhone front camera selfies and capable of inferring high fidelity depth maps from a plain RGB image in under a second.&lt;/p&gt;
&lt;h2 id=&quot;the-prototype&quot;&gt;The Prototype&lt;/h2&gt;
&lt;p&gt;After creating a small model capable of inferring depth maps for any given portrait image, we immediately wanted to evaluate its performance in a ‘real-world’ environment. We decided to build a prototype that applies a depth of field effect to a portrait image, by using the model and its outputs. With our long-term goal of deploying the model to iOS, Android and the web in mind, we built the prototype using TensorFlowJS to explore this newly released library. Our browser demo consists of a minimal ‘Hydra’ implementation with individual modules, one for extracting features and one for the actual depth inference, which can both be executed individually.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Our demo web app in action.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1200px) 1200px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1200&quot; height=&quot;442&quot; src=&quot;https://img.ly/_astro/1-rVZLH5Tsq0bBKjFNSlKYlA_Z23OWO9.webp&quot; srcset=&quot;/_astro/1-rVZLH5Tsq0bBKjFNSlKYlA_Z1dWDjs.webp 640w, /_astro/1-rVZLH5Tsq0bBKjFNSlKYlA_KKQvH.webp 750w, /_astro/1-rVZLH5Tsq0bBKjFNSlKYlA_ZoEQaL.webp 828w, /_astro/1-rVZLH5Tsq0bBKjFNSlKYlA_25hiok.webp 1080w, /_astro/1-rVZLH5Tsq0bBKjFNSlKYlA_Z23OWO9.webp 1200w&quot;&gt;&lt;/p&gt;
&lt;p&gt;While being optimized for performance and memory footprint, the trained weights of the model still add up to ~18MB, which we will improve by further fine-tuning or even applying pruning or quantization. Once the models are loaded, all further processing happens on the device though, so you may try out all the samples without worrying about your data plan.&lt;/p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;
&lt;p&gt;Seeing our vision come to life was quite a stunning experience. Suddenly our browser was able to perform a complex depth of field effect without the need for special hardware, manual annotations or anything else apart from our image. And the best part was manually moving the focal plane through the image, either by sliding or tapping on different regions. Although being trained on ‘just’ selfies the model handles turned heads, silhouettes and multiple people pretty well and isn’t as restricted to its domain as we initially expected.&lt;/p&gt;
&lt;p&gt;And while our initial prototype is still weighing in at ~18MB, we’re certain to slim that down further in order to use the model in production. Performance wise we were very impressed with the TensorFlowJS inference speed. Even though everything is happening on the client side and is therefore dependent on the clients hardware, we saw inference speed below one second right of the bat and those greatly improved after the initial run, as the resources were already allocated. While not being immediately helpful for the depth inference part, this allowed us to further confirm our theory behind Hydra: Re-running inference once the necessary resources on the machine have been allocated greatly increases performance and might even allow real-time performance after an initial setup-time.&lt;/p&gt;
&lt;p&gt;To summarise, we’re definitely eager to further explore the use of depth data in image editing and think we have found a way to overcome the access restrictions on different platforms and hardware with our custom model. Combined with our new Hydra approach we can see lots of potential features that will delight both our users and customers and we will keep you updated right here.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;(1)&lt;/strong&gt; &lt;br&gt;
The papers we extracted most knowledge for our use case from were:&lt;br&gt;
“Depth Map Prediction from a Single Image using a Multi-Scale Deep Network” (&lt;a href=&quot;https://arxiv.org/abs/1406.2283&quot;&gt;arXiv&lt;/a&gt;)&lt;br&gt;
“Deeper Depth Prediction with Fully Convolutional Residual Networks” (&lt;a href=&quot;https://arxiv.org/abs/1606.00373&quot;&gt;arXiv&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;*&lt;strong&gt;*Thanks for reading! To stay in the loop, subscribe to our&lt;/strong&gt; &lt;a href=&quot;https://photoeditorsdk.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>Malte</dc:creator><dc:creator>Eray</dc:creator><media:content url="https://blog.img.ly/2020/03/1-Rd4wX6T9PmoXZA56yVLgCQ-1.png" medium="image"/><category>Machine Learning</category><category>Photography</category><category>Deep Learning</category><category>Photos</category><category>Technology</category><category>AI</category></item><item><title>Rise above the Noise</title><link>https://img.ly/blog/rise-above-the-noise-9788494f3c0b/</link><guid isPermaLink="true">https://img.ly/blog/rise-above-the-noise-9788494f3c0b/</guid><description>Why we want to make design more accessible to everyone.</description><pubDate>Tue, 01 May 2018 22:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A few years back, a close friend came by with a presentation she had prepared for a marketing campaign. Overenergized by this career-boosting assignment, she had nothing else on her mind for weeks, barely reachable and always stressed out. When she finally popped out of her little bubble, you could feel how proud she was, presenting me her latest draft with a gleam in her eyes. She knew that I’m a very visual guy, so she asked for my opinion.&lt;/p&gt;
&lt;p&gt;While I could see the enormous amount of work she put into research, structure and storytelling, most of its brilliance was shaded by its design — or better, non-existing design. Oversaturated images, logos placed maliciously in the middle of nowhere, no concept of harmonic paddings, margins or color palettes. As a consequence, the visual presentation was an emotional flatline, to put it mildly. Slide after slide, I was in a constant struggle of ’should I tell her’ or not.&lt;/p&gt;
&lt;p&gt;If you’re a designer, you might be familiar with this feeling. Your trained eyes can be a true pain in the ass, often triggering discomfort whenever something is unbalanced, or, let’s say, lacks a certain design attitude. In the digital world, with each ad, presentation, website or user interface you come across, there lurks an urge to set things straight, like with a crooked frame on the wall. While some might argue that this can quickly end in an unhealthy compulsiveness, to some degree this is important. Good design is an essential ingredient to the effectiveness of the underlying medium. After all, your design is the packaging for your content, for your message, and as such, it deserves equal attention. When done right, its true power unfolds with emotions; it can make people feel excited, and most importantly, *&lt;strong&gt;*it can create desirability**&lt;/strong&gt;. In the end, it’s the perfect tool to maximise the impact of your message and let your work truly stand out. But heck, enough with design philosophy.&lt;/p&gt;
&lt;p&gt;Back at my friend’s computer, I suggested a few visual changes to the presentation, asking her to choose other fonts, pick different colours, change some pictures, and add more consistency to the layout. She did most of the changes herself following instructions and simple questions, which gave her a sense of ownership over the design.&lt;/p&gt;
&lt;p&gt;Looking back, it was two things that were really frustrating me. On the one hand it’s my conviction that a marketeer should know the basic principles of design. You’re responsible for communication, and design is an important tool to shape it and helps to rise above the noise. On the other hand, it was also the tools she’s been using for the presentation and assets that were responsible for that mess. Tools made for designers, so a designer can craft the most beautiful visuals, seem powerless in the hands of a novice. Even business tools like Powerpoint do so little to educate and empower their users to create good design. Time after time, I’ve seen how marketeers, coders, product managers and business managers across industries had to rely on design departments or just struggled with their own mediocre design skills.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Who could have known that this frequent observation would help us pave the way for our own product. In our early days, when we built the first versions of the PhotoEditor SDK, we focused on helping developers to add basic photo editing functions to their products. With non-destructive editing and handling of multiple elements of the canvas we expanded our editor beyond photography — to a design tool.&lt;/p&gt;
&lt;p&gt;Once we had all the essential functions in place, we started looking at every tool, from text over brush to adjustments from different angles. The most essential question was: how can this tool deliver beautiful output to those who lack design expertise? To those who don’t really know what character spacing is, or to the ones that don’t really understand what clarity does to an image and what it’s good for.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We believe in the vast potential of democratising design, and digital design starts with an editor.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Our journey towards that goal has just started. In April, we have launched a novel &lt;a href=&quot;https://img.ly/blog/text-design-ef84fe708d02/&quot;&gt;text design tool&lt;/a&gt; that makes text layouting a breeze. Our app Portrait showcases how we can generate beautifully designed portraits instantly and has already been downloaded over a Million times. There is much more to come, with tons of ideas, prototypes and data in our backpack.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Our text design tool&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 203px) 203px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;203&quot; height=&quot;361&quot; src=&quot;https://img.ly/_astro/1-g3nmBpbVaFxwcWC1st50xA_1NGfc5.webp&quot; srcset=&quot;/_astro/1-g3nmBpbVaFxwcWC1st50xA_1NGfc5.webp 203w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Of course, making our vision happen is tremendously challenging from a UI perspective, and again, it is the quality of the design that will make the difference. As editing is a process that spans platforms, use cases and mediums — I consider this job a true boss fight for every designer. A huge challenge with a huge accomplishment in return, provided that we’re able to pull it off.&lt;/p&gt;
&lt;p&gt;So, if you happen to be a designer, and feel the itching in your fingertips, just shoot us an email. &lt;a href=&quot;https://img.ly/company/careers&quot;&gt;Let’s start a conversation&lt;/a&gt;, and once you join our team let’s shape the future of design.&lt;/p&gt;
&lt;p&gt;*&lt;strong&gt;*Thanks for reading! To stay in the loop, subscribe to our&lt;/strong&gt; &lt;a href=&quot;https://photoeditorsdk.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>Eray</dc:creator><media:content url="https://blog.img.ly/2020/04/1-kqMsjh4DQYcHDs4Y0w2kEA.png" medium="image"/><category>Design</category><category>Marketing</category><category>Style Guides</category><category>Creativity</category><category>Photo Editing</category><category>Insights</category></item><item><title>When Creativity meets A.I.</title><link>https://img.ly/blog/when-creativity-meets-a-i-f48ee9a3612d/</link><guid isPermaLink="true">https://img.ly/blog/when-creativity-meets-a-i-f48ee9a3612d/</guid><description>How we built the Portrait App.</description><pubDate>Thu, 16 Nov 2017 23:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A new generation of A.I. algorithms, propelled by rising computational power, new hardware, and a shift in paradigms made its first notable impact in the creative world: The works of &lt;a href=&quot;https://arxiv.org/abs/1508.06576&quot;&gt;Gatys et al.&lt;/a&gt; and &lt;a href=&quot;https://papers.nips.cc/paper/2012/hash/c399862d3b9d6b76c8436e924a68c45b-Abstract.html&quot;&gt;Krizhevsky et al.&lt;/a&gt; have not only gathered considerable public attention but have helped apps like Prisma to be adapted and used by millions. I strongly believe that this is merely the beginning. *&lt;strong&gt;*With the help of machine learning, we will fine-tune, simplify, and automate creative processes and ultimately empower new techniques for design and content creation.**&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We’ve been following this topic for quite some time now and have spent considerable effort in researching the opportunities of deep learning for our &lt;a href=&quot;https://img.ly/products/photo-sdk/&quot;&gt;PhotoEditorSDK&lt;/a&gt;. After more than a year of research and development, today, we’re finally bringing one of our apps to beta. *&lt;strong&gt;*Portrait**&lt;/strong&gt; combines supervised deep learning with the visual power of our SDK. In a nutshell, Portrait makes creating beautifully designed portrait images as easy as taking a selfie. You turn your selfies into movie poster-like portraits, with styles ranging from double-exposure photography to stencil art. One may consider it as the next iteration of what Apple and Google recently brought to market with their new camera features.&lt;/p&gt;
&lt;p&gt;We’ve now come a long way and gained invaluable insights on our journey so far. Not only did we get our hands dirty with countless training sessions and refinements to the neural net, but our first hand experience also helped to set expectation management right and to dismantle hype from substance. Most notably, it changed our product shaping process, making it more important than ever to foster strong ties between the product stakeholders and to share a common vision and goal everybody can get behind.&lt;/p&gt;
&lt;p&gt;In the following I’d like to share the story of how we built the app and closed the gaps between roles of the stakeholders within this process.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;preface-before-neural-networks-were-the-hot-new-thing&quot;&gt;Preface: Before Neural Networks were the Hot New Thing&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.instagram.com/backslashtwentyone/&quot;&gt;My journey&lt;/a&gt; begins over ten years ago, while I was graduating in neuroscience. Back then, the idea of A.I. was just a vague promise. Artificial Neural Networks were too small, computers lacked the necessary power, and the results were certainly nice, but still too weak to compete with other traditional algorithms. Research felt stuck in tiny little specializations without really following a broader vision. Dazzled by its impracticability, my interest in Neural Networks slowly began to fade.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Me&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 837px) 837px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;837&quot; height=&quot;1005&quot; src=&quot;https://img.ly/_astro/image-19_Z1qfSoO.webp&quot; srcset=&quot;/_astro/image-19_Z17E27E.webp 640w, /_astro/image-19_Z181CKI.webp 750w, /_astro/image-19_Z1zXPnP.webp 828w, /_astro/image-19_Z1qfSoO.webp 837w&quot;&gt;&lt;/p&gt;
&lt;p&gt;It took research on Neural Networks another six years to get back on my radar. At that time, I was leading several product developments at 9elements. When I learned about the work of DeepMind (now Google) I had a genuine feeling that this time, A.I. was ready for the limelight.&lt;/p&gt;
&lt;p&gt;As we were in the course of building a library for image editing and computer vision — the PhotoEditorSDK, we realized how much neural nets could also affect the creative space, given its ability to abstract and formalize rules. What if there was a machine that could reproduce the common and dull tasks you have to do as an art director within a second? What if designers could get rid of repetitive and tedious activities that interrupt their creative flow?&lt;/p&gt;
&lt;p&gt;But this topic isn’t something you’d learn in a week, obviously. Still, innovations cannot happen if you’re not willing to take a risk, so we decided to invest considerable time and resources into this technology.&lt;/p&gt;
&lt;p&gt;From a product management’s perspective, this process is actually an anti-pattern: Usually, you wouldn’t want to start by finding the right purpose for a technology, instead you’d find the right technology for a purpose. I still believe that this is essentially the right approach, but sometimes you have to abandon your best practices and take a swim in uncharted waters. Consequently, we asked Malte, one of our iOS engineers, to spearhead our research and take a deep dive into this topic. We decided to start off with image segmentation as the first process that we wanted to optimize through machine learning. Masking and clipping sometimes can be a tedious tasks, and ultimately we wanted to reduce this process that can take several minutes to a single click.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;chapter-1-the-machine-engineer&quot;&gt;Chapter 1: The Machine Engineer&lt;/h2&gt;
&lt;p&gt;Malte, who is a diligent engineer and — how convenient — a &lt;a href=&quot;https://www.instagram.com/buhmi/&quot;&gt;passionate photographer&lt;/a&gt;, started investigating some approaches that focused on image segmentation. You can read more about his journey in his &lt;a href=&quot;https://img.ly/blog/deep-learning-for-photo-editing-943bdf9765e1/&quot;&gt;article&lt;/a&gt;. Although he experimented with various neural networks and post-processing techniques, the resulting masks sometimes lacked the desired accuracy and wouldn’t have matched a user’s expectations. This was a first expected insight. As we want to deliver ready-to-use products to our customers, that don’t need any complex tweaking, this was something we had to fix. Our problems originated mostly from our rather ambitious goal to segment any type of object within an image. It would have required to train with vast data and to scale up the number of filters in our network. However, due to our on-device constraint, this would have killed our carefully crafted performance.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Malte&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 960px) 960px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;960&quot; height=&quot;1280&quot; src=&quot;https://img.ly/_astro/image-20_1FNoyt.webp&quot; srcset=&quot;/_astro/image-20_ZMaLGV.webp 640w, /_astro/image-20_ZKUDmW.webp 750w, /_astro/image-20_vAmUF.webp 828w, /_astro/image-20_1FNoyt.webp 960w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Therefore, we shifted this generalist approach to a specialized network for images of a certain domain that the model can be applied to. In hindsight, this seems quite obvious, as our rather small model would have never been able to cope with the amount of variations existing in ‘the real world’ anyway. So, we went back to the drawing board and started discussing which domain to focus on. That’s where we got suck; we struggled to find an obvious trend in our customers’ use cases or known photography platforms.&lt;/p&gt;
&lt;p&gt;It was actually during his summer holiday, when Malte had the flash of genius. At a stop-over in Singapore, he noticed how the city was flooded with selfie-stick wielding tourists. The sheer amount of selfies taken at any public place in Singapore left him astonished and he realised that he just found the right domain. Selfies, and portraits in general, felt like an infinite datasource and prime use case for our image segmentation algorithm. Back home, we decided to focus on selfies and portrait-like photography.&lt;/p&gt;
&lt;p&gt;Malte started searching for portrait datasets and found a collection of roughly 2000 portrait images collected from Flickr. Those were a great starting point and after a few training runs, he already reached satisfactory results, as the model was now capable to capture all available variations. At that point, we had a system at our hands that was able to segment portrait or selfie images in real-time on the device you’re capturing them with. This seemed like a great opportunity, but we didn’t want to stop just there. Releasing a prototype that can free a selfie from its background is nice, but doesn’t feel like something that would truly showcase how AI can make a difference in our creative process.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;chapter-2-the-art-director&quot;&gt;Chapter 2: The Art Director&lt;/h2&gt;
&lt;p&gt;This is where our Art Director Tommi, a renowned graphic artist and former sprayer, stepped in to explore what can be done with *&lt;strong&gt;*a selfie, an accurate alpha mask and the image editing features from our PhotoEditor SDK**&lt;/strong&gt;. When Tommi took the lead, I asked him to draft a vision, a creative direction for our app that combines all the tools and possibilities at our disposal.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Tommi&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 820px) 820px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;820&quot; height=&quot;1048&quot; src=&quot;https://img.ly/_astro/image-21_Z16iIDq.webp&quot; srcset=&quot;/_astro/image-21_Zm3RuC.webp 640w, /_astro/image-21_1dqpLk.webp 750w, /_astro/image-21_Z16iIDq.webp 820w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Together, we started exploring portrait trends and unique imagery that would help us find a direction for our showcase. Soon, the walls of our meeting rooms and offices were plastered with inspirational works on portrait photography of all different kinds and styles. This visual catalogue kept inspiring us, although we weren’t sure on which style to settle in the end. It was when we could hardly find any more free spots on our walls and after looking at them for countless times that the idea struck:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What if we could enable users to turn their portrait to what we saw on these walls?&lt;/strong&gt; And this, without actually having the design expertise they would normally be required to do so.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Instead of brooding over a completely new form of portraits, we could take all these styles and instantly realize them with the technology we had. From that point on, we flipped our process upside down. Instead of thinking about what the technology is capable of, or identifying a problem worth solving, we aimed for the creative output that we wanted our app to produce. While we started our venture with a technology, we now had visual results that we could work towards. The main question shifted from “What is our technology capable of?” to “How can we achieve this visual output with our technology?”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Walls full of inspiration.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1400px) 1400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1400&quot; height=&quot;857&quot; src=&quot;https://img.ly/_astro/image-22_29aGwu.webp&quot; srcset=&quot;/_astro/image-22_Z5ex44.webp 640w, /_astro/image-22_19M8HX.webp 750w, /_astro/image-22_Z13ggyC.webp 828w, /_astro/image-22_Z2i4DqD.webp 1080w, /_astro/image-22_Z2tRtVa.webp 1280w, /_astro/image-22_29aGwu.webp 1400w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Tommi designed five lead graphics, so our team of engineers and designers could grasp what we ultimately wanted to achieve, using only a selfie and the features of our SDK.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;act-3-closing-ranks&quot;&gt;Act 3: Closing ranks&lt;/h2&gt;
&lt;p&gt;With such a clear vision for our app, we started separating the wheat from the chaff, categorizing the portraits and understanding which operations of our SDK we had to combine, assemble and enhance to create these visuals.&lt;/p&gt;
&lt;p&gt;What followed was a remarkable interplay across multiple stakeholders of our team. While we were always very vocal proponents of building strong relationship between product stakeholders, *&lt;strong&gt;*the introduction of the AI layer actually glued our team further together**&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Our designers started to embrace the engineering perspective, playfully identifying both opportunities and constraints through the tech layer. At the same time, our engineers embraced the design vision and formalized it into code. Let me give you some examples:&lt;/p&gt;
&lt;p&gt;While thinking of the UI, we understood that the transformation of a selfie into a graphical artwork required an immediate feedback for the user, so they can find a pose that works best with the respective artwork. Consequently, we optimized our networks for real-time processing, a true challenge that needed strong expertise in both iOS engineering and neural net architecture.&lt;/p&gt;
&lt;p&gt;Our designs and recipes in turn had to be tweaked to gracefully allow for errors of our AI, because an error rate of 3% can still produce undesired artefacts and mask inaccuracies. We did that by using techniques that beautifully fringed edges of the portrait.&lt;/p&gt;
&lt;p&gt;Altogether, the close cooperation, as well as countless meetings, feedback loops, and the continuous fine tuning of the code and underlying recipes is what brings us here.&lt;/p&gt;
&lt;p&gt;All of this wouldn’t have happened if we hadn’t took the risk to invest in a rising technology in the first place. And all of this wouldn’t have been possible if it wasn’t for the exemplary cooperation between all the stakeholders. Portrait is a showcase of how technology can inspire and tie a team together. This, in the end, is absolutely necessary if we want to achieve the leaps we expect with AI. If you want to impact the creative space by introducing an AI layer to it, your engineers have to think like designers, or at least deeply understand their work.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-road-ahead&quot;&gt;The Road Ahead&lt;/h2&gt;
&lt;p&gt;Portrait is a first showcase and one step of many in our venture to wire several AI aspects deep into our SDK. On our journey, we’ve identified many more opportunities where we can help broader audiences to make creative work and design more accessible. Of course, we will also improve our models and networks with better and more data, always keeping in mind the aesthetic and visual output we’d like to achieve. We’ll keep you posted on our updates and next ventures into this exciting new era.&lt;/p&gt;
&lt;p&gt;If you liked what you read, I’d encourage you to check out Portrait and our &lt;a href=&quot;https://img.ly/products/photo-sdk/&quot;&gt;PhotoEditor SDK&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Thanks to my co-authors Malte &amp;#x26; Felix!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading! 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>Eray</dc:creator><media:content url="https://blog.img.ly/2020/04/image-3.jpeg" medium="image"/><category>Artificial Intelligence</category><category>Creativity</category><category>iOS</category><category>Deep Learning</category><category>Machine Learning</category><category>AI</category></item></channel></rss>