media-devices 0.1.0 → 0.3.0
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/CHANGELOG.md +41 -0
- package/README.md +57 -24
- package/dist/device-manager.d.ts +26 -16
- package/dist/enumerate-devices.d.ts +3 -2
- package/dist/index.d.ts +2 -0
- package/dist/media-devices.cjs.development.js +142 -137
- package/dist/media-devices.cjs.development.js.map +1 -1
- package/dist/media-devices.cjs.production.min.js +1 -1
- package/dist/media-devices.cjs.production.min.js.map +1 -1
- package/dist/media-devices.esm.js +135 -133
- package/dist/media-devices.esm.js.map +1 -1
- package/package.json +24 -16
- package/src/__tests__/device-manager.test.ts +106 -24
- package/src/__tests__/enumerate-devices.test.ts +6 -2
- package/src/device-manager.ts +66 -37
- package/src/enumerate-devices.ts +4 -3
- package/src/get-user-media.ts +0 -1
- package/src/index.ts +3 -0
- package/src/test-utils/index.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,53 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
|
|
2
3
|
All notable changes to this project will be documented in this file.
|
|
3
4
|
|
|
4
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
6
|
|
|
7
|
+
## [0.3.0] - 2021-12-04
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Export `DeviceChange` type which describes each object in a device change set.
|
|
12
|
+
- New `mediaDevices.ondevicechange` mutable field for listeners.
|
|
13
|
+
- Public methods are bound, no longer depending on implicit `this` context.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Querying `getDisplayMedia(...)` now refreshes the device cache for cases where browsers loosen fingerprinting countermeasures.
|
|
18
|
+
|
|
19
|
+
### Deprecated
|
|
20
|
+
|
|
21
|
+
- Using the event emitter interface is no longer advised. It will be removed in a future release. Use the `ondevicechange` field instead:
|
|
22
|
+
```diff
|
|
23
|
+
-mediaDevices.on('devicechange', handler)
|
|
24
|
+
+mediaDevices.ondevicechange = handler
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## [0.2.0] - 2021-02-23
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Another parameter added to the `devicechange` listener containing the entire list of known devices.
|
|
32
|
+
- Enum and type exports for `DeviceKind`, `DeviceInfo`, and `OperationType`.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- Made `device.groupId` a nullable field because [Safari is a monster](https://github.com/PsychoLlama/media-devices/issues/3).
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- No longer throws an error if you try to import in an unsupported environment.
|
|
41
|
+
|
|
6
42
|
## [0.1.0] - 2021-02-21
|
|
43
|
+
|
|
7
44
|
### Added
|
|
45
|
+
|
|
8
46
|
- Initial API compatible with `navigator.mediaDevices`.
|
|
9
47
|
- A device list-diffing implementation of `ondevicechange`.
|
|
10
48
|
- Support detection via `supportsMediaDevices()`.
|
|
11
49
|
|
|
50
|
+
[Unreleased]: https://github.com/PsychoLlama/media-devices/compare/v0.3.0...HEAD
|
|
51
|
+
[0.3.0]: https://github.com/PsychoLlama/media-devices/compare/v0.2.0...v0.3.0
|
|
52
|
+
[0.2.0]: https://github.com/PsychoLlama/media-devices/compare/v0.1.0...v0.2.0
|
|
12
53
|
[0.1.0]: https://github.com/PsychoLlama/media-devices/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<h1>Media Devices</h1>
|
|
3
3
|
<p>Easily manage media devices in the browser</p>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<a href="https://github.com/PsychoLlama/media-devices/actions/workflows/main.yml">
|
|
7
|
+
<img src="https://img.shields.io/github/workflow/status/PsychoLlama/media-devices/CI/main" alt="Build status" />
|
|
8
|
+
</a>
|
|
9
|
+
<img src="https://img.shields.io/npm/types/media-devices" alt="Build status" />
|
|
10
|
+
<a href="https://www.npmjs.com/package/media-devices">
|
|
11
|
+
<img src="https://img.shields.io/npm/v/media-devices" alt="npm version" />
|
|
12
|
+
</a>
|
|
13
|
+
</div>
|
|
4
14
|
</div>
|
|
5
15
|
|
|
6
16
|
## Purpose
|
|
@@ -9,7 +19,7 @@
|
|
|
9
19
|
## API
|
|
10
20
|
The API is a carbon copy of [`navigator.mediaDevices`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/mediaDevices), with the exception of `ondevicechange` which was replaced for more bells and whistles.
|
|
11
21
|
|
|
12
|
-
Here's
|
|
22
|
+
Here's the gist:
|
|
13
23
|
|
|
14
24
|
```js
|
|
15
25
|
import MediaDevices from 'media-devices'
|
|
@@ -24,43 +34,61 @@ await MediaDevices.getUserMedia({ video: true, audio: true })
|
|
|
24
34
|
await MediaDevices.getDisplayMedia()
|
|
25
35
|
|
|
26
36
|
// Listen for changes in available devices
|
|
27
|
-
MediaDevices.
|
|
37
|
+
MediaDevices.ondevicechange = ({ changes }) => {
|
|
28
38
|
// [{ type: 'add', ... }, { type: 'update', ... }]
|
|
29
|
-
}
|
|
39
|
+
}
|
|
30
40
|
```
|
|
31
41
|
|
|
32
|
-
### `
|
|
33
|
-
|
|
42
|
+
### `supportsMediaDevices()`
|
|
43
|
+
Exported as a separate utility function, this helps determine if your browser supports the `navigator.mediaDevices` API. Be aware that some browsers only expose it on secure sites.
|
|
34
44
|
|
|
35
45
|
```js
|
|
36
|
-
|
|
37
|
-
type: 'add';
|
|
38
|
-
device: DeviceInfo;
|
|
39
|
-
}
|
|
46
|
+
import { supportsMediaDevices } from 'media-devices'
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
device: DeviceInfo;
|
|
48
|
+
if (supportsMediaDevices()) {
|
|
49
|
+
// yey
|
|
44
50
|
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `ondevicechange`
|
|
54
|
+
`MediaDevices` emits this event whenever the list of devices changes. It passes two things:
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
1. A list of changes
|
|
57
|
+
1. The full list of devices
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
MediaDevices.ondevicechange = ({ changes, devices }) => {
|
|
61
|
+
// ...
|
|
50
62
|
}
|
|
51
63
|
```
|
|
52
64
|
|
|
53
|
-
|
|
54
|
-
Exported as a separate utility function, this helps determine if your browser supports the `navigator.mediaDevices` API. Be aware that some browsers only expose it on secure sites.
|
|
65
|
+
The list of devices is exactly what you'd get from `enumerateDevices()`. The changes are a diff between this list and the last, showing which devices were added, which were removed, and which were updated.
|
|
55
66
|
|
|
56
67
|
```js
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
[
|
|
69
|
+
// A device was just plugged in.
|
|
70
|
+
{
|
|
71
|
+
type: 'add',
|
|
72
|
+
device: DeviceInfo,
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// A device was disconnected.
|
|
76
|
+
{
|
|
77
|
+
type: 'remove',
|
|
78
|
+
device: DeviceInfo,
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
// The browser gave us more information about a device.
|
|
82
|
+
{
|
|
83
|
+
type: 'update',
|
|
84
|
+
oldInfo: DeviceInfo,
|
|
85
|
+
newInfo: DeviceInfo,
|
|
86
|
+
},
|
|
87
|
+
]
|
|
62
88
|
```
|
|
63
89
|
|
|
90
|
+
Update events are odd. Browsers redact information until the user explicitly grants trust, so things like labels and device IDs might start off null. [Another quirk](#speaker-replacement) regarding speakers may cause the device to update in-place.
|
|
91
|
+
|
|
64
92
|
---------------
|
|
65
93
|
|
|
66
94
|
## Known Quirks
|
|
@@ -85,8 +113,13 @@ That makes it hard to tell whether the device list actually changed. This librar
|
|
|
85
113
|
|
|
86
114
|
Device IDs are set to `null` in this case.
|
|
87
115
|
|
|
116
|
+
### Missing Group IDs
|
|
117
|
+
As of Safari v14, even with permissions, the browser doesn't provide group IDs. Why? Because they're monsters.
|
|
118
|
+
|
|
119
|
+
Group IDs are `null` in Safari.
|
|
120
|
+
|
|
88
121
|
### Hidden Devices
|
|
89
|
-
Chrome only
|
|
122
|
+
Chrome and Safari only show the first of each device type (mic, camera, speakers) until `getUserMedia(...)` is approved. Other options are hidden. If you have 10 cameras, you'll only see the first until you're authorized. Even then, Chrome only shows you cameras, microphones are still hidden.
|
|
90
123
|
|
|
91
124
|
While we can't work around it, we can automatically identify that old camera in the list of 10 and show the other 9 as added devices.
|
|
92
125
|
|
package/dist/device-manager.d.ts
CHANGED
|
@@ -7,33 +7,42 @@ import { DeviceInfo } from './enumerate-devices';
|
|
|
7
7
|
* attempts graceful integration with browser fingerprinting countermeasures.
|
|
8
8
|
*/
|
|
9
9
|
export default class DeviceManager extends EventEmitter {
|
|
10
|
-
_knownDevices
|
|
10
|
+
private _knownDevices;
|
|
11
|
+
private _gainedScreenAccessOnce;
|
|
12
|
+
/**
|
|
13
|
+
* Specifies a function to be called whenever the list of available devices
|
|
14
|
+
* changes.
|
|
15
|
+
*
|
|
16
|
+
* Note: this is different from the native event. It passes the changeset
|
|
17
|
+
* and full list of devices as a parameter.
|
|
18
|
+
*/
|
|
19
|
+
ondevicechange: null | DeviceChangeListener;
|
|
11
20
|
constructor();
|
|
12
21
|
/**
|
|
13
22
|
* Request a live media stream from audio and/or video devices. Streams are
|
|
14
23
|
* configurable through constraints.
|
|
15
24
|
* See: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
|
16
25
|
*/
|
|
17
|
-
getUserMedia(constraints: MediaStreamConstraints)
|
|
26
|
+
getUserMedia: (constraints: MediaStreamConstraints) => Promise<MediaStream>;
|
|
18
27
|
/**
|
|
19
28
|
* Ask the user to share their screen. Resolves with a media stream carrying
|
|
20
29
|
* video, and potentially audio from the application window.
|
|
21
30
|
* See: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia
|
|
22
31
|
*/
|
|
23
|
-
getDisplayMedia(constraints?: MediaStreamConstraints)
|
|
32
|
+
getDisplayMedia: (constraints?: MediaStreamConstraints | undefined) => Promise<MediaStream>;
|
|
24
33
|
/**
|
|
25
34
|
* Lists every available hardware device, including microphones, cameras,
|
|
26
35
|
* and speakers (depending on browser support). May contain redacted
|
|
27
36
|
* information depending on application permissions.
|
|
28
37
|
*/
|
|
29
|
-
enumerateDevices()
|
|
38
|
+
enumerateDevices: () => Promise<Array<DeviceInfo>>;
|
|
30
39
|
/**
|
|
31
40
|
* Returns an object containing every media constraint supported by the
|
|
32
41
|
* browser.
|
|
33
42
|
* See: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getSupportedConstraints
|
|
34
43
|
*/
|
|
35
|
-
getSupportedConstraints()
|
|
36
|
-
_checkForDeviceChanges
|
|
44
|
+
getSupportedConstraints: () => MediaTrackSupportedConstraints;
|
|
45
|
+
private _checkForDeviceChanges;
|
|
37
46
|
/**
|
|
38
47
|
* Note: The device enumeration API may return null values for device IDs
|
|
39
48
|
* and labels. To avoid creating erroneous "Device Added" notifications,
|
|
@@ -43,30 +52,31 @@ export default class DeviceManager extends EventEmitter {
|
|
|
43
52
|
* correlate devices from permissioned requests with unpermissioned
|
|
44
53
|
* requests.
|
|
45
54
|
*/
|
|
46
|
-
_calculateDeviceDiff
|
|
55
|
+
private _calculateDeviceDiff;
|
|
47
56
|
}
|
|
48
|
-
declare type DeviceChange = DeviceAddEvent | DeviceRemoveEvent | DeviceUpdateEvent;
|
|
57
|
+
export declare type DeviceChange = DeviceAddEvent | DeviceRemoveEvent | DeviceUpdateEvent;
|
|
49
58
|
interface DeviceAddEvent {
|
|
50
|
-
type:
|
|
59
|
+
type: OperationType.Add;
|
|
51
60
|
device: DeviceInfo;
|
|
52
61
|
}
|
|
53
62
|
interface DeviceRemoveEvent {
|
|
54
|
-
type:
|
|
63
|
+
type: OperationType.Remove;
|
|
55
64
|
device: DeviceInfo;
|
|
56
65
|
}
|
|
57
66
|
interface DeviceUpdateEvent {
|
|
58
|
-
type:
|
|
67
|
+
type: OperationType.Update;
|
|
59
68
|
newInfo: DeviceInfo;
|
|
60
69
|
oldInfo: DeviceInfo;
|
|
61
70
|
}
|
|
62
|
-
export declare enum
|
|
71
|
+
export declare enum OperationType {
|
|
63
72
|
Add = "add",
|
|
64
73
|
Remove = "remove",
|
|
65
74
|
Update = "update"
|
|
66
75
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
interface DeviceChangeListener {
|
|
77
|
+
(update: {
|
|
78
|
+
changes: Array<DeviceChange>;
|
|
79
|
+
devices: Array<DeviceInfo>;
|
|
80
|
+
}): unknown;
|
|
71
81
|
}
|
|
72
82
|
export {};
|
|
@@ -23,9 +23,10 @@ export interface DeviceInfo {
|
|
|
23
23
|
/**
|
|
24
24
|
* A unique identifier grouping one or more devices together. Two devices
|
|
25
25
|
* with the same group ID symbolise that both devices belong to the same
|
|
26
|
-
* hardware, e.g. a webcam with an integrated microphone.
|
|
26
|
+
* hardware, e.g. a webcam with an integrated microphone. Note: Safari
|
|
27
|
+
* doesn't support group IDs.
|
|
27
28
|
*/
|
|
28
|
-
groupId: string;
|
|
29
|
+
groupId: null | string;
|
|
29
30
|
/**
|
|
30
31
|
* Declares the type of media provided. This covers microphones, cameras,
|
|
31
32
|
* and speakers.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import DeviceManager from './device-manager';
|
|
2
2
|
export { supportsMediaDevices } from './support-detection';
|
|
3
|
+
export { DeviceInfo, DeviceKind } from './enumerate-devices';
|
|
4
|
+
export { OperationType, DeviceChange } from './device-manager';
|
|
3
5
|
declare const _default: DeviceManager;
|
|
4
6
|
export default _default;
|