ffmpeg-web is a browser-friendly wrapper around an FFmpeg WebAssembly build. It manages loading FFmpeg into the browser at runtime, providing a convenient interface to run FFmpeg commands, handle progress events, and interact with the virtual filesystem (FS).
Status: Alpha / WIP – This library is under active development. Expect potential changes to APIs or build scripts.
- Dynamic Loading: Load FFmpeg lazily by inserting a
<script>tag or using a known CDN URL. - Progress & Logging Hooks: Listen for FFmpeg progress updates (
progress,time) and logging (stdout/stderr) in real time. - FS Operations: Create directories, read/write files, check file existence, etc., within FFmpeg’s virtual filesystem.
- Worker-Based: Internally uses a web worker to offload FFmpeg operations from the main thread.
- Customizable: Provide your own
.wasmand.jsbuild if needed.
(TBD: Provide instructions if/when you publish on npm or require local usage. For now, you can include it via script tag from a static server or local build.)
<script src="https://lab.geen.ee/geenee-ffmpeg/index.js"></script>
<script>
// After the script loads, window.FFmpegWeb.FFmpeg is available
const { FFmpeg } = window.FFmpegWeb;
const ffmpeg = new FFmpeg();
// ...
</script># Clone or download this repo
# Build / compile
# Serve the dist and reference index.js from your local server
<script src="http://localhost:3000/dist/index.js"></script>Below is a minimal snippet showing how to initialize FFmpeg in the browser and run a command:
// 1) Dynamically load the ffmpeg-web script
await loadScript('https://lab.geen.ee/geenee-ffmpeg/index.js');
// => This sets window.FFmpegWeb
// 2) Create FFmpeg instance
const { FFmpeg } = window.FFmpegWeb;
const ffmpeg = new FFmpeg();
// 3) Load the core
await ffmpeg.load();
// 4) Listen to progress or log events if desired
ffmpeg.on('progress', ({ progress, time }) => {
console.log('FFmpeg progress:', progress, time);
});
ffmpeg.on('log', ({ type, message }) => {
console.log(`[FFmpeg ${type}]`, message);
});
// 5) Run a command – e.g. check version
const result = await ffmpeg.exec(['-version']);
console.log('FFmpeg version output:', result);This approach:
- Loads the ffmpeg-web script from a CDN.
- Instantiates the FFmpeg class.
- Calls .load() to initialize the worker & WASM core.
- Executes commands like exec(['-i', 'file', ...]).
If you have your own .wasm or .js build (e.g., from the Docker scripts or custom config), you can specify those URLs:
// ...
await loadScript('https://example.com/my-ffmpeg-build/index.js');
const { FFmpeg } = window.FFmpegWeb;
const ffmpeg = new FFmpeg();
await ffmpeg.load({
coreURL: 'https://example.com/my-ffmpeg-build/core.js',
wasmURL: 'https://example.com/my-ffmpeg-build/ffmpeg.wasm',
});Creates an instance of the FFmpeg wrapper.
Initializes the internal worker and loads the FFmpeg core. Returns a promise that resolves to a boolean indicating success.
options.coreURL: (string) URL to the FFmpeg.jscore (if needed).options.wasmURL: (string) URL to the.wasmbinary.
async load(options?: { coreURL?: string; wasmURL?: string }): Promise<boolean>Runs an FFmpeg command with the provided arguments (e.g., ['-version'], ['-i', 'input.mp4', 'output.webm']). Returns a promise with any stdout/stderr output aggregated (if available).
async exec(args: string[]): Promise<any>createDir(path: string)writeFile(path: string, data: Uint8Array)readFile(path: string): Uint8ArraydeleteFile(path: string)listFiles(path: string): string[]fileExists(path: string): boolean
These methods let you manipulate the in-memory filesystem:
await ffmpeg.createDir('/working');
await ffmpeg.writeFile('/working/sample.txt', myData);
const result = await ffmpeg.readFile('/working/sample.txt');
console.log(new TextDecoder().decode(result));ffmpeg.on(event, callback)
ffmpeg.off(event, callback)
log: Receives object{ type, message }describing FFmpeg’s stdout/stderr logs.progress: Receives object{ progress, time }, typically from internal FFmpeg progress logs.
ffmpeg.on('log', ({ type, message }) => {
console.log(`[${type}]`, message);
});
ffmpeg.on('progress', ({ progress, time }) => {
console.log('Progress update:', progress, time);
});.
├── apps
│ └── ffmpeg-html # Example app to test FFmpeg in browser
├── packages
│ ├── core # The main "ffmpeg-web" wrapper code
│ └── wasm # Scripts & Dockerfiles for building custom WASM
├── package.json
├── tsconfig.json
└── ...Inside packages/wasm/config, you’ll find scripts like config-n-build.sh and generate-wasm.sh which:
- Configure FFmpeg for Emscripten.
- Compile to
.wasm+.jswith the needed flags.
To run:
cd packages/wasm/config
./config-n-build.sh
./generate-wasm.sh(Requires Emscripten toolchain, Docker usage optional.)
- Clone this repository.
- Install dependencies:
npm installoryarn. - Build: Check the build steps in
core/webpack.config.jsor your bundler config. - Run: There may be an example under
apps/ffmpeg-htmlyou can serve withnode server.js.
- Add Docker Workflow: Provide a single
docker run ...that outputs.wasm+.js. - Publish on npm: So developers can import
ffmpeg-webas a regular npm package. - Improve TS Declarations: Provide
.d.tsfor advanced usage.
- FFmpeg for the underlying technology.
- Emscripten for compiling C/C++ to WebAssembly.
- All external libraries and resources used in building this project.