@webex/media-helpers 3.0.0-beta.126 → 3.0.0-beta.128
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/README.md +74 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/index.ts +2 -0
- package/test/unit/spec/webrtc-core.js +105 -86
package/README.md
CHANGED
|
@@ -21,6 +21,80 @@ npm install --save @webex/media-helpers
|
|
|
21
21
|
|
|
22
22
|
## Usage
|
|
23
23
|
|
|
24
|
+
### Effects
|
|
25
|
+
There are two effects included in this package:
|
|
26
|
+
|
|
27
|
+
Virtual background (e.g., blur, image replacement, video replacement)
|
|
28
|
+
Noise reduction (e.g., background noise removal)
|
|
29
|
+
|
|
30
|
+
#### Virtual background
|
|
31
|
+
The virtual background effect provides a virtual background for video calling. The virtual background may be an image, an mp4 video, or the user's background with blur applied.
|
|
32
|
+
|
|
33
|
+
**Applying the effect**
|
|
34
|
+
1. Create a new camera track instance by using LocalCameraTrack() method.
|
|
35
|
+
2. Create a VirtualBackgroundEffect instance by passing appropriate constraints.
|
|
36
|
+
3. Use addEffect() method on cameraTrack to apply effect on it.
|
|
37
|
+
4. Enable the effect after adding it to cameraTrack using enable() method available on effect. Effect will be enabled on cameraTrack.
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
import {LocalCameraTrack, VirtualBackgroundEffect} from '@webex/media-helpers';
|
|
41
|
+
|
|
42
|
+
// Create a new video stream by a getting user's video media.
|
|
43
|
+
const stream = await navigator.mediaDevices.getUserMedia({ video: { width, height } });
|
|
44
|
+
|
|
45
|
+
const videoTrackFromLocalStream = stream.getVideoTracks()[0];
|
|
46
|
+
|
|
47
|
+
const cameraTrack = new LocalCameraTrack(new MediaStream([videoTrackFromLocalStream]));
|
|
48
|
+
|
|
49
|
+
// Create the effect.
|
|
50
|
+
const effect = new VirtualBackgroundEffect({
|
|
51
|
+
authToken: '<encoded-string>',
|
|
52
|
+
mode: `BLUR`,
|
|
53
|
+
blurStrength: `STRONG`,
|
|
54
|
+
quality: `LOW`,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// add the effect on the input camera track.
|
|
58
|
+
await cameraTrack.addEffect("background-blur", effect);
|
|
59
|
+
|
|
60
|
+
//enable the effect once it is added to the track
|
|
61
|
+
await effect.enable()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### Noise reduction
|
|
65
|
+
The noise reduction effect removes background noise from an audio stream to provide clear audio for calling.
|
|
66
|
+
|
|
67
|
+
**Applying the effect**
|
|
68
|
+
1. Create a new microphone track instance by using LocalMicrophoneTrack() method.
|
|
69
|
+
2. Create a NoiseReductionEffect instance by passing appropriate constraints.
|
|
70
|
+
3. Use addEffect() method on microphoneTrack to apply effect on it.
|
|
71
|
+
4. Enable the effect after adding it to microphoneTrack using enable() method available on effect. Effect will be enabled on microphoneTrack.
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
import {LocalMicrophoneTrack, NoiseReductionEffect} from '@webex/media-helpers';
|
|
75
|
+
|
|
76
|
+
// Create a new audio stream by getting a user's audio media.
|
|
77
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
78
|
+
|
|
79
|
+
const audioTrackFromLocalStream = stream.getAudioTracks()[0];
|
|
80
|
+
|
|
81
|
+
const microphoneTrack = new LocalMicrophoneTrack(new MediaStream([audioTrackFromLocalStream]));
|
|
82
|
+
|
|
83
|
+
// Create the effect.
|
|
84
|
+
const effect = new NoiseReductionEffect({
|
|
85
|
+
authToken: '<encoded-string>',
|
|
86
|
+
workletProcessorUrl: 'https://my-worklet-processor-url', // For 'WORKLET' mode
|
|
87
|
+
legacyProcessorUrl: 'https://my-legacy-processor-url', // For 'LEGACY' mode
|
|
88
|
+
mode: 'WORKLET', // or 'LEGACY'
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// add the effect on microphone track.
|
|
92
|
+
await microphoneTrack.addEffect("background-noise-removal", effect);
|
|
93
|
+
|
|
94
|
+
//enable the effect once it is added to the track
|
|
95
|
+
await effect.enable()
|
|
96
|
+
```
|
|
97
|
+
|
|
24
98
|
## Maintainers
|
|
25
99
|
|
|
26
100
|
This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/).
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,18 @@ _Object$defineProperty(exports, "LocalTrackEvents", {
|
|
|
46
46
|
return _webrtcCore.LocalTrackEvents;
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
|
+
_Object$defineProperty(exports, "NoiseReductionEffect", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
get: function get() {
|
|
52
|
+
return _webMediaEffects.NoiseReductionEffect;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
_Object$defineProperty(exports, "VirtualBackgroundEffect", {
|
|
56
|
+
enumerable: true,
|
|
57
|
+
get: function get() {
|
|
58
|
+
return _webMediaEffects.VirtualBackgroundEffect;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
49
61
|
_Object$defineProperty(exports, "createCameraTrack", {
|
|
50
62
|
enumerable: true,
|
|
51
63
|
get: function get() {
|
|
@@ -65,4 +77,5 @@ _Object$defineProperty(exports, "createMicrophoneTrack", {
|
|
|
65
77
|
}
|
|
66
78
|
});
|
|
67
79
|
var _webrtcCore = require("./webrtc-core");
|
|
80
|
+
var _webMediaEffects = require("@webex/web-media-effects");
|
|
68
81
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export {\n LocalTrack,\n LocalDisplayTrack,\n LocalTrackEvents,\n type TrackMuteEvent,\n type ServerMuteReason,\n LocalMicrophoneTrackEvents,\n LocalCameraTrackEvents,\n LocalMicrophoneTrack,\n LocalCameraTrack,\n createMicrophoneTrack,\n createCameraTrack,\n createDisplayTrack,\n} from './webrtc-core';\n"],"mappings":"
|
|
1
|
+
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export {\n LocalTrack,\n LocalDisplayTrack,\n LocalTrackEvents,\n type TrackMuteEvent,\n type ServerMuteReason,\n LocalMicrophoneTrackEvents,\n LocalCameraTrackEvents,\n LocalMicrophoneTrack,\n LocalCameraTrack,\n createMicrophoneTrack,\n createCameraTrack,\n createDisplayTrack,\n} from './webrtc-core';\n\nexport {NoiseReductionEffect, VirtualBackgroundEffect} from '@webex/web-media-effects';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAeA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/media-helpers",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.128",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"node": ">=16"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@webex/internal-media-core": "1.38.2"
|
|
17
|
+
"@webex/internal-media-core": "1.38.2",
|
|
18
|
+
"@webex/web-media-effects": "^2.8.0"
|
|
18
19
|
},
|
|
19
20
|
"browserify": {
|
|
20
21
|
"transform": [
|
|
@@ -23,8 +24,8 @@
|
|
|
23
24
|
]
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
27
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
27
|
+
"@webex/test-helper-chai": "3.0.0-beta.128",
|
|
28
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.128",
|
|
28
29
|
"sinon": "^9.2.4"
|
|
29
30
|
}
|
|
30
31
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,115 +1,134 @@
|
|
|
1
1
|
import {assert, expect} from '@webex/test-helper-chai';
|
|
2
2
|
import sinon from 'sinon';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
LocalCameraTrack,
|
|
5
|
+
LocalMicrophoneTrack,
|
|
6
|
+
LocalMicrophoneTrackEvents,
|
|
7
|
+
LocalCameraTrackEvents,
|
|
8
|
+
LocalDisplayTrack,
|
|
9
|
+
createCameraTrack,
|
|
10
|
+
createMicrophoneTrack,
|
|
11
|
+
createDisplayTrack,
|
|
12
|
+
} from '../../../src/webrtc-core';
|
|
4
13
|
import * as wcmetracks from '@webex/internal-media-core';
|
|
5
14
|
|
|
6
15
|
describe('media-helpers', () => {
|
|
7
16
|
describe('webrtc-core', () => {
|
|
8
|
-
|
|
9
17
|
const classesToTest = [
|
|
10
|
-
{
|
|
11
|
-
|
|
18
|
+
{
|
|
19
|
+
className: LocalCameraTrack,
|
|
20
|
+
title: 'LocalCameraTrack',
|
|
21
|
+
event: LocalCameraTrackEvents,
|
|
22
|
+
createFn: createCameraTrack,
|
|
23
|
+
spyFn: 'createCameraTrack',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
className: LocalMicrophoneTrack,
|
|
27
|
+
title: 'LocalMicrophoneTrack',
|
|
28
|
+
event: LocalMicrophoneTrackEvents,
|
|
29
|
+
createFn: createMicrophoneTrack,
|
|
30
|
+
spyFn: 'createMicrophoneTrack',
|
|
31
|
+
},
|
|
12
32
|
];
|
|
13
33
|
|
|
14
34
|
classesToTest.forEach(({className, title, event, createFn, spyFn}) =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
sinon.restore();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('by default allows unmuting', async () => {
|
|
30
|
-
assert.equal(track.isUnmuteAllowed(), true);
|
|
31
|
-
await track.setMuted(false);
|
|
32
|
-
})
|
|
35
|
+
describe(title, () => {
|
|
36
|
+
const fakeStream = {
|
|
37
|
+
getTracks: sinon.stub().returns([
|
|
38
|
+
{
|
|
39
|
+
label: 'fake track',
|
|
40
|
+
id: 'fake track id',
|
|
41
|
+
enabled: true,
|
|
42
|
+
},
|
|
43
|
+
]),
|
|
44
|
+
};
|
|
45
|
+
const track = new className(fakeStream);
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
sinon.restore();
|
|
49
|
+
});
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
it('by default allows unmuting', async () => {
|
|
52
|
+
assert.equal(track.isUnmuteAllowed(), true);
|
|
53
|
+
await track.setMuted(false);
|
|
54
|
+
});
|
|
41
55
|
|
|
42
|
-
|
|
43
|
-
|
|
56
|
+
it('rejects setMute(false) if unmute is not allowed', async () => {
|
|
57
|
+
track.setUnmuteAllowed(false);
|
|
44
58
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
59
|
+
assert.equal(track.isUnmuteAllowed(), false);
|
|
60
|
+
const fn = () => track.setMuted(false);
|
|
61
|
+
expect(fn).to.throw(/Unmute is not allowed/);
|
|
62
|
+
});
|
|
48
63
|
|
|
49
|
-
|
|
64
|
+
it('resolves setMute(false) if unmute is allowed', async () => {
|
|
65
|
+
track.setUnmuteAllowed(true);
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
67
|
+
assert.equal(track.isUnmuteAllowed(), true);
|
|
68
|
+
await track.setMuted(false);
|
|
53
69
|
});
|
|
54
70
|
|
|
55
|
-
|
|
56
|
-
|
|
71
|
+
describe('#setServerMuted', () => {
|
|
72
|
+
afterEach(() => {
|
|
73
|
+
sinon.restore();
|
|
74
|
+
});
|
|
57
75
|
|
|
58
|
-
|
|
76
|
+
const checkSetServerMuted = async (startMute, setMute, expectedCalled) => {
|
|
77
|
+
await track.setMuted(startMute);
|
|
59
78
|
|
|
60
|
-
|
|
61
|
-
track.on(event.ServerMuted, handler);
|
|
79
|
+
assert.equal(track.muted, startMute);
|
|
62
80
|
|
|
63
|
-
|
|
81
|
+
const handler = sinon.fake();
|
|
82
|
+
track.on(event.ServerMuted, handler);
|
|
64
83
|
|
|
65
|
-
|
|
66
|
-
if (expectedCalled) {
|
|
67
|
-
assert.calledOnceWithExactly(handler, {muted: setMute, reason: 'remotelyMuted'});
|
|
68
|
-
} else {
|
|
69
|
-
assert.notCalled(handler);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
84
|
+
await track.setServerMuted(setMute, 'remotelyMuted');
|
|
72
85
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
});
|
|
86
|
+
assert.equal(track.muted, setMute);
|
|
87
|
+
if (expectedCalled) {
|
|
88
|
+
assert.calledOnceWithExactly(handler, {muted: setMute, reason: 'remotelyMuted'});
|
|
89
|
+
} else {
|
|
90
|
+
assert.notCalled(handler);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
it('tests true to false', async () => {
|
|
95
|
+
await checkSetServerMuted(true, false, true);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('tests false to true', async () => {
|
|
99
|
+
await checkSetServerMuted(false, true, true);
|
|
100
|
+
});
|
|
89
101
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
assert.equal(result, 'something');
|
|
98
|
-
assert.calledOnceWithExactly(spy, className, constraints);
|
|
102
|
+
it('tests true to true', async () => {
|
|
103
|
+
await checkSetServerMuted(true, true, false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('tests false to false', async () => {
|
|
107
|
+
await checkSetServerMuted(false, false, false);
|
|
108
|
+
});
|
|
99
109
|
});
|
|
100
|
-
});
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
|
|
111
|
+
describe('#wcmeCreateMicrophoneTrack, #wcmeCreateCameraTrack', () => {
|
|
112
|
+
it('checks creating tracks', async () => {
|
|
113
|
+
const constraints = {devideId: 'abc'};
|
|
104
114
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const spy = sinon.stub(wcmetracks, 'createDisplayTrack').returns('something');
|
|
108
|
-
const result = createDisplayTrack();
|
|
109
|
-
assert.equal(result, 'something');
|
|
110
|
-
assert.calledOnceWithExactly(spy, LocalDisplayTrack);
|
|
111
|
-
});
|
|
115
|
+
const spy = sinon.stub(wcmetracks, spyFn).returns('something');
|
|
116
|
+
const result = createFn(constraints);
|
|
112
117
|
|
|
118
|
+
assert.equal(result, 'something');
|
|
119
|
+
assert.calledOnceWithExactly(spy, className, constraints);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
describe('createDisplayTrack', () => {
|
|
126
|
+
it('checks createDisplayTrack', async () => {
|
|
127
|
+
const spy = sinon.stub(wcmetracks, 'createDisplayTrack').returns('something');
|
|
128
|
+
const result = createDisplayTrack();
|
|
129
|
+
assert.equal(result, 'something');
|
|
130
|
+
assert.calledOnceWithExactly(spy, LocalDisplayTrack);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
113
133
|
});
|
|
114
|
-
|
|
115
|
-
});
|
|
134
|
+
});
|