<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anass Laribi</title>
    <description>The latest articles on DEV Community by Anass Laribi (@anaslaribi95).</description>
    <link>https://dev.to/anaslaribi95</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4117162%2F85882d91-425b-41d6-98e1-e5006cf5d254.png</url>
      <title>DEV Community: Anass Laribi</title>
      <link>https://dev.to/anaslaribi95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anaslaribi95"/>
    <language>en</language>
    <item>
      <title>How I Built a 100% Client-Side 8MB Video Compressor in Next.js with WebAssembly</title>
      <dc:creator>Anass Laribi</dc:creator>
      <pubDate>Wed, 09 Sep 2026 09:05:22 +0000</pubDate>
      <link>https://dev.to/anaslaribi95/how-i-built-a-100-client-side-8mb-video-compressor-in-nextjs-with-webassembly-77f</link>
      <guid>https://dev.to/anaslaribi95/how-i-built-a-100-client-side-8mb-video-compressor-in-nextjs-with-webassembly-77f</guid>
      <description>&lt;p&gt;Online video compressors are usually frustrating: you have to upload a 100MB personal video to a remote cloud server, wait in an artificial processing queue, deal with intrusive popup ads, and download a watermarked video.&lt;/p&gt;

&lt;p&gt;I wanted to see if modern browser technology was fast enough to run desktop-grade video compression entirely on the user's computer with zero server uploads.&lt;/p&gt;

&lt;p&gt;Here is the technical breakdown of how I built clipshrink.com using Next.js 16, React 19, and FFmpeg compiled to WebAssembly (WASM).&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;The Architecture: In-Browser Sandboxing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Traditional cloud tools rely on multi-core backend server clusters. ClipShrink takes the opposite approach: **0 bytes ever leave the user's device.&lt;/p&gt;

&lt;p&gt;[User Selects Video (.mp4, .mov, .webm)]&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
[Local Browser RAM Sandbox] ◄─── (0 bytes sent to external cloud servers)&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
[Dynamic Target Bitrate Math] ◄─── Bitrate = (Target MB × 8192) / Duration&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
[FFmpeg WebAssembly Pipeline] ◄─── Local CPU software re-encoding&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
[Instant Local MP4 Download] ◄─── Encoded with '+faststart' web streaming&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;The Tech Stack&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Framework: Next.js 16 (App Router)&lt;br&gt;
Interactive Core: &lt;code&gt;@ffmpeg/ffmpeg&lt;/code&gt; and &lt;code&gt;@ffmpeg/util&lt;/code&gt;&lt;br&gt;
Styling: Tailwind CSS v4&lt;br&gt;
Hosting:** Vercel (Edge network)&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;Engineering Challenges &amp;amp; Solutions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A. Eliminating Third-Party CDN Latency&lt;br&gt;
Originally, the app loaded &lt;code&gt;@ffmpeg/core&lt;/code&gt; from public CDNs (&lt;code&gt;unpkg.com&lt;/code&gt;). This created a single point of failure: privacy extensions and ad-blockers regularly blocked external CDN requests.&lt;/p&gt;

&lt;p&gt;The Solution: Self-hosting the &lt;code&gt;.wasm&lt;/code&gt; and &lt;code&gt;.js&lt;/code&gt; binaries in the &lt;code&gt;/public/ffmpeg/&lt;/code&gt; directory with immutable edge caching:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
typescript
await ffmpeg.load({
  coreURL: await toBlobURL("/ffmpeg/ffmpeg-core.js", "text/javascript"),
  wasmURL: await toBlobURL("/ffmpeg/ffmpeg-core.wasm", "application/wasm"),
});

B. Mobile Safari Memory Guard
iOS Safari enforces a strict WebAssembly heap allocation limit (typically 1GB–1.5GB). Attempting to process a 4K 60fps file directly in browser memory causes the tab to crash.
To protect the user experience, we implemented client-side file size guards before allocating memory:

const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
if (isMobile &amp;amp;&amp;amp; file.size &amp;gt; 150 * 1024 * 1024) {
  setError("Files over 150MB may exceed mobile browser memory. Please use a desktop browser.");
  return;
}

C. Fast Bilinear Downscaling
4K video has 8.3 million pixels per frame. Using FFmpeg's default bicubic scaler inside single-threaded WebAssembly resulted in long encoding times.
By introducing -sws_flags fast_bilinear and -preset ultrafast, we cut downscaling CPU cycles by 60% to 70% while maintaining crisp 720p HD output for platform limits like:
Discord 8MB Limit
WhatsApp 16MB Limit
Gmail / Outlook 25MB Attachments




&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
