<?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: Ujjawal Kashyap</title>
    <description>The latest articles on DEV Community by Ujjawal Kashyap (@mrujjwalg).</description>
    <link>https://dev.to/mrujjwalg</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3900412%2Fa6acdc4c-6fb7-43da-a954-1b9a11f60b0a.png</url>
      <title>DEV Community: Ujjawal Kashyap</title>
      <link>https://dev.to/mrujjwalg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrujjwalg"/>
    <language>en</language>
    <item>
      <title>Play HEVC, AV1 and MKV in the browser with WebCodecs (no server transcoding)</title>
      <dc:creator>Ujjawal Kashyap</dc:creator>
      <pubDate>Mon, 27 Apr 2026 14:22:49 +0000</pubDate>
      <link>https://dev.to/mrujjwalg/play-hevc-av1-and-mkv-in-the-browser-with-webcodecs-no-server-transcoding-57</link>
      <guid>https://dev.to/mrujjwalg/play-hevc-av1-and-mkv-in-the-browser-with-webcodecs-no-server-transcoding-57</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Movi Player uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API" rel="noopener noreferrer"&gt;WebCodecs&lt;/a&gt; + a &lt;a href="https://webassembly.org/" rel="noopener noreferrer"&gt;WebAssembly&lt;/a&gt; demuxer (FFmpeg compiled to WASM) to play &lt;strong&gt;HEVC, AV1, MKV, 4K HDR, and multi-audio&lt;/strong&gt; files directly in the browser. No server transcoding. No FFmpeg on your backend. Drop-in replacement for &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i movi-player
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;movi-player&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"movie.mkv"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/movi-player&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://moviplayer.com" rel="noopener noreferrer"&gt;moviplayer.com&lt;/a&gt; · &lt;a href="https://movi-player-examples.vercel.app/element.html" rel="noopener noreferrer"&gt;Live demo&lt;/a&gt; · &lt;a href="https://github.com/mrujjwalg/movi-player" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://chromewebstore.google.com/detail/movi-player/ckleeigcopjnpehkjokijokjegknfgej" rel="noopener noreferrer"&gt;Chrome extension&lt;/a&gt; · &lt;a href="https://marketplace.visualstudio.com/items?itemName=mrujjwalg.movi-player-vscode" rel="noopener noreferrer"&gt;VS Code extension&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why WebCodecs matters for web video
&lt;/h2&gt;

&lt;p&gt;Every major browser ships with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API" rel="noopener noreferrer"&gt;WebCodecs&lt;/a&gt; — a low-level API that gives you direct access to the GPU's hardware video decoder. The same silicon that decodes Netflix, YouTube, your OS video player. Sitting right there in &lt;code&gt;window.VideoDecoder&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And yet the entire web video ecosystem still acts like it's 2015:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; plays maybe MP4/H.264 reliably and shrugs at everything else&lt;/li&gt;
&lt;li&gt;video.js, hls.js, Plyr — all wrappers around that same &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;Anything fancy → "transcode it on the server with FFmpeg"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I asked the obvious question: &lt;strong&gt;what if you skipped the &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; tag entirely and went straight to WebCodecs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's Movi Player.&lt;/p&gt;

&lt;h2&gt;
  
  
  Codecs supported by WebCodecs in 2026
&lt;/h2&gt;

