How to Build FFmpeg WebAssembly on Ubuntu 24.04 Linux (Step-by-Step)

Heyan Maurya
10 Min Read

FFmpeg stands out when it comes to an open-source library for multimedia processing, handling video transcoding, and audio manipulation across various applications. WebAssembly (WASM), on the other hand, allows code written in C/C++ to run in web browsers at near-native speed.

Most of the time, we use it traditionally, confined to server-side operations; however, with the rise of WebAssembly, it has opened exciting possibilities for bringing FFmpeg’s power directly into web browsers.

If you’re looking to build FFmpeg WebAssembly in Ubuntu 24.04 Linux then we have listed quick steps which can help the beginners to install the dependencies and with commands that are required to test the FFmpeg WebAssembly.

Prerequisites for FFmpeg WebAssembly Build

FFmpeg WebAssembly build process on Ubuntu 24.04, we need to ensure our system meets the following requirements:

Your Ubuntu 24.04 LTS system should be fresh or fully updated, with at least 8 GB of RAM and 10 GB of free disk space for the compilation process.

Essential development tools include Git for source code management, Python 3 for build scripts, CMake for cross-platform builds, and curl or wget for downloading dependencies, which we will learn how to install in this article.

What is the need to Build FFmpeg to WebAssembly?

Here’s why you may want to compile FFmpeg to WebAssembly:

  • Run FFmpeg directly in the browser without server dependencies.
  • Enable client-side video/audio processing.
  • Build offline-capable web apps for media editing or playback.
  • Improve speed and interactivity in browser-based tools.

Step 1: Update Your System

Let’s as regular practice before starting any installation on Ubuntu Linux, update your system using the give command.

sudo apt update && sudo apt upgrade -y

Step 2: Install Required Packages

Next, there are some tools and packages we required to build a tool, all of them are available right in the default system repository of

sudo apt install -y git cmake build-essential python3 python3-pip autoconf automake libtool pkg-config yasm nasm

Step 3: Install Emscripten SDK (emcc compiler)

Emscripten is a toolchain that compiles C/C++ code into WebAssembly (.wasm). If you don’t know emcc is the compiler (like gcc, but for WebAssembly), hence we need to install to build ffmpeg for WebAssembly.

Clone it from its latest repository:

git clone https://github.com/emscripten-core/emsdk.git

Once done switch to the downloaded repo folder:

cd emsdk

After that install and activate the latest version of Emscripten.

./emsdk install latest

./emsdk activate latest

Adds Emscripten tools to your terminal session, so that later we can use emcc command from anywhere in our command temrinal.

source ./emsdk_env.sh 

Also add the bin directory to your path because we have to done that manually in our case.

echo 'export PATH=$HOME/emsdk/upstream/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

Make sure emcc is available:

emcc -v

Also , check if llvm-nm Is Available

which llvm-nm

You should see something like:

/home/ubuntu/emsdk/upstream/bin/llvm-nm

Step 4: Clone FFmpeg Source

Now, we need to download the FFmpeg C/C++ source code to compile it into WASM which can be get easily from its official Git repo, this will also ensures we’re using the latest or most stable version.

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg-wasm

Swtich to created directory:

cd ffmpeg-wasm

Step 5: Configure FFmpeg for WebAssembly

This step configures FFmpeg to be compatible with WebAssembly:

  • --cc=emcc: Use Emscripten compiler.
  • --disable-x86asm: WebAssembly doesn’t support CPU-specific assembly like x86.
  • --disable-*: Strip out everything you don’t need to reduce size and avoid unsupported modules.
  • --enable-*: Only include the codecs, formats, and filters that are required by your use case (e.g., decoding MP3, H.264 videos).
  • llvm-nm to parse .o files generated by emcc.

You can tweak the --enable-* list depending on what media formats you want to support in your browser app.

emconfigure ./configure \
  --cc=emcc \
  --ar=emar \
  --ranlib=emranlib \
  --nm=llvm-nm \
  --target-os=none \
  --arch=x86_32 \
  --disable-x86asm \
  --disable-inline-asm \
  --disable-programs \
  --disable-doc \
  --disable-network \
  --disable-everything \
  --enable-demuxer=wav \
  --enable-decoder=pcm_s16le \
  --enable-muxer=wav \
  --enable-encoder=pcm_s16le \
  --enable-protocol=file

Step 6: Compile FFmpeg to WebAssembly

This command compiles the C source code into .o object files using Emscripten.

  • emmake wraps the standard make tool so it knows to use emcc, emar, etc.
  • -j$(nproc) uses all CPU cores for faster compilation.

This will generate a lot of .o files in subdirectories like libavcodec/, libavformat/, etc.

emmake make -j$(nproc)

