Video to GIF with WASM

Web Assembly (WASM) opens the door to building high-performance apps in the browser with languages other than JavaScript. Software normally reserved for installed desktop apps can now run in the browser with near-native performance. The following tutorial demonstrates how to use FFmpeg.wasm to perform CPU-intensive video editing tasks from a frontend react app.

Initial Setup

Create a new react app, then install FFmpeg.

command line
npx create-snowpack-app gifmakr --template @snowpack/app-template-react

npm install @ffmpeg/ffmpeg @ffmpeg/core

GIF Maker App

Load FFmpeg

The main binary for FFmpeg is loaded asynchronously via a CDN. Load it when the component is initialized with the useEffect hook.

import React, { useState, useEffect } from 'react';
import './App.css';

import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
const ffmpeg = createFFmpeg({ log: true });

function App() {
  const [ready, setReady] = useState(false);

  const load = async () => {
    await ffmpeg.load();

  useEffect(() => {
  }, [])

  return ready ? () : ( <p>Loading...</p> );

export default App;

Preview the Video File

Use a file input to collect a video file, then convert it to a URL with URL.createObjectURL so it can be used in video element.

function App() {
  const [video, setVideo] = useState();

  return ready ? (
      <div className="App">

        { video && <video


        <input type="file" onChange={(e) => setVideo(} />


  ) : ( <p>Loading...</p> );

export default App;

Convert a Video to GIF

First, the convertToGif function below saves the video file to MEMFS where it can be used by FFmpeg.

Next, it runs a command to perform various video editing and encoding tasks. View the official FFmpeg docs for a breakdown of available options.

Lastly, it reads the result and generates a URL where it can be viewed in the browser.

function App() {

  const [gif, setGif] = useState();

  const convertToGif = async () => {
    // Write the file to memory 
    ffmpeg.FS('writeFile', 'test.mp4', await fetchFile(video));

    // Run the FFMpeg command
    await'-i', 'test.mp4', '-t', '2.5', '-ss', '2.0', '-f', 'gif', 'out.gif');

    // Read the result
    const data = ffmpeg.FS('readFile', 'out.gif');

    // Create a URL
    const url = URL.createObjectURL(new Blob([data.buffer], { type: 'image/gif' }));

  return (

      <button onClick={convertToGif}>Convert</button>

      { gif && <img src={gif} width="250" />}


export default App;

Q&A Chat