WebCodecs API Explained: How Browser Video Editors Work

WebCodecs is a browser API that lets JavaScript encode and decode video and audio frames using the browser's built-in codecs, often hardware-accelerated. It powers in-browser editors, but it doesn't read or write file containers such as MP4, and it is still a W3C Working Draft, so you pair it with a muxing library and feature detection.
Loopdesk's editor runs entirely in the browser on WebGPU and WebCodecs, so this is a topic we work with every day. This guide explains what the API is, which browsers support it, how an editor uses it, where it falls short and how it compares with FFmpeg.wasm. It goes deeper than our WebCodecs glossary entry and complements Browser-Based Video Editing and The Future of Video Editing With WebGPU.
Facts checked October 9, 2026 against the W3C specification, MDN (including its browser-compatibility data, v8.1.5 of October 8, 2026), the web-features and caniuse data, Apple's and Mozilla's release notes, Chrome for Developers, FFmpeg.wasm's documentation and the repositories listed under Sources. Full disclosure: Loopdesk is our product and is built on WebCodecs and WebGPU, so we have a stake in how this API is perceived; where support is partial, we say so.
What is the WebCodecs API?
WebCodecs is a web API that gives JavaScript low-level access to the browser's built-in video and audio encoders and decoders. It exposes VideoEncoder, VideoDecoder, AudioEncoder and AudioDecoder, plus frame and chunk types such as VideoFrame, AudioData, EncodedVideoChunk and EncodedAudioChunk. It is designed for applications like video editors, transcoders and low-latency streaming.
MDN lists twelve interfaces: AudioDecoder, VideoDecoder, AudioEncoder, VideoEncoder, EncodedAudioChunk, EncodedVideoChunk, AudioData, VideoFrame, VideoColorSpace, ImageDecoder, ImageTrackList and ImageTrack. The four codec classes and ImageDecoder are available in secure contexts (HTTPS) and in dedicated Web Workers, but not in Shared or Service Workers.
Its standards status matters for planning. WebCodecs is a W3C Working Draft (latest version published October 7, 2026, first published in April 2021), and W3C says it is "inappropriate to cite this document as other than a work in progress." The web-features data marks it as not Baseline (limited availability).
Why does WebCodecs exist when video, MediaRecorder and MSE already do video?
The older browser media APIs hide the codec. The video element plays whole files, Media Source Extensions need already-containerized data, and MediaRecorder encodes live streams in real time. WebCodecs exposes individual frames and chunks, so editors can decode, process and encode faster than real time, frame by frame.
| Approach | What it does | Raw frame access | Notes |
|---|---|---|---|
<video> element and Media Source Extensions | Plays media; MSE feeds a player with segments | No | The WebCodecs explainer: with MSE, "Applications must containerize input before adding it to the buffer" |
| MediaRecorder | Records a live MediaStream into a compressed file | No | The explainer: it "does not support faster-than-realtime encoding" |
| WebCodecs | Encodes and decodes individual frames and audio chunks with the browser's codecs | Yes: VideoFrame, AudioData | No container muxing or demuxing built in; "A VideoFrame can be passed to any method accepting a CanvasImageSource" |
| FFmpeg.wasm | FFmpeg compiled to WebAssembly | Yes (software) | Software codecs; licensing and threading notes below |
| Server-side FFmpeg | Upload, then transcode in the cloud | n/a | Costs bandwidth, servers and privacy trade-offs |
Which browsers support WebCodecs?
Chrome and Edge have supported WebCodecs since version 94, Opera since 80, Firefox on desktop since 130, and Safari since 16.4 for video, with audio encoders and decoders from Safari 26. Firefox for Android lacks the codec classes. caniuse data from September 30, 2026 shows about 91% of global usage with full support and about 3.5% partial.
| Interface | Chrome / Edge | Opera | Firefox (desktop) | Firefox for Android | Safari / iOS |
|---|---|---|---|---|---|
| VideoEncoder, VideoDecoder | 94 | 80 | 130 | No | 16.4 (video only) |
| AudioEncoder, AudioDecoder | 94 | 80 | 130 | No | 26 |
| VideoFrame | 94 | 80 | 130 | 130 | 16.4 |
| ImageDecoder | 94 | 80 | 133 | 133 | Preview only; not in Apple's release notes through Safari 27.0 (released September 14, 2026); not on iOS |
From MDN's compatibility data and vendor release notes (Apple 16.4: "Added video-only support for Web Codecs."; Apple 26.0: "Added support for WebCodec's AudioEncoder and AudioDecoder."; Mozilla, Firefox 130: "Enabled the Web Codecs API on desktop platforms"). VideoFrame and VideoColorSpace have been Baseline "low" since September 3, 2024. Some older blog posts claim "Safari 17+" or "Firefox 147+"; Apple, Mozilla and MDN don't support those numbers.
How does a browser video editor use WebCodecs?
An editor demuxes a file into encoded chunks, decodes them to VideoFrame objects with a VideoDecoder, composites frames on a canvas or with WebGPU, then re-encodes the result with a VideoEncoder and muxes the chunks back into MP4 or WebM. WebCodecs handles the decode and encode steps; the container work comes from a library.
file (MP4 / MOV / WebM)
└─ demux (library) ─▶ EncodedVideoChunk ─▶ VideoDecoder ─▶ VideoFrame
│
canvas or WebGPU: crop, captions, color, transitions
▼
file (MP4 / WebM) ◀─ mux (library) ◀─ EncodedVideoChunk ◀─ VideoEncoder
WebGPU is the natural partner. A VideoFrame can be imported as a GPU texture with GPUDevice.importExternalTexture(), and the WebGPU specification says that texture "expires (is destroyed) when, and only when, the source VideoFrame is closed". Draw first, then close the frame. WebGPU's availability varies by browser and operating system, so production editors keep a canvas fallback.
In Loopdesk: the editor is 100% browser-based, built on WebGPU and WebCodecs, so there is nothing to install and it works in Chrome, Firefox, Safari and Edge. Import covers MP4, MOV, MKV, AVI, WAV and MP3, and exports reach up to 4K. Which files a browser editor can open depends on its demuxers plus the codecs the browser exposes, which is why support is never just a WebCodecs question.
How do you check support and encode a frame?
Feature-detect with 'VideoEncoder' in window, then call VideoEncoder.isConfigSupported() with the exact configuration you plan to use, because support depends on codec, profile, resolution and device. Configure the encoder, feed it VideoFrame objects with microsecond timestamps, close each frame promptly, and flush before closing.
// 1. Detect support for the exact configuration you intend to use
if (!('VideoEncoder' in window)) {
throw new Error('WebCodecs is not available in this browser or context');
}
const config = {
codec: 'avc1.640028', // H.264 High profile, level 4.0
width: 1920,
height: 1080,
bitrate: 8_000_000, // 8 Mbps
bitrateMode: 'variable', // 'constant' | 'variable' (default) | 'quantizer'
framerate: 30,
hardwareAcceleration: 'prefer-hardware', // a hint, not a guarantee
};
const { supported } = await VideoEncoder.isConfigSupported(config);
if (!supported) {
// fall back to another codec string, a lower resolution, or a software path
}
// 2. Encode frames from a canvas and collect the chunks for a muxer
const chunks = [];
const encoder = new VideoEncoder({
output: (chunk, metadata) => chunks.push({ chunk, metadata }), // hand these to a muxer
error: (e) => console.error('Encoder error', e),
});
encoder.configure(config);
for (let i = 0; i < 90; i++) { // 3 seconds at 30 fps
const frame = new VideoFrame(canvas, { timestamp: (i * 1_000_000) / 30 }); // microseconds
encoder.encode(frame, { keyFrame: i % 60 === 0 });
frame.close(); // release the frame promptly
}
await encoder.flush();
encoder.close();
Watch encoder.encodeQueueSize in a real loop and pause when the queue grows, so you don't buffer an entire timeline in memory. For choosing the bitrate, see Video Bitrate Explained.
| Codec string | Meaning (WebCodecs codec registry and MDN) |
|---|---|
avc1.640028 | H.264 High profile, level 4.0 |
vp09.00.10.08 | VP9 profile 0, level 1.0, 8-bit |
av01.0.08M.08 | AV1 Main profile, level 4.0, Main tier, 8-bit |
Useful VideoEncoderConfig options: hardwareAcceleration (no-preference, prefer-hardware, prefer-software), bitrateMode (constant, variable, quantizer; the last ignores the bitrate), latencyMode (quality or realtime) and avc.format (avc or annexb).
What are WebCodecs' limits and gotchas?
The main gotchas are: no container muxing or demuxing, codec support that varies by browser and device, hardware acceleration that is only a hint, codecs the browser may reclaim, frames you must close or decoding can stall, and secure-context and worker rules. Plan for fallbacks, and test on real devices.
- Containers. MDN says WebCodecs "does not provide a built-in way to read EncodedVideoChunk objects from a video file", and the explainer lists "Direct APIs for media containers (muxers/demuxers)" as a non-goal.
- Hardware is a hint. Chrome for Developers says codecs are "often accelerated by hardware"; in the spec,
prefer-hardwareandprefer-softwareare hints, and user agents may proactively reclaim codecs. - Close your frames. Chrome's guidance: failing to release frames "(or waiting for garbage collection) can cause decoding to stall."
- Large files. Decoded frames are uncompressed, so long or high-resolution timelines can exhaust memory if you buffer too much. A common workaround is to edit from lighter proxy files and export from the originals; see Proxy Editing Explained.
- Codec gaps. MDN's codec-selection page notes there is no AAC encoding in Firefox or on desktop Linux, and HEVC encoding has significant gaps outside Apple platforms. Always call
isConfigSupported(). - Fingerprinting. The specification warns of "increased ability to fingerprint users by querying for different codec capabilities", so browsers may limit probing.
WebCodecs vs FFmpeg.wasm vs server-side FFmpeg
WebCodecs uses the browser's own codecs, which can be hardware-accelerated, but it needs a container library and only supports what the browser exposes. FFmpeg.wasm runs software codecs and handles many containers, but its documentation says it won't match native FFmpeg performance, and multithreading needs cross-origin isolation. Server-side FFmpeg is the most complete but costs bandwidth and servers.
| WebCodecs | FFmpeg.wasm | Server-side FFmpeg | |
|---|---|---|---|
| Codecs | The browser's own, hardware-accelerated where available | Software (FFmpeg compiled to WebAssembly) | Anything FFmpeg supports |
| Containers | None built in; add a library | Many | All |
| Speed | Fast where hardware helps | FFmpeg.wasm's own benchmark (Chrome 116, an older core, so treat it as an illustration): native 5.2 s, single-thread 128.8 s, multithread 60.4 s, roughly 25x and 12x slower | Depends on your servers |
| Licensing | Browser API; your libraries' licenses apply | Wrapper is MIT, but the npm core packages are GPL-2.0-or-later builds (--enable-gpl, libx264, libx265) | FFmpeg's LGPL/GPL terms depend on the build |
| Deployment | Secure context; support varies by browser | Multithreading needs SharedArrayBuffer, which needs a cross-origin-isolated secure context; 2 GB input limit | Upload time, storage, cost, privacy |
Because the FFmpeg.wasm core is a GPL build, "If those parts get used the GPL applies to all of FFmpeg", per FFmpeg's legal page. Check licensing before you ship it in a closed-source product.
Which libraries handle MP4 and WebM containers?
Mediabunny is now the main option: MDN names it as such, it is MPL-2.0 licensed and was last released on October 5, 2026 (v1.61.3). The older mp4-muxer and webm-muxer packages are MIT licensed but deprecated on npm in favor of Mediabunny; mp4box.js (BSD-3-Clause) remains maintained for demuxing and web-demuxer (MIT) is another demuxing option.
| Library | Role | License | Latest release or commit seen (Oct 9, 2026) |
|---|---|---|---|
| Mediabunny | Reads and writes media containers | MPL-2.0 | v1.61.3, October 5, 2026 |
| mp4box.js | MP4 parsing and demuxing | BSD-3-Clause | v2.4.1 (June 19, 2026); commit September 23, 2026 |
| web-demuxer | Demuxing | MIT | 4.0.0 (December 20, 2025) |
| mp4-muxer, webm-muxer | Muxing | MIT | v5.2.2 and v5.1.4 (July 2, 2025); npm: "superseded by Mediabunny. Please migrate to it." |
Is WebCodecs private?
WebCodecs itself runs in the user's browser, but whether media leaves the device depends on the application. The spec also notes that probing codec capabilities can aid fingerprinting, so browsers may limit it. An editor with cloud AI features still uploads media for analysis.
We found no WebCodecs-specific statement that processing "stays client-side", so judge privacy by the app's policy, not the API. Loopdesk's FAQ says content is encrypted in transit and at rest and is never used to train AI models. For how that compares with other editors, see Best AI Video Editing Agents in 2026.
Sources
Read and verified on October 9, 2026.
- W3C, "WebCodecs" (Working Draft, October 7, 2026): https://www.w3.org/TR/webcodecs/ · Codec Registry: https://www.w3.org/TR/webcodecs-codec-registry/ · AVC registration: https://www.w3.org/TR/webcodecs-avc-codec-registration/ · Explainer: https://github.com/w3c/webcodecs/blob/main/explainer.md · WebGPU: https://www.w3.org/TR/webgpu/
- MDN, "WebCodecs API" (modified August 12, 2026): https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API · "VideoEncoder: configure() method": https://developer.mozilla.org/en-US/docs/Web/API/VideoEncoder/configure · "Codec selection": https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API/Codec_selection · "Codecs in common media types": https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/codecs_parameter
- MDN browser-compat-data v8.1.5 (October 8, 2026): https://bcd.developer.mozilla.org/bcd/api/v0/current/api.VideoEncoder.json
- web-features "webcodecs" (v3.41.0): https://raw.githubusercontent.com/web-platform-dx/web-features/main/features/webcodecs.yml.dist · caniuse data (September 30, 2026): https://raw.githubusercontent.com/Fyrd/caniuse/main/features-json/webcodecs.json
- Apple, Safari release notes (16.4, 26, 27): https://developer.apple.com/documentation/safari-release-notes · Mozilla, Firefox 130.0 release notes: https://www.mozilla.org/en-US/firefox/130.0/releasenotes/
- Chrome for Developers, "Video processing with WebCodecs" (updated January 22, 2025): https://developer.chrome.com/docs/web-platform/best-practices/webcodecs
- FFmpeg.wasm FAQ and performance pages: https://ffmpegwasm.netlify.app/docs/faq · https://ffmpegwasm.netlify.app/docs/performance · FFmpeg, "License and Legal Considerations": https://ffmpeg.org/legal.html · MDN, "SharedArrayBuffer": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
- Repositories: https://github.com/Vanilagy/mediabunny · https://github.com/Vanilagy/mp4-muxer · https://github.com/Vanilagy/webm-muxer · https://github.com/gpac/mp4box.js · https://github.com/bilibili/web-demuxer
Not verified: the live caniuse.com page (JavaScript-rendered; we used its published data), Firefox for Android after version 130, and ImageDecoder in stable Safari. Older than 12 months: Chrome's article and FFmpeg.wasm's benchmark.
Frequently Asked Questions
Is WebCodecs a W3C standard?
Not yet a final standard. WebCodecs is a W3C Working Draft (latest version published October 7, 2026), and W3C marks it as a work in progress. It is widely implemented, with Chrome and Edge since version 94, but it is not Baseline: availability is still limited, for example no Firefox for Android.
Is WebCodecs supported in Safari and Firefox?
Yes, with caveats. Firefox supports it on desktop from version 130 (not Firefox for Android), and Safari supports video encoding and decoding from 16.4, adding audio from Safari 26. ImageDecoder is the lagging piece: Firefox added it in 133, while Safari offers only a preview.
Does WebCodecs use FFmpeg?
No. WebCodecs calls the codecs built into the browser and operating system. FFmpeg.wasm is a separate approach that compiles FFmpeg to WebAssembly and runs software codecs. Applications can combine them, using WebCodecs where it is supported and FFmpeg.wasm as a fallback.
Can WebCodecs create or read MP4 files?
Not by itself. WebCodecs works with encoded chunks, not files, so you need a library to demux MP4 into chunks and mux encoded chunks back into MP4 or WebM. Mediabunny is MDN's primary option; mp4box.js is a long-standing demuxer.
Does WebCodecs use hardware acceleration?
Often, but it isn't guaranteed. Chrome's documentation says codecs are "often accelerated by hardware", and the spec's hardwareAcceleration setting is a hint (prefer-hardware or prefer-software). Browsers may also reclaim codecs, and hardware encoding support varies by codec and device.
Which codecs does WebCodecs support?
Whatever the browser exposes. H.264 (avc1), VP8, VP9 and AV1 are the common ones, with HEVC on some platforms. Always check with VideoEncoder.isConfigSupported(): AAC encoding, for example, isn't available in Firefox or on desktop Linux, and HEVC encoding has significant gaps outside Apple platforms. For how the codecs themselves compare, see Video Codecs Explained.
How does WebCodecs work with WebGPU?
A VideoFrame can be imported into WebGPU as an external texture, so an editor can composite, color-correct or caption frames on the GPU before encoding. The texture is destroyed when its source frame is closed, so draw first, then close the frame. WebGPU availability varies by browser and operating system.
Building or choosing a browser-based editor? Try Loopdesk: it runs in your browser on WebGPU and WebCodecs with nothing to install. Plans start at $19/month ($15 billed annually).