Compile FFmpeg to WebAssembly with Emscripten
Compiling FFmpeg to WebAssembly (WASM) allows you to perform client-side audio and video processing, transcoding, and filtering directly inside a web browser without dedicated server resources. This guide walks through setting up the Emscripten SDK, configuring FFmpeg source code with WebAssembly-compatible build flags, compiling the libraries, and exporting the final JavaScript and WASM artifacts.
1. Prerequisites and Environment Setup
To compile FFmpeg to WASM, you need a Unix-like environment (Linux,
macOS, or WSL on Windows) equipped with git,
make, pkg-config, and Python.
First, install and activate the Emscripten SDK (emsdk):
# Clone the Emscripten repository
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
# Download and install the latest SDK tools
./emsdk install latest
# Set up the SDK in the current shell
./emsdk activate latest
source ./emsdk_env.sh2. Download FFmpeg Source Code
Clone the official FFmpeg repository. It is recommended to check out
a stable release branch (such as n6.1 or n7.0)
rather than the unstable master branch.
git clone https://github.com/FFmpeg/FFmpeg.git
cd FFmpeg
git checkout n6.13. Configure FFmpeg for Emscripten
FFmpeg requires specific compilation flags to target WebAssembly.
Native assembly optimizations, multi-threading (unless specifically
configured with pthreads), and hardware acceleration must
be disabled.
Use emconfigure to run FFmpeg's configure
script:
emconfigure ./configure \
--target-os=none \
--arch=x86_32 \
--enable-cross-compile \
--disable-x86asm \
--disable-inline-asm \
--disable-stripping \
--disable-programs \
--disable-doc \
--disable-all \
--enable-avcodec \
--enable-avformat \
--enable-avutil \
--enable-swresample \
--enable-swscale \
--enable-demuxer=mov,matroska,mp3,wav \
--enable-decoder=h264,aac,mp3,pcm_s16le \
--enable-protocol=file \
--cc="emcc" \
--cxx="em++" \
--ar="emar" \
--ranlib="emranlib" \
--nm="emnm" \
--extra-cflags="-O3"Key configuration options:
--disable-all: Strips all features to keep the binary small. Enable only the specific demuxers, decoders, and filters your application requires.--disable-x86asmand--disable-inline-asm: Disables CPU-specific assembly instructions incompatible with WASM.--cc="emcc": Directs the build system to use Emscripten's C compiler.
4. Build Static Libraries
Run emmake make to build the core FFmpeg static
libraries (.a files):
emmake make -j$(nproc)Upon completion, static libraries like
libavcodec/libavcodec.a,
libavformat/libavformat.a, and
libavutil/libavutil.a will be generated in their respective
directories.
5. Link Libraries into WASM and JavaScript
To generate the .wasm file and its JavaScript loader,
compile a C entry point or link the static libraries directly using
emcc.
Here is an example command to link the static libraries into a standalone WebAssembly module with Emscripten's virtual filesystem:
emcc -O3 \
-s WASM=1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s INITIAL_MEMORY=67108864 \
-s EXPORTED_RUNTIME_METHODS='["FS", "cwrap", "ccall"]' \
-s MODULARIZE=1 \
-s EXPORT_NAME="createFFmpegCore" \
libavformat/libavformat.a \
libavcodec/libavcodec.a \
libswresample/libswresample.a \
libswscale/libswscale.a \
libavutil/libavutil.a \
-o ffmpeg-core.jsCompilation flags explained:
-s WASM=1: Emits WebAssembly instead of asm.js.-s ALLOW_MEMORY_GROWTH=1: Dynamically increases WASM memory when loading large files.-s INITIAL_MEMORY=67108864: Allocates an initial 64MB of heap memory.-s MODULARIZE=1: Encapsulates output in a closure returning a Promise.-o ffmpeg-core.js: Producesffmpeg-core.jsandffmpeg-core.wasm.
6. Using the Output in the Browser
Import the generated JavaScript file into your web application to initialize the module:
<script src="ffmpeg-core.js"></script>
<script>
createFFmpegCore().then((Module) => {
console.log("FFmpeg WASM loaded successfully");
// You can now interact with the Emscripten FS API
// Module.FS.writeFile('input.mp4', data);
});
</script>