@voyagerx/libav.js 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,15 @@
1
+ LGPL.
2
+
3
+ The license text for this code is in the source files.
4
+ [LICENSE files do more harm than good](https://yahweasel.github.io/license-files-considered-harmful/).
5
+
6
+ This file exists because some people expect it to be here.
7
+
8
+ libav.js builds include correct license headers. Do not remove them.
9
+
10
+ If you make modifications to this repository beyond configuration changes¹ and
11
+ distribute builds with those changes, you are *legally obligated* to share those
12
+ changes. If you do not, you are in violation of FFmpeg's license terms. I'm
13
+ looking at you, “my startup is too cool to read licenses” scumbags.
14
+
15
+ ¹ i.e., changes that link to FFmpeg.
package/README.md ADDED
@@ -0,0 +1,410 @@
1
+ # libav.js
2
+
3
+ This is a compilation of the libraries associated with handling audio and video
4
+ in FFmpeg—libavformat, libavcodec, libavfilter, libavutil and libswresample—for
5
+ WebAssembly and asm.js, and thus the web, as well as the `ffmpeg` and `ffprobe`
6
+ CLIs themselves. It is compiled via emscripten, is highly customizable, and has
7
+ a ruthless commitment to correct licensing.
8
+
9
+ In short, this is a pure JavaScript and WebAssembly system for low-level audio
10
+ and video encoding, decoding, muxing, demuxing, and filtering.
11
+
12
+ FFmpeg is released under the LGPL. Therefore, if you distribute this library,
13
+ you must provide sources. The sources are included in the `sources/` directory
14
+ of the compiled version of libav.js.
15
+
16
+ In order to reduce license-header Hell, the small amount of wrapper functions
17
+ provided by libav.js are all released under the so-called “0-clause BSD”
18
+ license, which does not require that the license text itself appear in
19
+ derivative works. Built libraries have their correct license headers.
20
+
21
+ This file is the main README for using and building libav.js, and should be
22
+ sufficient for many users. More detail on specific concepts is provided in other
23
+ files:
24
+
25
+ * [API.md](docs/API.md) describes the libav.js-specific parts of the API.
26
+
27
+ * [CONFIG.md](docs/CONFIG.md) describes the configuration system and how to
28
+ create your own configuration of libav.js.
29
+
30
+ * [IO.md](docs/IO.md) describes the various I/O modes provided by libav.js.
31
+
32
+ * [TESTS.md](docs/TESTS.md) describes the testing framework.
33
+
34
+
35
+ ## Using libav.js
36
+
37
+ libav.js builds are available on
38
+ [GitHub](https://github.com/Yahweasel/libav.js/releases) and in NPM. Include
39
+ dist/libav-`version`-`variant`.js to use libav.js. The variants are discussed
40
+ below.
41
+
42
+ The simplest way to use libav.js is to include it from a CDN. libav.js uses Web
43
+ Workers by default, and Web Workers cannot be loaded from a different origin, so
44
+ if you load it from a CDN, you must disable its own loading of workers. As such,
45
+ it's only recommended to use libav.js from a CDN if you're already *in* a
46
+ worker, and thus don't need sub-workers. Nonetheless, the following is a simple
47
+ example of using libav.js from a CDN in the browser thread:
48
+
49
+ ```html
50
+ <!doctype html>
51
+ <html>
52
+ <body>
53
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@libav.js/variant-default@6.4.7/dist/libav-6.4.7.1-default.js"></script>
54
+ <script type="text/javascript">(async function() {
55
+ const libav = await LibAV.LibAV({noworker: true});
56
+ await libav.writeFile("tmp.opus", new Uint8Array(
57
+ await (await fetch("exa.opus")).arrayBuffer()
58
+ ));
59
+ const [fmt_ctx, [stream]] = await libav.ff_init_demuxer_file("tmp.opus");
60
+ const [, c, pkt, frame] = await libav.ff_init_decoder(stream.codec_id, stream.codecpar);
61
+ const [, packets] = await libav.ff_read_multi(fmt_ctx, pkt);
62
+ const frames = await libav.ff_decode_multi(c, pkt, frame, packets[stream.index], true);
63
+ alert(`Got ${frames.length} audio frames!`);
64
+ })();
65
+ </script>
66
+ </body>
67
+ </html>
68
+ ```
69
+
70
+ Here's a better example, using libav.js locally:
71
+
72
+ ```html
73
+ <!doctype html>
74
+ <html>
75
+ <body>
76
+ <script type="text/javascript" src="libav-6.4.7.1-default.js"></script>
77
+ <script type="text/javascript">(async function() {
78
+ const libav = await LibAV.LibAV();
79
+ await libav.writeFile("tmp.opus", new Uint8Array(
80
+ await (await fetch("exa.opus")).arrayBuffer()
81
+ ));
82
+ const [fmt_ctx, [stream]] = await libav.ff_init_demuxer_file("tmp.opus");
83
+ const [, c, pkt, frame] = await libav.ff_init_decoder(stream.codec_id, stream.codecpar);
84
+ const [, packets] = await libav.ff_read_multi(fmt_ctx, pkt);
85
+ const frames = await libav.ff_decode_multi(c, pkt, frame, packets[stream.index], true);
86
+ alert(`Got ${frames.length} audio frames!`);
87
+ })();
88
+ </script>
89
+ </body>
90
+ </html>
91
+ ```
92
+
93
+ It's also possible to use libav.js from Node.js, though this isn't a good idea,
94
+ since you can presumably use a native version of FFmpeg's libraries. The Node
95
+ interface is only provided for internal testing.
96
+
97
+ Use `.dbg.js` instead of `.js` for a non-minified, more debuggable version. Use
98
+ `.mjs` for the ES6 module version. Use `.dbg.mjs` for both. You don't need any
99
+ combination; e.g., if you only intend to use imports, you do not need any `.js`
100
+ files.
101
+
102
+ libav.js exposes a global variable, `LibAV`, for all API access. If importing as a
103
+ module, `LibAV` is the default export.
104
+
105
+ For certain unusual loading situations, you can set the `LibAV` global variable
106
+ before importing. In particular, if the base directory (directory in which
107
+ libav's files are located) can't be detected for some reason, then you must set
108
+ `LibAV.base` to the correct base. `LibAV.base` does not need to be a full URL,
109
+ but should be if loading from another origin.
110
+
111
+ Bundlers have further concerns. To use libav.js with a bundler, see the section
112
+ on bundlers below.
113
+
114
+ `LibAV.LibAV` is a factory function which returns a promise which resolves to a
115
+ ready instance of libav. The factory function and libav instance methods are
116
+ documented in [API.md](docs/API.md).
117
+
118
+
119
+ ## Which files do I need?
120
+
121
+ You need the main entry file and at least one target, for a minimum of three
122
+ files, but you should probably include several others.
123
+
124
+ The main entry file is named as follows: `libav-<version>-<variant>.js`. You
125
+ only need the variant you intend to use. The debug version is named
126
+ `libav-<version>-<variant>.dbg.js`, and you can use that in place of the
127
+ original, but it is not required. If using ES6 modules, use `mjs` in place of
128
+ `js`.
129
+
130
+ That entry file will load a target based on the environment it's loaded in and
131
+ the options used to load it, as described above. The supported targets are
132
+ asm.js, plain WebAssembly, and threaded WebAssembly. It is harmless to include
133
+ all of them, as users will not download all of them, only the ones they use.
134
+ But, you may also include only those you intend to use. In every case, there is
135
+ a `.dbg.js` equivalent which is only needed if you intend to use debug mode.
136
+
137
+ * asm.js: Named `libav-<version>-<variant>.asm.js`. No modern browser excludes
138
+ support for WebAssembly, so this is probably not necessary.
139
+
140
+ * Plain WebAssembly: Named `libav-<version>-<variant>.wasm.js` and
141
+ `libav-<version>-<variant>.wasm.wasm`. Used in most situations.
142
+
143
+ * Threaded WebAssembly: Named `libav-<version>-<variant>.thr.js`, `.thr.wasm`,
144
+ and `.thr.worker.js`. Used only when threading is supported by the browser
145
+ *and* `yesthreads` is set. If you don't intend to use threads (set
146
+ `yesthreads`), it is safe to exclude this. Used only when threads are
147
+ activated and supported.
148
+
149
+ At a minimum, it is usually sufficient to include only the `.js`, `.wasm.js`,
150
+ and `.wasm.wasm` files. To include threads, you must also include `.thr.js` and
151
+ `.thr.wasm`. Again, use `mjs` instead of `js` if using ES6 imports.
152
+
153
+ The file `libav.types.d.ts` is a TypeScript types definition file, and is only
154
+ needed to compile TypeScript code with support for libav.js's types. It should
155
+ never be necessary to distribute.
156
+
157
+ Note that, independently of what files are available to end users, *you are
158
+ contractually obligated to release the source code of libav.js and all of its
159
+ dependencies* if you provide the compiled version. If you are using a compiled,
160
+ released version, it is sufficient to provide the `sources` directory.
161
+
162
+ libav.js is published to NPM as `libav.js`, and each released variant is
163
+ published in a much smaller NPM package as `@libav.js/variant-<variant>`. The
164
+ CDN example above uses the `@libav.js/variant-default` package, for example.
165
+
166
+ ### Why the version number in the filenames?
167
+
168
+ Caching is Hell.
169
+
170
+ `libav-<variant>.*` is also available in the releases and repository, but you're
171
+ highly recommended *not* to use this name on any web installation, as caching
172
+ will cause strange nonsense to happen. Use a full versioned name to avoid
173
+ caching madness.
174
+
175
+
176
+ ## Devices and asynchrony
177
+
178
+ Emscripten's implementation of an in-memory filesystem has severe limitations.
179
+ You're recommended to use virtual devices, implemented by `libav.js`, for most
180
+ I/O. See [IO.md](docs/IO.md) for more details. libav.js itself imposes no
181
+ restriction on file sizes so long as you use asynchronous, device-backed I/O
182
+ (thus, the only restriction to size is JavaScript's number type).
183
+
184
+ ffmpeg was never designed to work asynchronously, and was only designed to work
185
+ with blocking I/O. Still, it's possible to use libav.js with asynchronous input
186
+ through these devices.
187
+
188
+
189
+ ## TypeScript
190
+
191
+ Type definitions for libav.js are provided by `libav.types.d.ts`. You can
192
+ either copy this file and import it:
193
+
194
+ ```typescript
195
+ import type LibAVJS from "./libav.types";
196
+ declare let LibAV: LibAVJS.LibAVWrapper;
197
+ ```
198
+
199
+ or import it from the npm package:
200
+
201
+ ```typescript
202
+ import type LibAVJS from "libav.js";
203
+ declare let LibAV: LibAVJS.LibAVWrapper;
204
+ ```
205
+
206
+
207
+ ## Variants and Building libav.js
208
+
209
+ With all of its bells and whistles enabled, FFmpeg is pretty large. So, I
210
+ disable most bells and most whistles and build specific versions with specific
211
+ features.
212
+
213
+ The default variant, `libav-<version>-default.js`, includes support for the most
214
+ important (and timeless) audio codecs and formats: Opus, FLAC, and wav, in WebM,
215
+ ogg, FLAC, or wav containers. It also has a set of common audio filters.
216
+
217
+ Built-in variants are created by combining “configuration fragments”. You can
218
+ find more on configuration fragments or making your own variants in
219
+ [CONFIG.md](docs/CONFIG.md).
220
+
221
+ Use `make build-<variant>`, replacing `<variant>` with the variant name, to
222
+ build another variant.
223
+
224
+ Most of the variants provided in the repository are also built and available in
225
+ NPM and as binary releases. The notable exception is all variants that include
226
+ codecs controlled by the Misanthropic Patent Extortion Gang (MPEG). They are not
227
+ built by default, and if you have any sense, you should not use them. MPEG is a
228
+ cancer on the digital media ecosystem.
229
+
230
+ The included variants and their codecs and formats are:
231
+
232
+ * default, default-cli: Opus (via libopus), FLAC, and wav in ogg, WebM, FLAC,
233
+ and wav containers, plus audio filters. The `-cli` subvariant additionally
234
+ includes the CLI (`ffmpeg` and `ffprobe` functions).
235
+
236
+ * opus, opus-af: Opus in ogg or WebM. `-af` additionally includes audio
237
+ filters.
238
+
239
+ * flac, flac-af: FLAC in ogg or FLAC. `-af` additionally includes audio
240
+ filters.
241
+
242
+ * wav, wav-af: PCM wav (16-bit or 24-bit) in wav. `-af` additionally includes
243
+ audio filters.
244
+
245
+ * obsolete: Same as default with the addition of two obsolete codecs, Vorbis
246
+ (via libvorbis) and MPEG-1 Layer 3 (MP3) (via libmp3lame). Also includes the
247
+ MP3 container format.
248
+
249
+ * webm, webm-vp9¹, webm-cli, webm-vp9-cli¹: Same as default with the addition
250
+ of VP8 (via libvpx) and video filters. `-vp9` additionally includes VP9,
251
+ `-cli` additionally includes the CLI. `-vp9` is separated due to the rather
252
+ significant size of the VP9 codec.
253
+
254
+ * webcodecs, webcodecs-avf: Designed to serve as a demuxer/muxer for codecs
255
+ supported by WebCodecs. Pairs well with
256
+ [libavjs-webcodecs-bridge](https://github.com/Yahweasel/libavjs-webcodecs-bridge).
257
+ Includes codecs for Opus, FLAC, and wav. Includes *parsers* (but not codecs)
258
+ for AAC, VP8, VP9, AV1, H.264, and H.265. Includes the ogg, WebM, MP4, FLAC,
259
+ and wav formats. This means that it can demux files including, e.g., H.264,
260
+ but cannot decode the frames. If your WebCodecs supports H.264, you can then
261
+ use it to decode. `-avf` additionally includes audio and video filters.
262
+
263
+ * vp8-opus, vp8-opus-avf: VP8 and Opus in WebM (or ogg). `-avf` additionally
264
+ includes audio and video filters.
265
+
266
+ * vp9-opus¹, vp9-opus-avf¹: VP9 and Opus in WebM (or ogg). `-avf` additionally
267
+ includes audio and video filters.
268
+
269
+ * av1-opus¹, av1-opus-avf¹: AV1 (via libaom) and Opus in WebM (or ogg). Note
270
+ that AV1 support is currently so slow in WebAssembly even with threads that
271
+ these variants are effectively unusable. `-avf` additionally includes audio
272
+ and video filters.
273
+
274
+ * aac², aac-af²: Reprobate codec AAC in MP4 or AAC/ADTS. `-af` additionally
275
+ includes audio filters.
276
+
277
+ * h264-aac², h264-aac-avf²: Reprobate codec H.264 (via libopenh264) and
278
+ reprobate codec AAC in MP4 (or AAC/ADTS). `-avf` additionally includes audio
279
+ and video filters.
280
+
281
+ * hevc-aac², hevc-aac-avf²: Reprobate codec H.265 (decoding only) and reprobate
282
+ codec AAC in MP4 (or AAC/ADTS). `-avf` additionally includes audio and video
283
+ filters.
284
+
285
+ ¹ These builds are not included in the full NPM release for space reasons, but are
286
+ included in GitHub releases, and are available on NPM as
287
+ @libav.js/variant-`<variant>`, e.g. `@libav.js/variant-vp9-opus`.
288
+
289
+ ² Includes technologies patented by the Misanthropic Patent Extortion Gang
290
+ (MPEG). You should not build these, you should not use these builds, and you
291
+ should not support this organization which works actively against the common
292
+ good.
293
+
294
+
295
+ This is intentionally designed so that you can add new variants without needing
296
+ to patch anything that already exists. If you want to create your own variants,
297
+ see [CONFIG.md](docs/CONFIG.md).
298
+
299
+ You can also build against different versions of FFmpeg than the version built
300
+ by default. To build against, for instance, FFmpeg 4.3.6, use `make
301
+ FFMPEG_VERSION_MAJOR=4 FFMPEG_VERSION_MINREV=3.6`. Note that you *must* use
302
+ `FFMPEG_VERSION_MAJOR` and `FFMPEG_VERSION_MINREV`, not just `FFMPEG_VERSION`,
303
+ because `FFMPEG_VERSION_MAJOR` is used to direct the process of patching FFmpeg.
304
+ libav.js should generally build against any version of FFmpeg in the 4, 5, or 6
305
+ series, but is not heavily tested against older versions; you should use the
306
+ default version unless you have some specific compatibility issue that forces
307
+ you to use a different version.
308
+
309
+
310
+ ## Size
311
+
312
+ FFmpeg is big, so libav.js is big. But, it's not ludicrous; the WebAssembly is
313
+ usually between 1.5 and 3 MiB for fairly complete builds, and the asm.js is about
314
+ double that.
315
+
316
+ You can estimate the size of variants based on the size of the constituent
317
+ fragments. As of version 5.0.6.1.1, an empty build is approximately 589KiB
318
+ (WebAssembly). The sizes of each additional fragment can be found in
319
+ [fragment-sizes.csv](docs/fragment-sizes.csv). The data in that CSV file can be
320
+ recreated by `tools/fragment-sizes.sh`, but note that the CSV file in the
321
+ repository is after further processing (in particular, normalizing to KiB and
322
+ subtracting away the empty size).
323
+
324
+ The asm.js versions are much bigger, but will not be loaded on
325
+ WebAssembly-capable clients.
326
+
327
+ The wrapper (“glue”) code is about 292KiB, but is highly compressible.
328
+
329
+
330
+ ## Performance
331
+
332
+ Generally speaking, the performance of audio en- and decoding is much faster
333
+ than real time, to the point that it's simply not a concern for most
334
+ applications. The author of libav.js regularly uses libav.js in live audio
335
+ systems.
336
+
337
+ Video is a different story, of course.
338
+
339
+ Video is nowhere near as slow as you might imagine. On reasonable systems,
340
+ faster-than-real-time performance for decoding of up to 1080P is achievable if
341
+ you use a threaded version of libav.js. If you're willing to use older, simpler
342
+ video codecs and lower-resolution video, even real-time *encoding* is possible.
343
+ But, for complex codecs, real-time en/decoding is not realistic. One of the
344
+ revolutions of video en/decoding is hardware en/decoding, and libav.js cannot do
345
+ that, so its performance ceiling is already low.
346
+
347
+ Muxing and demuxing are bound by I/O time, not software performance. libav.js
348
+ will always mux or demux faster than you can use the data.
349
+
350
+
351
+ ## libav.js and WebCodecs
352
+
353
+ On some modern browsers, the WebCodecs API is availble for hardware-accelerated
354
+ (or at least, CPU-specific) en/decoding of various codecs. When it is available,
355
+ it is better to use it than libav.js. However, WebCodecs does not mux or demux,
356
+ and which codecs it supports varies based on the moods of its implementor (if it
357
+ is even present), so generally, it is necessary to support WebCodecs but fall
358
+ back to libav.js when necessary.
359
+
360
+ To make this easier, two companion projects to libav.js are provided that
361
+ connect it to WebCodecs:
362
+
363
+ * [libavjs-webcodecs-polyfill](https://github.com/ennuicastr/libavjs-webcodecs-polyfill)
364
+ is a polyfill for the WebCodecs API using libav.js. Even if WebCodecs exists
365
+ on your browser, this polyfill allows the user to guarantee a certain set of
366
+ supported codecs; any codecs not supported by the built-in WebCodecs can
367
+ simply fall back to libav.js, using only one API.
368
+
369
+ * [libavjs-webcodecs-bridge](https://github.com/Yahweasel/libavjs-webcodecs-bridge)
370
+ is a bridge between libav.js and WebCodecs, converting between the two data
371
+ formats. This makes it easy to use libav.js for demuxing and WebCodecs for
372
+ decoding, or WebCodecs for encoding and libav.js for muxing. Of course, the
373
+ WebCodecs used with the bridge can easily be the polyfill if needed.
374
+
375
+
376
+ ## Bundlers
377
+
378
+ Generally speaking, because libav.js needs to adjust its loading procedure based
379
+ on the environment it's being loaded in, it's not a good idea to bundle
380
+ libav.js. However, if you have to bundle it, it can be done if necessary.
381
+
382
+ libav.js has a frontend (`libav-<version>-<variant>.js`), a factory
383
+ (`libav-<version>-<variant>.wasm.js` or `.thr.js`), and, if using WebAssembly, a
384
+ backend (`libav-<version>-<variant>.wasm.wasm` or `.thr.wasm`). Any of these can
385
+ be overridden, and any of them can be object URLs to bundle everything, though
386
+ this will destroy libav.js's ability to load the correct version for the system.
387
+
388
+ To override the frontend, simply load a different frontend!
389
+
390
+ To override the factory, you have two choices:
391
+
392
+ * Pass `toImport`, a string, to `LibAV.LibAV`'s options, e.g.,
393
+ `LibAV.LibAV({toImport: "libav-but-better.wasm.js"})`.
394
+
395
+ * Load the factory yourself, and pass the factory function as the `factory`
396
+ option to `LibAV.LibAV`, e.g., `LibAV.LibAV({factory: LibAVFactory})`. By
397
+ default, the factory function is exported as `LibAVFactory`, or for ES6
398
+ modules, it is the default export of the module.
399
+
400
+ To override the backend, you can pass the full URL (or object URL) to the
401
+ WebAssembly as the option `wasmurl` to `LibAV.LibAV`, e.g.,
402
+ `LibAV.LibAV({wasmurl: URL.createObjectURL(...)})`.
403
+
404
+ Be careful about which versions of things you bundle. The ES6 module version of
405
+ libav.js assumes that it will actually *be* an ES6 module, and so will be able
406
+ to use, e.g., `import`. If your bundler transforms it into a non-ES6 module, you
407
+ must explicitly tell it to import some other way by passing the option `noes6`
408
+ to `LibAV.LibAV`, e.g., `LibAV.LibAV({noes6: true})`. Also, if your bundler
409
+ converts the ES6 frontend to non-ES6 and you intend to explicitly specify
410
+ `toImport`, you must specify the *non-ES6* factory.