UNPKG

@dmk-dark/opus-media-recorder-fork

Version:

MedialRecorer polyfill for Opus recording using WebAssembly

242 lines (180 loc) 10.5 kB
# @dmk-dark/opus-media-recorder-fork ## Fork Improvements This fork of the original opus-media-recorder adds the following improvements: - **TypeScript Definitions**: Full TypeScript type support added for better developer experience - **GlobalThis Support**: Replaced direct `global` references with standard `globalThis` for better cross-environment compatibility - **Custom Sample Rate**: Added support for custom AudioContext sample rate through a new `audioOptions` parameter, allowing to control the recording quality - **Security Fixes**: Updated dependencies to resolve security vulnerabilities identified in the original package Important: Throughout this documentation, please replace all references to opus-media-recorder with @dmk-dark/opus-media-recorder-fork. The rest of the original documentation follows below. * [Try it!](https://kbumsik.io/opus-media-recorder/) * [JS Fiddle example](https://jsfiddle.net/kbumsik/v3wpnxao/) `opus-media-recorder` is a [MediaRecorder API](https://w3c.github.io/mediacapture-record/#mediarecorder-api) polyfill written in ES6 and WebAssembly. It aims for cross-browser Opus codec support with various audio formats such as Ogg and WebM. `opus-media-recorder` can be used as a polyfill, or it can replace the built-in MediaRecorder since `opus-media-recorder` supports more MIME types. `opus-media-recorder` uses WebAssembly compiled from popular libraries (e.g libopus, libogg, libwebm, and speexdsp) to ensure good performance and standards-compliance. - [Why opus-media-recorder?](#why-opus-media-recorder) - [How to use](#how-to-use) - [Thing to know](#thing-to-know) - [JavaScript](#javascript) - [Examples](#examples) - [Installation](#installation) - [Working with a bundler](#working-with-a-bundler) - [Simple JavaScript example (webpack)](#simple-javascript-example-webpack) - [HTML `<script>` tag](#html-script-tag) - [Use opus-media-recorder only when a browser doesn't support it](#use-opus-media-recorder-only-when-a-browser-doesnt-support-it) - [Browser support](#browser-support) - [MIME Type support](#mime-type-support) - [Limitations](#limitations) - [How to build](#how-to-build) - [Changelog](#changelog) ## Why opus-media-recorder? | | opus-media-recorder | Chrome | Firefox | iOS | Edge | |--------------|:-------------------:|:------:|:-------:|:---:|:----:| | `audio/ogg` | O | X | O | X | X | | `audio/webm` | O | O | X | X | X | | `audio/wav` | O | X | X | X | X | \* Both `audio/ogg` and `audio/webm` refer containers for Opus audio codec. Currently the MediaRecorder API suffers from the two problems: 1. Not all browsers support MediaRecorder. 2. Even the browsers that provides MediaRecorder don't support the same format. `opus-media-recorder` tackles these problems by supporting all major modern browsers (Chrome, Firefox, iOS, and Edge) and by providing various formats. By taking advantages of WebAssembly and Web Workers, `opus-media-recorder` tries to have minimum performace penalties of running encoders in a browser. ## How to use opus-media-recorder is compatible with the [Mediastream Recording API](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) standard. ### Thing to know * The page must be served over HTTPS in order to record. * Being able to record does *not always* mean you can play it in a browser: * macOS/iOS Safari cannot play Opus natively yet. * Old Edge requires [an extension](https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/6513488-ogg-vorbis-and-opus-audio-formats-support-firefox) to play Opus natively. * You can get an Opus decorder to play it. There are Opus decoders available, such as [Chris Rudmin's Opus decoder](https://github.com/chris-rudmin/opus-recorder). * Otherwise, users can download as a recording file and play it using apps like [VLC](https://www.videolan.org/vlc/index.html). * When `mimeType` is not specified a default encoder is loaded depending on OS: * Chrome: `audio/webm` * Firefox: `audio/ogg` * Edge: `audio/webm` * iOS/macOS Safari: `audio/wave` - because they cannot play Opus at all. ### JavaScript For standard usages of `MediaRecorder`, see the [MDN reference](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) and other online resources. Our [testing website](docs) and [example section](example) may be useful as well. #### Examples * [Webpack](example/webpack) * [create-react-app](example/create-react-app) * [Rollup](example/rollup) * [Browserify](example/browserify) #### Installation ```bash npm install --save-dev @dmk-dark/opus-media-recorder-fork ``` #### Working with a bundler Because `opus-media-recorder` needs to load a dedicated web worker and `.wasm` binaries, special configurations are necessary. In general: ```javascript import OpusMediaRecorder from '@dmk-dark/opus-media-recorder-fork'; // Choose desired format like audio/webm. Default is audio/ogg const options = { mimeType: 'audio/ogg' } // Web worker and .wasm configuration. Note: This is NOT a part of W3C standard. const workerOptions = { encoderWorkerFactory: function () { // UMD should be used if you don't use a web worker bundler for this. return new Worker('.../path/to/opus-media-recorder/encoderWorker.umd.js') }, OggOpusEncoderWasmPath: '.../path/to/opus-media-recorder/OggOpusEncoder.wasm', WebMOpusEncoderWasmPath: '.../path/to/opus-media-recorder/WebMOpusEncoder.wasm' }; window.MediaRecorder = OpusMediaRecorder; recorder = new MediaRecorder(stream, options, workerOptions); ``` #### Simple JavaScript example (webpack) ```javascript import MediaRecorder from '@dmk-dark/opus-media-recorder-fork'; // Use worker-loader import EncoderWorker from 'worker-loader!opus-media-recorder/encoderWorker.js'; // You should use file-loader in webpack.config.js. // See webpack example link in the above section for more detail. import OggOpusWasm from 'opus-media-recorder/OggOpusEncoder.wasm'; import WebMOpusWasm from 'opus-media-recorder/WebMOpusEncoder.wasm'; // Non-standard options const workerOptions = { encoderWorkerFactory: _ => new EncoderWorker(), OggOpusEncoderWasmPath: OggOpusWasm, WebMOpusEncoderWasmPath: WebMOpusWasm }; let recorder; function startRecording () { navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => { let options = { mimeType: 'audio/ogg' }; // Start recording recorder = new MediaRecorder(stream, options, workerOptions); recorder.start(); // Set record to <audio> when recording will be finished recorder.addEventListener('dataavailable', (e) => { audioElement.src = URL.createObjectURL(e.data); }); }); } // Recording should be started in user-initiated event like buttons recordButton.addEventListener('click', startRecording); // Stop recording stopButton.addEventListener('click', () => { recorder.stop(); // Remove “recording” icon from browser tab recorder.stream.getTracks().forEach(i => i.stop()); }) ``` ### HTML `<script>` tag The `OpusMediaRecorder` object is available in the global namespace using [UMD](https://github.com/umdjs/umd). ```html <!-- load OpusMediaRecorder.umd.js. OpusMediaRecorder will be loaded. --> <script src="https://cdn.jsdelivr.net/npm/opus-media-recorder@latest/OpusMediaRecorder.umd.js"></script> <!-- load encoderWorker.umd.js. This should be after OpusMediaRecorder. --> <!-- This script tag will create OpusMediaRecorder.encoderWorker. --> <script src="https://cdn.jsdelivr.net/npm/opus-media-recorder@latest/encoderWorker.umd.js"></script> <script> ... // If you already load encoderWorker.js using <script> tag, // you don't need to define encoderWorkerFactory. const workerOptions = { OggOpusEncoderWasmPath: 'https://cdn.jsdelivr.net/npm/opus-media-recorder@latest/OggOpusEncoder.wasm', WebMOpusEncoderWasmPath: 'https://cdn.jsdelivr.net/npm/opus-media-recorder@latest/WebMOpusEncoder.wasm' }; // Replace MediaRecorder window.MediaRecorder = OpusMediaRecorder; let recorder = new MediaRecorder(stream, {}, workerOptions); ... </script> ``` ### Use opus-media-recorder only when a browser doesn't support it ```javascript // Check if MediaRecorder available. if (!window.MediaRecorder) { window.MediaRecorder = OpusMediaRecorder; } // Check if a target format (e.g. audio/ogg) is supported. else if (!window.MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')) { window.MediaRecorder = OpusMediaRecorder; } ``` ## Browser support Supported: * Chrome >= 58 * Firefox >= 53 * Microsoft Edge >= 41 * Safari (macOS and iOS) >= 11 Browsers with issues: * iOS 11.2 only: Not working due to a regression in WebAssembly: https://bugs.webkit.org/show_bug.cgi?id=181781 ## MIME Type support * `audio/webm` * `audio/webm; codecs=opus` * `audio/ogg` * `audio/ogg; codecs=opus` * `audio/wav` or `audio/wave` ## Limitations * Does not support Video recording. * `opus-media-recorder` throws generic Error objects instead of native DOMException. * Because `audio/wav` is not designed for streaming, when `mimeType` is `audio/wav`, each `dataavailabe` events produces a complete and separated `.wav` file that cannot be concatenated together unlike Ogg and WebM. Therefore, it is recommended not to use `timeslice` option when calling `start()`, unless you know what the implication is. * There is no [`SecurityError`](https://w3c.github.io/mediacapture-record/#exception-summary) case implemented. (WIP) ## How to build 1. To build from the source, you need [Emscripten](https://github.com/kripken/emscripten), [yarn](https://yarnpkg.com), Python 2.7 or higher, and basic C program build systems such as [GNU Make](https://www.gnu.org/software/make/). 2. `yarn install` to install JavaScript dependencies. 3. `yarn run build` to build. `yarn run build:production` to build files for distribution. 4. `yarn run serve` to run a test web server locally. Default URL is `https://localhost:9000` (It has to be HTTPS). You might have to change `DEV_SERVER_URL` and `DEV_SERVER_PORT` to change the address of the local test server. 5. `yarn run clean` to clean up build files. ## Changelog See [CHANGELOG.md](CHANGELOG.md).