&lt;p&gt;Once you stop fighting &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; and decode frames yourself via WebCodecs, the codec wall basically falls over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;H.264 / AVC&lt;/strong&gt; — yes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;H.265 / HEVC&lt;/strong&gt; — yes (the one Safari guards behind paywalls)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VP8 / VP9&lt;/strong&gt; — yes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AV1&lt;/strong&gt; — yes (next-gen, almost no native &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; support)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MPEG-2, MPEG-4 Part 2&lt;/strong&gt; — yes (legacy stuff that breaks &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Hardware decode where available, software fallback where not&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same story for audio: AAC, MP3, Opus, FLAC, AC-3, E-AC-3 — all decoded in the browser.&lt;/p&gt;

&lt;p&gt;The browser had this power the whole time. We just had to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebCodecs alone isn't enough — you need a demuxer
&lt;/h2&gt;

&lt;p&gt;WebCodecs decodes &lt;em&gt;frames&lt;/em&gt;. It doesn't know what an MKV file is. It doesn't parse containers, doesn't pull tracks, doesn't read HDR metadata, doesn't do seeking, doesn't handle subtitles.&lt;/p&gt;

&lt;p&gt;That's the other half of Movi Player: a &lt;strong&gt;WebAssembly demuxer&lt;/strong&gt; (&lt;a href="https://ffmpeg.org/" rel="noopener noreferrer"&gt;FFmpeg&lt;/a&gt; compiled to WASM) that cracks open the file, pulls each track out, and feeds raw packets to WebCodecs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File → WASM demuxer → packets → WebCodecs decoder → Canvas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: you get the formats FFmpeg understands (basically everything) decoded at the speed of native hardware. Zero server transcoding. Zero &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;movi-player&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"movie.mkv"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/movi-player&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one line plays MKV, HEVC, AV1, 4K HDR, multi-audio, embedded subtitles — everything &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; can't.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Try it now&lt;/strong&gt;: &lt;code&gt;npm i movi-player&lt;/code&gt; — &lt;a href="https://movi-player-examples.vercel.app/element.html" rel="noopener noreferrer"&gt;live demo&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Standalone WASM demuxer for video metadata (50KB)
&lt;/h2&gt;

&lt;p&gt;Sometimes you don't even &lt;em&gt;want&lt;/em&gt; to play the video. You want to know what's &lt;em&gt;in&lt;/em&gt; it — codecs, resolution, HDR flags, audio languages, chapter list.&lt;/p&gt;

&lt;p&gt;Movi ships a separate &lt;strong&gt;demuxer-only build&lt;/strong&gt; for that. ~50KB of JS + the shared WASM binary, no playback code, no UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Demuxer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpSource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;movi-player/demuxer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;demuxer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Demuxer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video.mkv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;demuxer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Duration: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;s`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Format: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formatName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Chapters: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chapters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;demuxer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVideoTracks&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;codec&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frameRate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;fps`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HDR: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isHDR&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorPrimaries&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorTransfer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;demuxer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAudioTracks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// [{ codec: "ac3", language: "hin" }, { codec: "aac", language: "eng" }, ...]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;demuxer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSubtitleTracks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// [{ codec: "srt", language: "eng" }, { codec: "ass", language: "jpn" }, ...]&lt;/span&gt;

&lt;span class="nx"&gt;demuxer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Video validators&lt;/strong&gt; before upload — reject 8K HDR uploads on a free plan, no server round-trip&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asset management dashboards&lt;/strong&gt; — show codec, resolution, language tracks at a glance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HDR detection pipelines&lt;/strong&gt; — flag content for the HDR rendering path&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search indexing&lt;/strong&gt; — extract chapter titles, audio languages, subtitle text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-transcode analysis&lt;/strong&gt; — check what you're about to spend money re-encoding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All client-side. No server. No FFmpeg on a Lambda.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-audio track switching in the browser
&lt;/h2&gt;

&lt;p&gt;Once you have the tracks, you can let users &lt;em&gt;use&lt;/em&gt; them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; will never give you this. Movi exposes every audio track in the file and lets the user switch live, mid-playback. Press &lt;code&gt;B&lt;/code&gt; or pick from the menu.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hindi dub → English original → Japanese → director's commentary&lt;/li&gt;
&lt;li&gt;All from one file&lt;/li&gt;
&lt;li&gt;Zero server work&lt;/li&gt;
&lt;li&gt;Subtitles (&lt;code&gt;V&lt;/code&gt; key) switch the same way — SRT, ASS, embedded PGS, all of it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For anime sites, regional OTT, language learning apps, film archives — this alone is worth the swap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other features: HDR, subtitles, encrypted playback
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HDR rendering&lt;/strong&gt; — real BT.2020 / PQ / HLG tone-mapping on supported displays. No other web player does this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded subtitles&lt;/strong&gt; — pulled straight out of the MKV. No external WebVTT conversion step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted playback&lt;/strong&gt; — AES-256-GCM, HMAC-signed tokens, 2-second expiry. No DRM license server, no Widevine contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canvas-based render&lt;/strong&gt; — no &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element exposed, right-click "save video" disabled by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Picture-in-Picture, ambient mode, chapters, thumbnails, rotation&lt;/strong&gt; — all built on top of the canvas pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Movi Player vs video.js vs hls.js vs Plyr
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Movi&lt;/th&gt;
&lt;th&gt;video.js&lt;/th&gt;
&lt;th&gt;hls.js&lt;/th&gt;
&lt;th&gt;Plyr&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WebCodecs-based decode&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HEVC / AV1&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-audio switching (client-side)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;HLS only&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HDR rendering&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embedded subs (SRT/ASS/PGS)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No server transcoding&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encrypted (no DRM server)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Bundle sizes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Build&lt;/th&gt;
&lt;th&gt;What you get&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;movi-player/demuxer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Metadata, track info, HDR detection&lt;/td&gt;
&lt;td&gt;~50KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;movi-player/player&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Programmatic playback, no UI&lt;/td&gt;
&lt;td&gt;~180KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;movi-player&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full player with controls, gestures, themes&lt;/td&gt;
&lt;td&gt;~410KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;WASM binary is shared across all three and Brotli-friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can browsers play MKV files natively?
&lt;/h3&gt;

&lt;p&gt;Not reliably. Chrome plays &lt;em&gt;some&lt;/em&gt; H.264-in-MKV files but multi-audio, HEVC, and AV1 inside MKV fail silently or throw "format not supported". Movi Player uses WebCodecs + a WASM demuxer to decode every track in the file regardless of browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I play HEVC (H.265) in the browser without Safari?
&lt;/h3&gt;

&lt;p&gt;Yes. Chrome 107+, Edge, and Safari 16.4+ expose HEVC decoders through WebCodecs even when &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; refuses to play HEVC. Movi Player taps directly into those decoders.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does AV1 work in the browser?
&lt;/h3&gt;

&lt;p&gt;Yes — most modern browsers expose AV1 in WebCodecs (hardware decode where available, software fallback otherwise). Movi Player handles both transparently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is WebCodecs supported in all browsers?
&lt;/h3&gt;

&lt;p&gt;Chrome 94+, Edge 94+, Safari 16.4+. Firefox support is in progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need server-side FFmpeg or transcoding?
&lt;/h3&gt;

&lt;p&gt;No. All decoding happens client-side via WebCodecs + WebAssembly. Your server just needs to support HTTP range requests for seeking.&lt;/p&gt;

&lt;h3&gt;
  
  
  How big is the bundle?
&lt;/h3&gt;

&lt;p&gt;50KB for the demuxer-only build, 180KB for programmatic playback, 410KB for the full player UI. WASM binary is shared and Brotli-compresses well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it without writing code: web app, Chrome + VS Code extensions
&lt;/h2&gt;

&lt;p&gt;Don't want to integrate the library yet? Just use the player.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://moviplayer.com" rel="noopener noreferrer"&gt;moviplayer.com&lt;/a&gt;&lt;/strong&gt; — drop any video file into the browser and it plays. MKV, HEVC, AV1, HDR, multi-audio — all client-side, nothing uploaded. The fastest way to test what Movi can do with your own files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://chromewebstore.google.com/detail/movi-player/ckleeigcopjnpehkjokijokjegknfgej" rel="noopener noreferrer"&gt;Movi Player for Chrome&lt;/a&gt;&lt;/strong&gt; — adds a play button overlay on video links across the web, right-click "Open with Movi Player" on any URL, or paste a video URL into the popup. MKV, HEVC, AV1, HDR — all play in-browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=mrujjwalg.movi-player-vscode" rel="noopener noreferrer"&gt;Movi Player for VS Code&lt;/a&gt;&lt;/strong&gt; — single-click any video file in the Explorer to play it inside VS Code. MKV, HEVC, AV1, HDR, even &lt;code&gt;.iso&lt;/code&gt; / &lt;code&gt;.vob&lt;/code&gt; via "Open With…". 100% local, no upload.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same WebCodecs + WASM demuxer pipeline under the hood — these are a way to dogfood (and demo) the library on real-world files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Web app&lt;/strong&gt;: &lt;a href="https://moviplayer.com" rel="noopener noreferrer"&gt;https://moviplayer.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;code&gt;npm i movi-player&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome extension&lt;/strong&gt;: &lt;a href="https://chromewebstore.google.com/detail/movi-player/ckleeigcopjnpehkjokijokjegknfgej" rel="noopener noreferrer"&gt;https://chromewebstore.google.com/detail/movi-player/ckleeigcopjnpehkjokijokjegknfgej&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code extension&lt;/strong&gt;: &lt;a href="https://marketplace.visualstudio.com/items?itemName=mrujjwalg.movi-player-vscode" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=mrujjwalg.movi-player-vscode&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live demo&lt;/strong&gt;: &lt;a href="https://movi-player-examples.vercel.app/element.html" rel="noopener noreferrer"&gt;https://movi-player-examples.vercel.app/element.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demuxer demo&lt;/strong&gt;: &lt;a href="https://movi-player-examples.vercel.app/demuxer.html" rel="noopener noreferrer"&gt;https://movi-player-examples.vercel.app/demuxer.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/mrujjwalg/movi-player" rel="noopener noreferrer"&gt;https://github.com/mrujjwalg/movi-player&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Apache 2.0, free to use commercially&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd love feedback on
&lt;/h2&gt;

&lt;p&gt;I built this because the browser already had the tools — WebCodecs, WebAssembly, Canvas — and nobody was stitching them together for real-world video. Now I want to know what &lt;em&gt;you&lt;/em&gt; need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the WebCodecs-based decode the part that interests you, or is it multi-audio / HDR / encryption?&lt;/li&gt;
&lt;li&gt;Would you use the standalone demuxer (50KB) for upload validation or asset metadata?&lt;/li&gt;
&lt;li&gt;What integrations matter — Next.js, React Native Web, Vue, Svelte components?&lt;/li&gt;
&lt;li&gt;Is the 410KB full bundle a dealbreaker, or fine for a video-heavy app?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop a comment. Genuinely curious what's missing.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>webcodecs</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
