mRec
· An unobtrusive and DOM-independent JavaScript/npm package (UMD) providing utility functions to record a webcam stream using WebRTC.
π CodePen Demo (under construction)
This package relies on the MediaRecorder API. Although it is widley supported (see https://caniuse.com/?search=mediarecorder), Appleβs Safari still disables that feature by default (see https://stackoverflow.com/questions/54344342/video-recording-for-safari-browser). That means, this package only works in non-iOS environments and for non-Safari browsers.
Firefox | Chromium (Chrome, Edge, etc) |
Safari | |
---|---|---|---|
Linux | π | π | π« |
macOS | π | π | π |
Windows | π | π | π |
Android | π | π | π« |
iOS | π | π | π |
As of version 2, this package uses webpack to simplify development (see development section) and streamline the bundle output. That entails that this package now follows the UMD pattern, which allows it to be used within the following module systems: CJS, AMD, and ESM (check this article if you want to learn more about these systems).
The following snippets demonstrate how you can integrate this package into your project.
Put the following line in the head
section of your HTML
file:
<!-- index.html -->
<script src="https://unpkg.com/@ccp-eva/media-recorder" async></script>
Notes
async
attribute here, as the required DOM components are included in the js file. You can also put that line at the very end of your body
if you feel like itInserting the script under step 1 will add a global(!) property named: mrec
to your window object. Thus, you can access the utility functions/components by prepending them with mrec
(see what functions are available here).
<!-- index.html -->
<button id="toggle-btn" onclick="mrec.toggleModal()"></button>
<!-- OR -->
<button id="toggle-btn" onclick="window.mrec.toggleModal()"></button>
Similarily you may also use JavaScript to attach event listeners:
// index.js
const toggleButton = document.getElementById('toggle-btn');
toggleButton.addEventListener('click', mrec.toggleModal);
npm install @ccp-eva/media-recorder
In order to use npm packages in your browser you need a bundler. The following example uses webpack
.
npm init -y
npm i -D webpack webpack webpack-cli
Assuming your index.js
is in a src
folder, you can use ESM syntax to import components as such:
// src/index.js
// named import for a single or multiple components
// import { toggleModal } from '@ccp-eva/media-recorder'
// import all components
import * as mrec from '@ccp-eva/media-recorder';
// execute toggleModal() function
mrec.toggleModal();
Assuming your index.html
is in a dist
folder and contains:
<!-- dist/index.html -->
<html lang="en">
<head>
<script src="https://github.com/ccp-eva/media-recorder/raw/main/main.js" async></script>
</head>
<body></body>
</html>
Now you should have the following file structure:
my-project
|- /dist
|- index.html
|- /src
|- index.js
|- package.json
This file structure uses webpack defaults. Thus, if can run:
npx webpack
webpack will create a main.js
within the dist
directory. If you now open the index.html
you will see the empty modal window.
Regardless of how you install the package, you can use the following utility functions:
function | parameter | type | description |
---|
Utility Function (signature:default value) ? = optional ! = required parameter |
Description |
---|---|
injectShell() |
Injecting HTML & CSS for the modal UI (you may never need to call this function) |
logMediaDevices(showDeviceKind?:true, showDeviceLabel?:true, showDeviceId?:false) |
Will console.log device type, label and ID |
modalContent(htmlContent?:'<h1>Hi</h1>', backgroundColor?:'deeppink') |
Set the modal content: The first parameter accepts html as a string. The second parameter defines the background color of the modal.Example: modalContent("<h1>Hello</h1>") . You can also pass the predefined strings: #video-preview or #video-playback to load the corresponding video elements.Note: Calling modalContent() always opens the modal afterwards. |
toggleModal() |
show/hide the modal UI (use modalContent before to set any content) |
openVideoPreview() |
Opens the modal with the video stream by calling implicitly modalContent('#video-preview') |
openVideoPlayback() |
Opens the modal off the recorded video by calling implicitly modalContent('#video-playback') |
startStream({constraintObject}?:[1]) |
starts a webcam stream w/o recording it |
stopStream() |
stops all active webcam streams |
startRecorder({constraintObject}?:[1]) |
starts a webcam stream (if not active) and starts recording |
stopRecorder() |
stops the recording, creates a video file, stops the webcam stream |
uploadVideo("filename:") |
Parameters: string (optional) Uploads the recording using given parameter "filename". If no argument is provided, the filename defaults to a ISO 8601 timestamp. See notes about uploading. |
[1] startStream({obj})
and startRecorder({obj})
allow you tp pass a MediaTrackConstraints Object as an argument, which allows you define what media tracks (e.g., video, audio) should be recorded, and how they should be recorded (e.g., resolution, fps, facing mode). When providing no arguments, both functions default to:
{
audio: true,
video: { facingMode: 'user' },
frameRate: 15,
}
See https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia for examples you can provide to both functions.
For local development, I recommend PHP Server for VS Code).
You need to have a server-side endpoint for this function. Right now, this function only works for PHP.
upload_video.php
$target_path = "uploads/" . basename($_FILES["vidfile"]["name"] . ".webm");
move_uploaded_file($_FILES["vidfile"]["tmp_name"], $target_path );
php.ini
Change phpβs post_max_size
and upload_max_filesize
accordingly in your php.ini
, if your video is likely to exceed the default 2MB limitation:
post_max_size = 105M
upload_max_filesize = 100M
git clone git@github.com:ccp-eva/media-recorder.git
npm install
npm start
(opens a dev server on localhost:8080
)example.html
git clone git@github.com:ccp-eva/media-recorder.git
npm install
npm run build
This project uses the ESLint/AirBnb linter styles (see .eslintrc.yml
) and prettier as formatter (see .prettierrc
). As there is no CI hook for linting, it would be great if you conform to these styles/linters.