
A deep dive into the technical challenges of building an injected video popup SDK, achieving 10:1 compression ratios with WebAssembly and solving cross-domain communication with performance for optimal client satisfaction.
Valentin Chmara
Interactive video popups can significantly boost user engagement, but they pose serious performance challenges in modern web browsers. When building for Vendeo.io's injected video popup SDK, I encountered critical technical hurdles that required innovative solutions to ensure optimal client satisfaction and performance.
Key Achievements:
This article details the technical challenges I faced and the performance-oriented solutions that satisfied Vendeo clients' needs for fast, reliable video popup integration.
The Problem: Raw video files exceeding 50-100MB can cause severe performance degradation on client websites. If we load these files in web popups, the resulte can be:
Client impact: Website owners can be hesitant to implement video popups due to performance concerns, directly affecting adoption rates and customer satisfaction.
The problem:
Creating a video popup system that could be embedded on any website via a simple <script> tag while:
Client impact: Complex integration processes would have been a major barrier to adoption for non-technical clients.
I leveraged WebAssembly (WASM) to run FFmpeg directly in the browser, enabling powerful video processing without server infrastructure.
Technical implementation:
// Core compression workflow
const ffmpeg = createFFmpeg({ /* ... */ });
await ffmpeg.load(); // Load FFmpeg WASM module
ffmpeg.FS('writeFile', 'input.mp4', inputData); // Write input to memory
await ffmpeg.run(...ffmpegArgs); // Execute compression
const outputData = ffmpeg.FS('readFile', 'output.mp4'); // Read compressed output
I developed a precisely tuned FFmpeg command to achieve optimal compression after extensive testing with various parameters. The goal was to reduce file size while maintaining acceptable quality for popup displays.
ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 -pix_fmt yuv420p \
-color_primaries bt709 -color_trc bt709 -colorspace bt709 \
-c:a aac -strict experimental -b:a 192k -vf scale=398:-2 output.mp4
Key technical decisions:
| Parameter | Value | Rationale |
|---|---|---|
| Codec | H.264 (libx264) | Industry standard, universal browser support |
| Preset | Medium | Balance between compression speed and efficiency |
| CRF | 23 | Optimal quality-to-size ratio for popup displays |
| Resolution | 398px width | Perfectly sized for popup UI, maintains aspect ratio |
| Audio | AAC 192kbps | Preserves audio quality while reducing size |
Compression performance:
Client satisfaction impact:
I implemented an iframe-based architecture that provides both isolation and integration. The bundle is lightweight, ensuring minimal impact on host pages while allowing dynamic interaction.
Architecture benefits:
To ensure true isolation and zero performance impact on host sites, I inject the widget’s container <div> at the very end of the <body> only after the DOM is loaded wrap into an IIFE. This guarantees our SDK is always loaded last, preserving all client page priorities.
<script>
!function(){
document.addEventListener("DOMContentLoaded",()=>{
const e=document.createElement("div");
e.id="vendeo-app",document.body.appendChild(e);
const t=document.createElement("script");
t.src="https://db.vendeo.io/storage/v1/object/public/scripts/latest.js";
t.async=1;
t.type="module";
document.body.appendChild(t);
window.vendeo_flow_id="${props.id}";
})
}();
</script>
The SDK then mounts a minimal Vue 3 app (≈40KB) to manage all iframe logic and styling reactively. This approach ensures:
Technical implementation:
// Widget to parent communication
window.parent.postMessage({
type: "widget",
action: "is_left",
value: true/false
}, "*");
// Parent response handler
window.addEventListener("message", (event) => {
if (event.data.type === "widget") {
updateWidgetState(event.data.action, event.data.value);
}
});
This protocol allows the widget to:
Building Vendeo's video popup product meant fighting real-world browser quirks, pushing the boundaries of what’s possible with WebAssembly and JavaScript, and always keeping the client experience front and center.
Key Takeaways:
z-index: 2147483647, I ensured universal compatibility and zero conflicts, tested on Chrome, Safari, Firefox, and Edge.There were moments of frustration, like wrestling with browser memory limits and edge-case CORS bugs, but each challenge made the final product more robust. If you’re facing similar problems, know that the browser platform is far more capable than many engineers think. For example, Supabase's team has released a PostgreSQL in the browser that runs entirely in WebAssembly, proving that the limits of what’s possible are constantly being pushed.
Want to discuss similar technical challenges or performance optimization strategies? Connect with me on X or check out the Vendeo.io implementation.
Comparing modern JavaScript bundlers for Nuxt 3: Rspack, Vite, and Webpack
An in-depth comparison of Rspack, Vite, and Webpack, exploring their performance, features, and use cases to help you choose the right tool for your project.
From Root-Me to SaaS builder - My journey into code, security and autonomy
At 16, I wanted to break into systems. Today, I build them. This is how a hacker mindset, a frustrating job, and a Python minesweeper led me to be self-employed.