Once done, check the current folder has – ffmpeg.js and ffmpeg.wasm files or not.

ls 

If you don’t have these two files then we need to create them manually using ffmpeg_wrapper.c.

Explanation: WebAssembly runs a main function. You need a small wrapper that acts as an entry point and can be called from JavaScript. Even if you don’t use it to process files, it’s a good way to initialize the module.

nano ffmpeg_wrapper.c

Add this code and save the file. Use Ctrl+X, Y and Enter keys to save and exit nano text editor.

#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>

int main() {
    printf("FFmpeg WASM module initialized.\n");
    fflush(stdout); // <-- ADD THIS
    return 0;
}

Step 7: Compile the Final WASM Binary

You’re now linking all the compiled FFmpeg object files into a final WebAssembly module:

This command will generate:

  • ffmpeg.wasm: WebAssembly binary
  • ffmpeg.js: JavaScript glue code
  • ffmpeg.data (if needed): any memory initialization
emcc -O3 \
  -s MODULARIZE=1 \
  -s EXPORT_NAME="FFmpegModule" \
  -s EXPORTED_FUNCTIONS="['_main']" \
  -s EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" \
  ffmpeg_wrapper.c \
  -I. \
  ./libavcodec/*.o ./libavformat/*.o ./libavutil/*.o \
  ./libswresample/*.o ./libswscale/*.o \
  -o ffmpeg.js

Pro Tip (for real-world use)

If you want to use FFmpeg-WASM in real apps (e.g., to decode/encode audio/video), then instead of building from scratch, you can:

✅ Use existing projects like: They’re pre-built, optimized, and offer rich APIs.

Step 8: Test FFmpeg WebAssembly in Browser

To verify the compiled FFmpeg WebAssembly is working in a browser. Lets create a test file, for that inside your current folder which “ffmpeg-wasm“, create an index.html file and paste the code given in this step:

nano index.html

Paste these lines and save the file by pressing Ctrl+X, Y and hit the Enter key.

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>FFmpeg WASM Status</title>
</head>
<body>
  <h1>FFmpeg WebAssembly Status</h1>
  <div id="status">Checking FFmpeg WASM...</div>

  <script>
    document.getElementById('status').innerText = "Loading local FFmpeg WASM...>

    // Ensure ffmpeg.js was compiled with Emscripten MODULARIZE=1 and EXPORT_NA>
    const ffmpegScript = document.createElement('script');
    ffmpegScript.src = 'ffmpeg.js';
    ffmpegScript.onload = () => {
      FFmpegModule().then((Module) => {
        console.log("✅ Local FFmpeg WASM loaded.");
        document.getElementById('status').innerText = "✅ FFmpeg WASM loaded fr>
      }).catch(err => {
        console.error("❌ Error loading FFmpeg:", err);
        document.getElementById('status').innerText = "❌ Failed to load FFmpeg>
      });
    };
    document.body.appendChild(ffmpegScript);
  </script>
</body>
</html>

Run Python web server to quickly test FFmpeg WebAssembly:

python3 -m http.server 8000

Now, open your browser and point to local address:

http://localhost:8000

You will have something like shown in the given screenshot saying: FFmpeg WASM loaded from local build.

FFmpeg WebAssembly build status in Ubuntu 24.04 Linux

Conclusion

Building FFmpeg WebAssembly on Ubuntu 24.04 opens up powerful possibilities for browser-based media processing. You’ve successfully navigated the entire process from setting up the development environment to creating optimized WebAssembly modules.

Your next steps might include integrating this build into frontend applications, experimenting with different codec configurations, or exploring advanced WebAssembly features like SharedArrayBuffer for improved performance. So, keep experimenting.

FAQ

Can I enable full codec support?

Yes, but be aware that enabling all codecs significantly increases the WebAssembly file size. Selectively enable only the codecs you need using --enable-encoder= and --enable-decoder= flags during configuration.

Can this run in any browser?

FFmpeg WebAssembly runs in all modern browsers that support WebAssembly, including Chrome, Firefox, Safari, and Edge. However, performance may vary between browsers, and some advanced features might have limited support.

What’s the difference between ffmpeg.wasm and a custom build?

A custom build allows you to control exactly which features are included, optimize for your specific use case, and potentially achieve smaller file sizes. Pre-built ffmpeg.wasm offers convenience but may include features you don’t need.

Is it safe to use FFmpeg WASM in production?

FFmpeg WebAssembly can be used in production, but consider factors like file size, loading time, and browser compatibility. Implement proper error handling and fallback mechanisms for unsupported browsers or failed loads.

How do I update my FFmpeg WebAssembly build?

To update, pull the latest FFmpeg source code, update your emsdk installation, and rebuild using the same configuration. Test thoroughly after updates to ensure compatibility with your application.

Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.