Libav.js
This is a compilation of the libraries associated with handling audio and video in ffmpeg—libavformat, libavcodec, libavfilter, libavutil, libswresample, and libswscale—for emscripten, and thus the web.
Install / Use
/learn @Yahweasel/Libav.jsREADME
libav.js
This is a compilation of the libraries associated with handling audio and video
in FFmpeg—libavformat, libavcodec, libavfilter, libavutil and libswresample—for
WebAssembly and asm.js, and thus the web, as well as the ffmpeg and ffprobe
CLIs themselves. It is compiled via emscripten, is highly customizable, and has
a ruthless commitment to correct licensing.
In short, this is a pure JavaScript and WebAssembly system for low-level audio and video encoding, decoding, muxing, demuxing, and filtering.
FFmpeg is released under the LGPL. Therefore, if you distribute this library,
you must provide sources. The sources are included in the sources/ directory
of the compiled version of libav.js.
In order to reduce license-header Hell, the small amount of wrapper functions provided by libav.js are all released under the so-called “0-clause BSD” license, which does not require that the license text itself appear in derivative works. Built libraries have their correct license headers.
This file is the main README for using and building libav.js, and should be sufficient for many users. More detail on specific concepts is provided in other files:
-
API.md describes the libav.js-specific parts of the API.
-
CONFIG.md describes the configuration system and how to create your own configuration of libav.js.
-
IO.md describes the various I/O modes provided by libav.js.
-
TESTS.md describes the testing framework.
Using libav.js
libav.js builds are available on
GitHub and in NPM. Include
dist/libav-version-variant.js to use libav.js. The variants are discussed
below.
The simplest way to use libav.js is to include it from a CDN. libav.js uses Web Workers by default, and Web Workers cannot be loaded from a different origin, so if you load it from a CDN, you must disable its own loading of workers. As such, it's only recommended to use libav.js from a CDN if you're already in a worker, and thus don't need sub-workers. Nonetheless, the following is a simple example of using libav.js from a CDN in the browser thread:
<!doctype html>
<html>
<body>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@libav.js/variant-default@6.8.8/dist/libav-6.8.8.0-default.js"></script>
<script type="text/javascript">(async function() {
const libav = await LibAV.LibAV({noworker: true});
await libav.writeFile("tmp.opus", new Uint8Array(
await (await fetch("exa.opus")).arrayBuffer()
));
const [fmt_ctx, [stream]] = await libav.ff_init_demuxer_file("tmp.opus");
const [, c, pkt, frame] = await libav.ff_init_decoder(stream.codec_id, stream.codecpar);
const [, packets] = await libav.ff_read_multi(fmt_ctx, pkt);
const frames = await libav.ff_decode_multi(c, pkt, frame, packets[stream.index], true);
alert(`Got ${frames.length} audio frames!`);
})();
</script>
</body>
</html>
Here's a better example, using libav.js locally:
<!doctype html>
<html>
<body>
<script type="text/javascript" src="libav-6.8.8.0-default.js"></script>
<script type="text/javascript">(async function() {
const libav = await LibAV.LibAV();
await libav.writeFile("tmp.opus", new Uint8Array(
await (await fetch("exa.opus")).arrayBuffer()
));
const [fmt_ctx, [stream]] = await libav.ff_init_demuxer_file("tmp.opus");
const [, c, pkt, frame] = await libav.ff_init_decoder(stream.codec_id, stream.codecpar);
const [, packets] = await libav.ff_read_multi(fmt_ctx, pkt);
const frames = await libav.ff_decode_multi(c, pkt, frame, packets[stream.index], true);
alert(`Got ${frames.length} audio frames!`);
})();
</script>
</body>
</html>
It's also possible to use libav.js from Node.js, though this isn't a good idea, since you can presumably use a native version of FFmpeg's libraries. The Node interface is only provided for internal testing.
Use .dbg.js instead of .js for a non-minified, more debuggable version. Use
.mjs for the ES6 module version. Use .dbg.mjs for both. You don't need any
combination; e.g., if you only intend to use imports, you do not need any .js
files.
libav.js exposes a global variable, LibAV, for all API access. If importing as a
module, LibAV is the default export.
For certain unusual loading situations, you can set the LibAV global variable
before importing. In particular, if the base directory (directory in which
libav's files are located) can't be detected for some reason, then you must set
LibAV.base to the correct base. LibAV.base does not need to be a full URL,
but should be if loading from another origin.
Bundlers have further concerns. To use libav.js with a bundler, see the section on bundlers below.
LibAV.LibAV is a factory function which returns a promise which resolves to a
ready instance of libav. The factory function and libav instance methods are
documented in API.md.
Which files do I need?
You need the main entry file and at least one target, for a minimum of three files, but you should probably include several others.
The main entry file is named as follows: libav-<version>-<variant>.js. You
only need the variant you intend to use. The debug version is named
libav-<version>-<variant>.dbg.js, and you can use that in place of the
original, but it is not required. If using ES6 modules, use mjs in place of
js.
That entry file will load a target based on the environment it's loaded in and
the options used to load it, as described above. The supported targets are
asm.js, plain WebAssembly, and threaded WebAssembly. It is harmless to include
all of them, as users will not download all of them, only the ones they use.
But, you may also include only those you intend to use. In every case, there is
a .dbg.js equivalent which is only needed if you intend to use debug mode.
-
asm.js: Named
libav-<version>-<variant>.asm.js. No modern browser excludes support for WebAssembly, so this is probably not necessary. -
Plain WebAssembly: Named
libav-<version>-<variant>.wasm.jsandlibav-<version>-<variant>.wasm.wasm. Used in most situations. -
Threaded WebAssembly: Named
libav-<version>-<variant>.thr.js,.thr.wasm, and.thr.worker.js. Used only when threading is supported by the browser andyesthreadsis set. If you don't intend to use threads (setyesthreads), it is safe to exclude this. Used only when threads are activated and supported.
At a minimum, it is usually sufficient to include only the .js, .wasm.js,
and .wasm.wasm files. To include threads, you must also include .thr.js and
.thr.wasm. Again, use mjs instead of js if using ES6 imports.
The file libav.types.d.ts is a TypeScript types definition file, and is only
needed to compile TypeScript code with support for libav.js's types. It should
never be necessary to distribute.
Note that, independently of what files are available to end users, you are
contractually obligated to release the source code of libav.js and all of its
dependencies if you provide the compiled version. If you are using a compiled,
released version, it is sufficient to provide the sources directory.
libav.js is published to NPM as libav.js, and each released variant is
published in a much smaller NPM package as @libav.js/variant-<variant>. The
CDN example above uses the @libav.js/variant-default package, for example. The
@libav.js/types package is also provided with only the types (.d.ts file),
and if using TypeScript, you are highly recommended to use it, to avoid bringing
entire variants in as dependencies of your own packages.
Why the version number in the filenames?
Caching is Hell.
libav-<variant>.* is also available in the releases and repository, but you're
highly recommended not to use this name on any web installation, as caching
will cause strange nonsense to happen. Use a full versioned name to avoid
caching madness.
Devices and asynchrony
Emscripten's implementation of an in-memory filesystem has severe limitations.
You're recommended to use virtual devices, implemented by libav.js, for most
I/O. See IO.md for more details. libav.js itself imposes no
restriction on file sizes so long as you use asynchronous, device-backed I/O
(thus, the only restriction to size is JavaScript's number type).
ffmpeg was never designed to work asynchronously, and was only designed to work with blocking I/O. Still, it's possible to use libav.js with asynchronous input through these devices.
TypeScript
Type definitions for libav.js are provided by libav.types.d.ts. You can
either copy this file and import it:
import type LibAVJS from "./libav.types";
declare let LibAV: LibAVJS.LibAVWrapper;
or import it from the npm package:
import type LibAVJS from "libav.js";
declare let LibAV: LibAVJS.LibAVWrapper;
Variants and Building libav.js
With all of its bells and whistles enabled, FFmpeg is pretty large. So, I disable most bells and most whistles and build specific versions with specific features.
The default variant, libav-<version>-default.js, includes support for the most
important (and timeless) audio codecs and formats: Opus, FLAC, and wav, in WebM,
ogg, FLAC, or wav containers. It also has a set of common audio filters.
Built-in variants are created by combining “configuration fragments”. You can find more on configuration fragments or making your own variants in CONFIG.md.
Use make build-<variant>, replacing <variant> with the variant name, to
build another variant.
Most of the variants provided in the repository are also built and
Related Skills
docs-writer
98.6k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
328.4kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
Design
Campus Second-Hand Trading Platform \- General Design Document (v5.0 \- React Architecture \- Complete Final Version)1\. System Overall Design 1.1. Project Overview This project aims t
arscontexta
2.8kClaude Code plugin that generates individualized knowledge systems from conversation. You describe how you think and work, have a conversation and get a complete second brain as markdown files you own.
