Abstract away all the quirks of handling media devices
A library that will handle media by wrapping
enumerateDevices
and getUserMedia
extending both functions with additional logic.
npm install @pexip/media-control
This library is meant to extend the mediaDevices
api methods
such as getUserMedia
, enumerateDevices
and events on media streams and tracks.
The final goal is to have a library that gives a stable and robust way to use these methods while guaranteeing that the developer has better control over which devices are delivered, fail, or exist.
The package is published to Github registry scoped with @pexip. Access right to @pexip is needed in order to install the package.
Here is the steps to setup Github Personal Access Token for npm
/yarn
in
order to add the package.
-
A Github Personal Access Token is needed to be setup in order to get the @pexip/media-control package. Follow Github's doc to create a Personal Access Token.
-
When the Personal Access Token is ready, you can set it up for
npm
oryarn
via.npmrc
. By adding your personal access token to your~/.npmrc
file, edit the~/.npmrc
file for your project to include the following line, replacing TOKEN with your personal access token. Create a new~/.npmrc
file if one doesn't exist.//npm.pkg.github.com/:_authToken=TOKEN
-
Add a local
.npmrc
file to your repository with the following lines to tell the package manager,npm
oryarn
where the registry is for@pexip
scoped packages.@pexip:registry=https://npm.pkg.github.com
-
Now it is ready to add any
@pexip/PACKAGE_NAME
package to your repository.# Use yarn yarn add @pexip/media-control # Or use npm npm install @pexip/media-control
P.S.: there is no polyfill added to this package, the user needs to add
polyfill to the application, i.e. core-js
. We leverage on
@babel/plugin-transform-runtime
and @babel/runtime
to accomplish this.
Get stream with audio and video without specifying devices, let the browser choose the right devices.
import {getUserMedia} from '@pexip/media-control';
const stream = await getUserMedia({audio: true, video: true});
Only get stream with video
import {getUserMedia} from '@pexip/media-control';
// neglecting audioInput is the same as setting it explicitly to false
const stream = await getUserMedia({video: true});
Get stream with the specific device only but any for audio.
import {getUserMedia} from 'media-control';
const videoInputWanted = {
deviceId: '0abbc454-71e5-4f7e-9c8b-9de36f1334c3',
kind: 'videoinput',
label: 'Camera',
};
const stream = await getUserMedia({
audio: true,
video: {device: {exact: videoInputWanted}},
});
Get stream with specific video input and fallback if it's not available and the specific audio input only, no fallback
import {getUserMedia} from 'media-control';
const audioInput = {
deviceId: 'a373b235-3ebf-40c7-b619-a491e05e35e6',
label: "Rick's Microphone",
kind: 'audioinput',
};
const videoInput = {
deviceId: '0abbc454-71e5-4f7e-9c8b-9de36f1334c3',
label: "Morty's Camera",
kind: 'videoinput',
};
const stream = await getUserMedia({
audio: {device: {exact: audioInput}},
video: videoInput,
});
Get stream with specific devices and fallback when they are not available
import {getUserMedia} from 'media-control';
const audioInput = {
deviceId: 'a373b235-3ebf-40c7-b619-a491e05e35e6',
label: "Rick's Microphone",
kind: 'audioinput',
};
const videoInput = {
deviceId: '0abbc454-71e5-4f7e-9c8b-9de36f1334c3',
label: "Morty's Camera",
kind: 'videoinput',
};
const stream = await getUserMedia({
audio: audioInput,
video: videoInput,
});
The following requests both audio and video without any specific requirements:
import {getUserMedia} from 'media-control';
const stream = await getUserMedia({audio: true, video: true});
The following expresses a preference for 1280x720 camera resolution:
import {getUserMedia} from 'media-control';
const stream = await getUserMedia({
audio: true,
video: {
width: 1280,
height: 720,
},
});
The following expresses a preference for user facing camera:
import {getUserMedia} from 'media-control';
const stream = await getUserMedia({
audio: true,
video: {facingMode: 'user'},
});
import {MediaEventType, subscribe} from 'media-control';
subscribe((event: MediaEvent) => {
switch (event.detail.type) {
case MediaEventType.Mute: // {id: string}
// id of the device that was muted
const id = event.detail.id;
break;
case MediaEventType.Unmute: // {id: string}
// id of the device that was unmuted
const id = event.detail.id;
break;
case MediaEventType.Ended: // {id: string}
// id of the device that ended
const id = event.detail.id;
break;
case MediaEventType.DevicesChanged: // {devices: MediaDeviceInfo[]}
// devices currently available through enumerateDevices
const devices = event.detail.devices;
break;
case MediaEventType.DevicesFound: // {devices: MediaDeviceInfo[], authorizedDevices: MediaDeviceInfo[]}
// new devices connected
const devices = event.detail.devices;
break;
case MediaEventType.DevicesLost: // {devices: MediaDeviceInfo[], authorizedDevices: MediaDeviceInfo[]}
// devices lost from the enumerateDevices list
const devices = event.detail.devices;
break;
case MediaEventType.DeviceLost: // {device: MediaDeviceInfo}
// device currently in use that was lost from the enumerateDevices list
const device = event.detail.device;
break;
case MediaEventType.DevicesUnauthorized: // {devices: MediaDeviceInfo[], authorizedDevices: MediaDeviceInfo[]}
// Unauthorized list of devices
const device = event.detail.devices;
break;
case MediaEventType.NoInputDevices:
// Indicate that there is no input devices from the machine
break;
case MediaEventType.Error: // {error: Error}
const error = event.detail.error;
break;
}
});