canvas-record
Version:
Record a video in the browser or directly on the File System from a canvas region (2D/WebGL/WebGPU) as MP4, WebM, MKV, MOV, GIF, PNG/JPG Sequence using WebCodecs and wasm when available.
730 lines (513 loc) • 33.4 kB
Markdown
# canvas-record
[](https://www.npmjs.com/package/canvas-record)
[](https://www.npmjs.com/package/canvas-record)
[](https://bundlephobia.com/package/canvas-record)
[](https://github.com/dmnsgn/canvas-record/blob/main/package.json)
[](https://github.com/microsoft/TypeScript)
[](https://conventionalcommits.org)
[](https://github.com/prettier/prettier)
[](https://github.com/eslint/eslint)
[](https://github.com/dmnsgn/canvas-record/blob/main/LICENSE.md)
Record a video in the browser or directly on the File System from a canvas region (2D/WebGL/WebGPU) as MP4, WebM, MKV, MOV, GIF, PNG/JPG Sequence using WebCodecs and Wasm when available.
[](https://paypal.me/dmnsgn)
[](https://commerce.coinbase.com/checkout/56cbdf28-e323-48d8-9c98-7019e72c97f3)
[](https://twitter.com/dmnsgn)
[](https://bsky.app/profile/dmnsgn.me)

## Installation
```bash
npm install canvas-record
```
## Usage
```js
import { Recorder, RecorderStatus, Encoders } from "canvas-record";
import createCanvasContext from "canvas-context";
import { AVC } from "media-codecs";
// Setup
const pixelRatio = devicePixelRatio;
const width = 512;
const height = 512;
const { context, canvas } = createCanvasContext("2d", {
width: width * pixelRatio,
height: height * pixelRatio,
contextAttributes: { willReadFrequently: true },
});
Object.assign(canvas.style, { width: `${width}px`, height: `${height}px` });
const mainElement = document.querySelector("main");
mainElement.appendChild(canvas);
// Animation
let canvasRecorder;
function render() {
const width = canvas.width;
const height = canvas.height;
const t = canvasRecorder.frame / canvasRecorder.frameTotal || Number.EPSILON;
context.clearRect(0, 0, width, height);
context.fillStyle = "red";
context.fillRect(0, 0, t * width, height);
}
const tick = async () => {
render();
if (canvasRecorder.status !== RecorderStatus.Recording) return;
await canvasRecorder.step();
if (canvasRecorder.status !== RecorderStatus.Stopped) {
requestAnimationFrame(() => tick());
}
};
canvasRecorder = new Recorder(context, {
name: "canvas-record-example",
encoderOptions: {
codec: AVC.getCodec({ profile: "Main", level: "5.2" }),
},
});
// Start and encode frame 0
await canvasRecorder.start();
// Animate to encode the rest
tick(canvasRecorder);
```
## API
Encoder comparison:
| Encoder | Extension | Required Web API | WASM | Speed |
| -------------- | ---------------------- | ------------------ | --------------------- | -------- |
| `WebCodecs` | `mp4` / `webm` / `mkv` | WebCodecs | ❌ | Fast |
| `MP4Wasm` | `mp4` | WebCodecs | ✅ (embed) | Fast |
| `H264MP4` | `mp4` | | ✅ (embed) | Medium |
| `FFmpeg` | `mp4` / `webm` | SharedArrayBuffer | ✅ (need binary path) | Slow |
| `GIF` | `gif` | WebWorkers (wip) | ❌ | Fast |
| `Frame` | `png` / `jpg` | File System Access | ❌ | Fast |
| `MediaCapture` | `mkv` / `webm` | MediaStream | ❌ | Realtime |
Note:
- `WebCodecs` encoderOptions allow different codecs to be used: VP8/VP9/AV1/HEVC. See [media-codecs](https://github.com/dmnsgn/media-codecs) to get a codec string from human readable options and check which ones are supported in your browser with [github.io/media-codecs](https://dmnsgn.github.io/media-codecs/).
- `WebCodecs` 5-10x faster than H264MP4Encoder and 20x faster than `FFmpeg` (it needs to mux files after writing png to virtual FS)
- `FFmpeg` (mp4 and webm) and `WebCodecs` (mp4) have a AVC maximum frame size of 9437184 pixels. That's fine until a bit more than 4K 16:9 @ 30fps. So if you need 4K Square or 8K exports, be patient with `H264MP4Encoder` (which probably also has the 4GB memory limit) or use Frame encoder and mux them manually with `FFmpeg` CLI (`ffmpeg -framerate 30 -i "%05d.jpg" -b:v 60M -r 30 -profile:v baseline -pix_fmt yuv420p -movflags +faststart output.mp4`)
- `MP4Wasm` is embedded from [mp4-wasm](https://github.com/mattdesl/mp4-wasm/) for ease of use (`FFmpeg` will require `encoderOptions.corePath`)
Roadmap:
- [ ] add debug logging
- [ ] use WebWorkers for gifenc
<!-- api-start -->
## Modules
<dl>
<dt><a href="#module_canvas-record">canvas-record</a></dt>
<dd><p>Re-export Recorder, RecorderStatus, all Encoders and utils.</p>
</dd>
</dl>
## Classes
<dl>
<dt><a href="#Recorder">Recorder</a></dt>
<dd></dd>
<dt><a href="#Encoder">Encoder</a></dt>
<dd></dd>
<dt><a href="#FFmpegEncoder">FFmpegEncoder</a></dt>
<dd></dd>
<dt><a href="#FrameEncoder">FrameEncoder</a></dt>
<dd></dd>
<dt><a href="#GIFEncoder">GIFEncoder</a></dt>
<dd></dd>
<dt><a href="#H264MP4Encoder">H264MP4Encoder</a></dt>
<dd></dd>
<dt><a href="#MediaCaptureEncoder">MediaCaptureEncoder</a></dt>
<dd></dd>
<dt><a href="#MP4WasmEncoder">MP4WasmEncoder</a></dt>
<dd></dd>
<dt><a href="#WebCodecsEncoder">WebCodecsEncoder</a></dt>
<dd></dd>
</dl>
## Constants
<dl>
<dt><a href="#isWebCodecsSupported">isWebCodecsSupported</a> : <code>boolean</code></dt>
<dd><p>Check for WebCodecs support on the current platform.</p>
</dd>
</dl>
## Functions
<dl>
<dt><a href="#estimateBitRate">estimateBitRate(width, height, frameRate, motionRank, bitrateMode)</a> ⇒ <code>number</code></dt>
<dd><p>Estimate the bit rate of a video rounded to nearest megabit.
Based on "H.264 for the rest of us" by Kush Amerasinghe.</p>
</dd>
</dl>
## Typedefs
<dl>
<dt><a href="#onStatusChangeCb">onStatusChangeCb</a> : <code>function</code></dt>
<dd><p>A callback to notify on the status change. To compare with RecorderStatus enum values.</p>
</dd>
<dt><a href="#RecorderOptions">RecorderOptions</a> : <code>object</code></dt>
<dd><p>Options for recording. All optional.</p>
</dd>
<dt><a href="#RecorderStartOptions">RecorderStartOptions</a> : <code>object</code></dt>
<dd><p>Options for recording initialisation. All optional.</p>
</dd>
<dt><a href="#EncoderExtensions">EncoderExtensions</a> : <code>"mp4"</code> | <code>"webm"</code> | <code>"png"</code> | <code>"jpg"</code> | <code>"gif"</code> | <code>"mkv"</code></dt>
<dd></dd>
<dt><a href="#EncoderTarget">EncoderTarget</a> : <code>"in-browser"</code> | <code>"file-system"</code></dt>
<dd></dd>
<dt><a href="#FFmpegEncoderOptions">FFmpegEncoderOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#FFmpegEncoderEncoderOptions">FFmpegEncoderEncoderOptions</a> : <code>module:@ffmpeg/ffmpeg/dist/esm/types.js~FFMessageLoadConfig</code></dt>
<dd></dd>
<dt><a href="#GIFEncoderOptions">GIFEncoderOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#GIFEncoderQuantizeOptions">GIFEncoderQuantizeOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#GIFEncoderEncoderOptions">GIFEncoderEncoderOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#H264MP4EncoderOptions">H264MP4EncoderOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#H264MP4EncoderEncoderOptions">H264MP4EncoderEncoderOptions</a> : <code>module:h264-mp4-encoder~H264MP4Encoder</code></dt>
<dd></dd>
<dt><a href="#MediaCaptureEncoderOptions">MediaCaptureEncoderOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#MediaCaptureEncoderEncoderOptions">MediaCaptureEncoderEncoderOptions</a> : <code>MediaRecorderOptions</code></dt>
<dd></dd>
<dt><a href="#MP4WasmEncoderOptions">MP4WasmEncoderOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#MP4WasmEncoderEncoderOptions">MP4WasmEncoderEncoderOptions</a> : <code>VideoEncoderConfig</code></dt>
<dd></dd>
<dt><a href="#WebCodecsEncoderOptions">WebCodecsEncoderOptions</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#WebCodecsEncoderEncoderOptions">WebCodecsEncoderEncoderOptions</a> : <code>VideoEncoderConfig</code></dt>
<dd></dd>
<dt><a href="#WebCodecsMuxerOptions">WebCodecsMuxerOptions</a> : <code>module:mediabunny~OutputOptions</code></dt>
<dd></dd>
</dl>
<a name="module_canvas-record"></a>
## canvas-record
Re-export Recorder, RecorderStatus, all Encoders and utils.
<a name="Recorder"></a>
## Recorder
**Kind**: global class
- [Recorder](#Recorder)
- [new Recorder(context, [options])](#new_Recorder_new)
- [.defaultOptions](#Recorder+defaultOptions) : [<code>RecorderOptions</code>](#RecorderOptions)
- [.mimeTypes](#Recorder+mimeTypes) : <code>object</code>
- [.start([startOptions])](#Recorder+start)
- [.step()](#Recorder+step)
- [.stop()](#Recorder+stop) ⇒ <code>ArrayBuffer</code> \| <code>Uint8Array</code> \| <code>Array.<Blob></code> \| <code>undefined</code>
- [.dispose()](#Recorder+dispose)
<a name="new_Recorder_new"></a>
### new Recorder(context, [options])
Create a Recorder instance
| Param | Type | Default |
| --------- | ------------------------------------------------ | --------------- |
| context | <code>RenderingContext</code> | |
| [options] | [<code>RecorderOptions</code>](#RecorderOptions) | <code>{}</code> |
<a name="Recorder+defaultOptions"></a>
### recorder.defaultOptions : [<code>RecorderOptions</code>](#RecorderOptions)
Sensible defaults for recording so that the recorder "just works".
**Kind**: instance property of [<code>Recorder</code>](#Recorder)
<a name="Recorder+mimeTypes"></a>
### recorder.mimeTypes : <code>object</code>
A mapping of extension to their mime types
**Kind**: instance property of [<code>Recorder</code>](#Recorder)
<a name="Recorder+start"></a>
### recorder.start([startOptions])
Start the recording by initializing and optionally calling the initial step.
**Kind**: instance method of [<code>Recorder</code>](#Recorder)
| Param | Type | Default |
| -------------- | ---------------------------------------------------------- | --------------- |
| [startOptions] | [<code>RecorderStartOptions</code>](#RecorderStartOptions) | <code>{}</code> |
<a name="Recorder+step"></a>
### recorder.step()
Encode a frame and increment the time and the playhead.
Calls `await canvasRecorder.stop()` when duration is reached.
**Kind**: instance method of [<code>Recorder</code>](#Recorder)
<a name="Recorder+stop"></a>
### recorder.stop() ⇒ <code>ArrayBuffer</code> \| <code>Uint8Array</code> \| <code>Array.<Blob></code> \| <code>undefined</code>
Stop the recording and return the recorded buffer.
If options.download is set, automatically start downloading the resulting file.
Is called when duration is reached or manually.
**Kind**: instance method of [<code>Recorder</code>](#Recorder)
<a name="Recorder+dispose"></a>
### recorder.dispose()
Clean up the recorder and encoder
**Kind**: instance method of [<code>Recorder</code>](#Recorder)
<a name="Encoder"></a>
## Encoder
**Kind**: global class
**Properties**
| Name | Type |
| ---------------- | ---------------------------------------------------- |
| target | [<code>EncoderTarget</code>](#EncoderTarget) |
| extension | [<code>EncoderExtensions</code>](#EncoderExtensions) |
| [encoderOptions] | <code>object</code> |
| [muxerOptions] | <code>object</code> |
- [Encoder](#Encoder)
- [new Encoder(options)](#new_Encoder_new)
- [.supportedExtensions](#Encoder+supportedExtensions) : <code>Array.<Extensions></code>
- [.supportedTargets](#Encoder+supportedTargets) : [<code>Array.<EncoderTarget></code>](#EncoderTarget)
- [.init(options)](#Encoder+init)
- [.encode(frame, [frameNumber])](#Encoder+encode)
- [.stop()](#Encoder+stop) ⇒ <code>ArrayBuffer</code> \| <code>Uint8Array</code> \| <code>Array.<Blob></code> \| <code>undefined</code>
- [.dispose()](#Encoder+dispose)
<a name="new_Encoder_new"></a>
### new Encoder(options)
Base Encoder class. All Encoders extend it and its method are called by the Recorder.
| Param | Type |
| ------- | ------------------- |
| options | <code>object</code> |
<a name="Encoder+supportedExtensions"></a>
### encoder.supportedExtensions : <code>Array.<Extensions></code>
The extension the encoder supports
**Kind**: instance property of [<code>Encoder</code>](#Encoder)
<a name="Encoder+supportedTargets"></a>
### encoder.supportedTargets : [<code>Array.<EncoderTarget></code>](#EncoderTarget)
The target to download the file to.
**Kind**: instance property of [<code>Encoder</code>](#Encoder)
<a name="Encoder+init"></a>
### encoder.init(options)
Setup the encoder: load binary, instantiate muxers, setup file system target...
**Kind**: instance method of [<code>Encoder</code>](#Encoder)
| Param | Type |
| ------- | ------------------- |
| options | <code>object</code> |
<a name="Encoder+encode"></a>
### encoder.encode(frame, [frameNumber])
Encode a single frame. The frameNumber is usually used for GOP (Group Of Pictures).
**Kind**: instance method of [<code>Encoder</code>](#Encoder)
| Param | Type |
| ------------- | ------------------- |
| frame | <code>number</code> |
| [frameNumber] | <code>number</code> |
<a name="Encoder+stop"></a>
### encoder.stop() ⇒ <code>ArrayBuffer</code> \| <code>Uint8Array</code> \| <code>Array.<Blob></code> \| <code>undefined</code>
Stop the encoding process and cleanup the temporary data.
**Kind**: instance method of [<code>Encoder</code>](#Encoder)
<a name="Encoder+dispose"></a>
### encoder.dispose()
Clean up the encoder
**Kind**: instance method of [<code>Encoder</code>](#Encoder)
<a name="FFmpegEncoder"></a>
## FFmpegEncoder
**Kind**: global class
<a name="new_FFmpegEncoder_new"></a>
### new FFmpegEncoder([options])
| Param | Type |
| --------- | ---------------------------------------------------------- |
| [options] | [<code>FFmpegEncoderOptions</code>](#FFmpegEncoderOptions) |
<a name="FrameEncoder"></a>
## FrameEncoder
**Kind**: global class
<a name="GIFEncoder"></a>
## GIFEncoder
**Kind**: global class
<a name="new_GIFEncoder_new"></a>
### new GIFEncoder([options])
| Param | Type |
| --------- | ---------------------------------------------------- |
| [options] | [<code>GIFEncoderOptions</code>](#GIFEncoderOptions) |
<a name="H264MP4Encoder"></a>
## H264MP4Encoder
**Kind**: global class
<a name="new_H264MP4Encoder_new"></a>
### new H264MP4Encoder([options])
| Param | Type |
| --------- | ------------------------------------------------------------ |
| [options] | [<code>H264MP4EncoderOptions</code>](#H264MP4EncoderOptions) |
<a name="MediaCaptureEncoder"></a>
## MediaCaptureEncoder
**Kind**: global class
<a name="new_MediaCaptureEncoder_new"></a>
### new MediaCaptureEncoder([options])
| Param | Type |
| --------- | ---------------------------------------------------------------------- |
| [options] | [<code>MediaCaptureEncoderOptions</code>](#MediaCaptureEncoderOptions) |
<a name="MP4WasmEncoder"></a>
## MP4WasmEncoder
**Kind**: global class
<a name="new_MP4WasmEncoder_new"></a>
### new MP4WasmEncoder([options])
| Param | Type |
| --------- | ------------------------------------------------------------ |
| [options] | [<code>MP4WasmEncoderOptions</code>](#MP4WasmEncoderOptions) |
<a name="WebCodecsEncoder"></a>
## WebCodecsEncoder
**Kind**: global class
<a name="new_WebCodecsEncoder_new"></a>
### new WebCodecsEncoder([options])
| Param | Type |
| --------- | ---------------------------------------------------------------- |
| [options] | [<code>WebCodecsEncoderOptions</code>](#WebCodecsEncoderOptions) |
<a name="RecorderStatus"></a>
## RecorderStatus : <code>enum</code>
Enum for recorder status
**Kind**: global enum
**Read only**: true
**Example**
```js
// Check recorder status before continuing
if (canvasRecorder.status !== RecorderStatus.Stopped) {
rAFId = requestAnimationFrame(() => tick());
}
```
<a name="isWebCodecsSupported"></a>
## isWebCodecsSupported : <code>boolean</code>
Check for WebCodecs support on the current platform.
**Kind**: global constant
<a name="estimateBitRate"></a>
## estimateBitRate(width, height, frameRate, motionRank, bitrateMode) ⇒ <code>number</code>
Estimate the bit rate of a video rounded to nearest megabit.
Based on "H.264 for the rest of us" by Kush Amerasinghe.
**Kind**: global function
**Returns**: <code>number</code> - A bitrate value in bits per second
| Param | Type | Default | Description |
| ----------- | ---------------------------------------------------------------------- | --------------------- | --------------------- |
| width | <code>number</code> | | |
| height | <code>number</code> | | |
| frameRate | <code>number</code> | <code>30</code> | |
| motionRank | <code>number</code> | <code>4</code> | A factor of 1, 2 or 4 |
| bitrateMode | <code>"variable"</code> \| <code>"constant"</code> | <code>variable</code> | |
**Example**
```js
// Full HD (1080p)
const bitRate = estimateBitRate(1920, 1080, 30, "variable");
const bitRateMbps = bitRate * 1_000_000; // => 13 Mbps
```
<a name="onStatusChangeCb"></a>
## onStatusChangeCb : <code>function</code>
A callback to notify on the status change. To compare with RecorderStatus enum values.
**Kind**: global typedef
| Param | Type | Description |
| -------------- | ------------------- | ----------- |
| RecorderStatus | <code>number</code> | the status |
<a name="RecorderOptions"></a>
## RecorderOptions : <code>object</code>
Options for recording. All optional.
**Kind**: global typedef
**Properties**
| Name | Type | Default | Description |
| ---------------- | -------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [name] | <code>string</code> | <code>"\"\""</code> | A name for the recorder, used as prefix for the default file name. |
| [duration] | <code>number</code> | <code>10</code> | The recording duration in seconds. If set to Infinity, `await canvasRecorder.stop()` needs to be called manually. |
| [frameRate] | <code>number</code> | <code>30</code> | The frame rate in frame per seconds. Use `await canvasRecorder.step();` to go to the next frame. |
| [rect] | <code>Array</code> | <code>[]</code> | Sub-region [x, y, width, height] of the canvas to encode from bottom left. Default to 0, 0 and context.drawingBufferWidth/drawingBufferHeight or canvas.width/height. |
| [download] | <code>boolean</code> | <code>true</code> | Automatically download the recording when duration is reached or when `await canvasRecorder.stop()` is manually called. |
| [extension] | <code>string</code> | <code>"\"mp4\""</code> | Default file extension: infers which Encoder is selected. |
| [target] | <code>string</code> | <code>"\"in-browser\""</code> | Default writing target: in-browser or file-system when available. |
| [encoder] | <code>object</code> | | A specific encoder. Default encoder based on options.extension: GIF > WebCodecs > H264MP4. |
| [encoderOptions] | <code>object</code> | | See `src/encoders` or individual packages for a list of options. |
| [muxerOptions] | <code>object</code> | | See "mediabunny" for a list of options. |
| [frameOptions] | <code>object</code> | | Options for createImageBitmap(), VideoFrame, getImageData() or canvas-screenshot. |
| [onStatusChange] | [<code>onStatusChangeCb</code>](#onStatusChangeCb) | | |
<a name="RecorderStartOptions"></a>
## RecorderStartOptions : <code>object</code>
Options for recording initialisation. All optional.
**Kind**: global typedef
**Properties**
| Name | Type | Description |
| ---------- | -------------------- | ----------------------------------------------------------------------------- |
| [filename] | <code>string</code> | Overwrite the file name completely. |
| [initOnly] | <code>boolean</code> | Only initialised the recorder and don't call the first await recorder.step(). |
<a name="EncoderExtensions"></a>
## EncoderExtensions : <code>"mp4"</code> \| <code>"webm"</code> \| <code>"png"</code> \| <code>"jpg"</code> \| <code>"gif"</code> \| <code>"mkv"</code>
**Kind**: global typedef
<a name="EncoderTarget"></a>
## EncoderTarget : <code>"in-browser"</code> \| <code>"file-system"</code>
**Kind**: global typedef
<a name="FFmpegEncoderOptions"></a>
## FFmpegEncoderOptions : <code>object</code>
**Kind**: global typedef
**Properties**
| Name | Type | Default |
| ---------------- | ------------------------------------------------------------------------ | --------------- |
| [encoderOptions] | [<code>FFmpegEncoderEncoderOptions</code>](#FFmpegEncoderEncoderOptions) | <code>{}</code> |
<a name="FFmpegEncoderEncoderOptions"></a>
## FFmpegEncoderEncoderOptions : <code>module:@ffmpeg/ffmpeg/dist/esm/types.js~FFMessageLoadConfig</code>
**Kind**: global typedef
**See**: [FFmpeg#load](https://ffmpegwasm.netlify.app/docs/api/ffmpeg/classes/FFmpeg#load)
<a name="GIFEncoderOptions"></a>
## GIFEncoderOptions : <code>object</code>
**Kind**: global typedef
**Properties**
| Name | Type | Default |
| ----------------- | -------------------------------------------------------------------- | ---------------- |
| [maxColors] | <code>number</code> | <code>256</code> |
| [quantizeOptions] | [<code>GIFEncoderQuantizeOptions</code>](#GIFEncoderQuantizeOptions) | |
| [encoderOptions] | [<code>GIFEncoderEncoderOptions</code>](#GIFEncoderEncoderOptions) | <code>{}</code> |
<a name="GIFEncoderQuantizeOptions"></a>
## GIFEncoderQuantizeOptions : <code>object</code>
**Kind**: global typedef
**See**: [QuantizeOptions](https://github.com/mattdesl/gifenc#palette--quantizergba-maxcolors-options--)
**Properties**
| Name | Type | Default |
| --------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------- |
| [format] | <code>"rgb565"</code> \| <code>"rgb444"</code> \| <code>"rgba4444"</code> | <code>"rgb565"</code> |
| [oneBitAlpha] | <code>boolean</code> \| <code>number</code> | <code>false</code> |
| [clearAlpha] | <code>boolean</code> | <code>true</code> |
| [clearAlphaThreshold] | <code>number</code> | <code>0</code> |
| [clearAlphaColor] | <code>number</code> | <code>0x00</code> |
<a name="GIFEncoderEncoderOptions"></a>
## GIFEncoderEncoderOptions : <code>object</code>
**Kind**: global typedef
**See**: [WriteFrameOpts](https://github.com/mattdesl/gifenc#gifwriteframeindex-width-height-opts--)
**Properties**
| Name | Type | Default |
| ------------------ | ----------------------------------------------- | ------------------ |
| [palette] | <code>Array.<Array.<number>></code> | |
| [first] | <code>boolean</code> | <code>false</code> |
| [transparent] | <code>boolean</code> | <code>0</code> |
| [transparentIndex] | <code>number</code> | <code>0</code> |
| [delay] | <code>number</code> | <code>0</code> |
| [repeat] | <code>number</code> | <code>0</code> |
| [dispose] | <code>number</code> | <code>-1</code> |
<a name="H264MP4EncoderOptions"></a>
## H264MP4EncoderOptions : <code>object</code>
**Kind**: global typedef
**Properties**
| Name | Type | Default |
| ---------------- | -------------------------------------------------------------------------- | --------------- |
| [debug] | <code>boolean</code> | |
| [encoderOptions] | [<code>H264MP4EncoderEncoderOptions</code>](#H264MP4EncoderEncoderOptions) | <code>{}</code> |
<a name="H264MP4EncoderEncoderOptions"></a>
## H264MP4EncoderEncoderOptions : <code>module:h264-mp4-encoder~H264MP4Encoder</code>
**Kind**: global typedef
**See**: [h264-mp4-encoder#api](https://github.com/TrevorSundberg/h264-mp4-encoder#api)
<a name="MediaCaptureEncoderOptions"></a>
## MediaCaptureEncoderOptions : <code>object</code>
**Kind**: global typedef
**Properties**
| Name | Type | Default |
| ---------------- | ------------------------------------------------------------------------------------ | --------------- |
| [flushFrequency] | <code>number</code> | <code>10</code> |
| [encoderOptions] | [<code>MediaCaptureEncoderEncoderOptions</code>](#MediaCaptureEncoderEncoderOptions) | <code>{}</code> |
<a name="MediaCaptureEncoderEncoderOptions"></a>
## MediaCaptureEncoderEncoderOptions : <code>MediaRecorderOptions</code>
**Kind**: global typedef
**See**: [MediaRecorder#options](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder#options)
<a name="MP4WasmEncoderOptions"></a>
## MP4WasmEncoderOptions : <code>object</code>
**Kind**: global typedef
**Properties**
| Name | Type | Default |
| ----------------- | -------------------------------------------------------------------------- | --------------- |
| [groupOfPictures] | <code>number</code> | <code>20</code> |
| [flushFrequency] | <code>number</code> | <code>10</code> |
| [encoderOptions] | [<code>MP4WasmEncoderEncoderOptions</code>](#MP4WasmEncoderEncoderOptions) | <code>{}</code> |
<a name="MP4WasmEncoderEncoderOptions"></a>
## MP4WasmEncoderEncoderOptions : <code>VideoEncoderConfig</code>
**Kind**: global typedef
**See**: [VideoEncoder.configure](https://developer.mozilla.org/en-US/docs/Web/API/VideoEncoder/configure#config)
<a name="WebCodecsEncoderOptions"></a>
## WebCodecsEncoderOptions : <code>object</code>
**Kind**: global typedef
**Properties**
| Name | Type | Default |
| ----------------- | ------------------------------------------------------------------------------ | --------------- |
| [groupOfPictures] | <code>number</code> | <code>20</code> |
| [flushFrequency] | <code>number</code> | <code>10</code> |
| [encoderOptions] | [<code>WebCodecsEncoderEncoderOptions</code>](#WebCodecsEncoderEncoderOptions) | <code>{}</code> |
<a name="WebCodecsEncoderEncoderOptions"></a>
## WebCodecsEncoderEncoderOptions : <code>VideoEncoderConfig</code>
**Kind**: global typedef
**See**: [VideoEncoder.configure](https://developer.mozilla.org/en-US/docs/Web/API/VideoEncoder/configure#config)
<a name="WebCodecsMuxerOptions"></a>
## WebCodecsMuxerOptions : <code>module:mediabunny~OutputOptions</code>
**Kind**: global typedef
**See**: [mediabunny#output-formats](https://mediabunny.dev/guide/output-formats)
<!-- api-end -->
## License
All MIT:
- [mp4-wasm](https://github.com/mattdesl/mp4-wasm/blob/master/LICENSE.md)
- [h264-mp4-encoder](https://github.com/TrevorSundberg/h264-mp4-encoder/blob/master/LICENSE.md)
- [@ffmpeg/ffmpeg](https://github.com/ffmpegwasm/ffmpeg.wasm/blob/master/LICENSE)
- [gifenc](https://github.com/mattdesl/gifenc/blob/master/LICENSE.md)
- [webm-muxer](https://github.com/Vanilagy/webm-muxer/blob/main/LICENSE)
- [mp4-muxer](https://github.com/Vanilagy/mp4-muxer/blob/main/LICENSE)
MIT. See [license file](https://github.com/dmnsgn/canvas-record/blob/main/LICENSE.md).