twilio-video 2.24.2 → 2.25.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 +72 -0
- package/COMMON_ISSUES.md +4 -48
- package/README.md +1 -2
- package/dist/twilio-video.js +188 -71
- package/dist/twilio-video.min.js +21 -21
- package/es5/createlocaltrack.js +10 -2
- package/es5/createlocaltrack.js.map +1 -1
- package/es5/createlocaltracks.js +20 -8
- package/es5/createlocaltracks.js.map +1 -1
- package/es5/media/track/audiotrack.js +0 -11
- package/es5/media/track/audiotrack.js.map +1 -1
- package/es5/media/track/localaudiotrack.js +112 -0
- package/es5/media/track/localaudiotrack.js.map +1 -1
- package/es5/media/track/localmediatrack.js +3 -6
- package/es5/media/track/localmediatrack.js.map +1 -1
- package/es5/media/track/localvideotrack.js +2 -2
- package/es5/media/track/localvideotrack.js.map +1 -1
- package/es5/media/track/mediatrack.js +3 -3
- package/es5/media/track/mediatrack.js.map +1 -1
- package/es5/media/track/remoteaudiotrack.js +12 -0
- package/es5/media/track/remoteaudiotrack.js.map +1 -1
- package/es5/media/track/remotemediatrack.js +2 -2
- package/es5/media/track/remotemediatrack.js.map +1 -1
- package/es5/util/browserdetection.js +16 -15
- package/es5/util/browserdetection.js.map +1 -1
- package/es5/webrtc/rtcpeerconnection/firefox.js +0 -14
- package/es5/webrtc/rtcpeerconnection/firefox.js.map +1 -1
- package/lib/createlocaltrack.js +10 -2
- package/lib/createlocaltracks.ts +32 -11
- package/lib/media/track/audiotrack.js +0 -12
- package/lib/media/track/localaudiotrack.js +112 -0
- package/lib/media/track/localmediatrack.js +2 -5
- package/lib/media/track/localvideotrack.js +2 -3
- package/lib/media/track/mediatrack.js +2 -2
- package/lib/media/track/remoteaudiotrack.js +13 -0
- package/lib/media/track/remotemediatrack.js +2 -2
- package/lib/util/browserdetection.js +16 -15
- package/lib/webrtc/rtcpeerconnection/firefox.js +0 -16
- package/package.json +2 -2
- package/tsdef/index.d.ts +1 -0
- package/tsdef/types.d.ts +2 -0
|
@@ -23,36 +23,37 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
23
23
|
function isAndroid() {
|
|
24
24
|
return /Android/.test(navigator.userAgent);
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Check whether the current browser is an iOS device.
|
|
28
|
-
* @returns {boolean}
|
|
29
|
-
*/
|
|
30
|
-
function isIOS() {
|
|
31
|
-
return /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
32
|
-
}
|
|
33
26
|
/**
|
|
34
27
|
* Detects whether or not a device is an Apple touch screen device.
|
|
35
28
|
* @returns {boolean}
|
|
36
29
|
*/
|
|
37
30
|
function hasTouchScreen() {
|
|
38
|
-
return navigator && navigator.maxTouchPoints &&
|
|
39
|
-
navigator.maxTouchPoints > 2;
|
|
31
|
+
return !!(navigator && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);
|
|
40
32
|
}
|
|
41
33
|
/**
|
|
42
|
-
* Detects whether or not a device is an iPad
|
|
34
|
+
* Detects whether or not a device is an iPad.
|
|
43
35
|
* @returns {boolean}
|
|
44
36
|
*/
|
|
45
37
|
function isIpad() {
|
|
46
|
-
return hasTouchScreen() && window.screen.width >= 744 &&
|
|
47
|
-
|
|
38
|
+
return hasTouchScreen() && window.screen.width >= 744 && (/Macintosh/i.test(navigator.userAgent)
|
|
39
|
+
|| /iPad/.test(navigator.userAgent)
|
|
40
|
+
|| /iPad/.test(navigator.platform));
|
|
48
41
|
}
|
|
49
42
|
/**
|
|
50
|
-
* Detects whether or not a device is an iPhone
|
|
43
|
+
* Detects whether or not a device is an iPhone.
|
|
51
44
|
* @returns {boolean}
|
|
52
45
|
*/
|
|
53
46
|
function isIphone() {
|
|
54
|
-
return hasTouchScreen() && window.screen.width <= 476 &&
|
|
55
|
-
|
|
47
|
+
return hasTouchScreen() && window.screen.width <= 476 && (/Macintosh/i.test(navigator.userAgent)
|
|
48
|
+
|| /iPhone/.test(navigator.userAgent)
|
|
49
|
+
|| /iPhone/.test(navigator.platform));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check whether the current device is an iOS device.
|
|
53
|
+
* @returns {boolean}
|
|
54
|
+
*/
|
|
55
|
+
function isIOS() {
|
|
56
|
+
return isIpad() || isIphone();
|
|
56
57
|
}
|
|
57
58
|
/**
|
|
58
59
|
* Check whether the current browser is a mobile browser
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserdetection.js","sourceRoot":"","sources":["../../lib/util/browserdetection.js"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,YAAY,CAAC;;;;;;;;;;;;;;;;;AAEb;;;GAGG;AACH,SAAS,SAAS;IAChB,OAAO,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,SAAS,
|
|
1
|
+
{"version":3,"file":"browserdetection.js","sourceRoot":"","sources":["../../lib/util/browserdetection.js"],"names":[],"mappings":"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"}
|
|
@@ -5,12 +5,6 @@ var FirefoxRTCSessionDescription = require('../rtcsessiondescription/firefox');
|
|
|
5
5
|
var inherits = require('../../vendor/inherits');
|
|
6
6
|
var updateTracksToSSRCs = require('../util/sdp').updateUnifiedPlanTrackIdsToSSRCs;
|
|
7
7
|
var util = require('../util');
|
|
8
|
-
// NOTE(mroberts): This is a short-lived workaround. Checking the user agent
|
|
9
|
-
// string might not fix every affected Firefox instance, but it should be good
|
|
10
|
-
// enough for this bug.
|
|
11
|
-
var needsWorkaroundForBug1480277 = typeof navigator === 'object'
|
|
12
|
-
&& navigator.userAgent
|
|
13
|
-
&& (navigator.userAgent.match(/Firefox\/61/) || navigator.userAgent.match(/Firefox\/62/));
|
|
14
8
|
// NOTE(mroberts): This class wraps Firefox's RTCPeerConnection implementation.
|
|
15
9
|
// It provides some functionality not currently present in Firefox, namely the
|
|
16
10
|
// abilities to
|
|
@@ -109,14 +103,6 @@ Object.defineProperty(FirefoxRTCPeerConnection.prototype, 'peerIdentity', {
|
|
|
109
103
|
name: ''
|
|
110
104
|
})
|
|
111
105
|
});
|
|
112
|
-
if (needsWorkaroundForBug1480277) {
|
|
113
|
-
FirefoxRTCPeerConnection.prototype.addTrack = function addTrack() {
|
|
114
|
-
var track = arguments[0];
|
|
115
|
-
var sender = this._peerConnection.addTrack.apply(this._peerConnection, arguments);
|
|
116
|
-
sender.replaceTrack(track);
|
|
117
|
-
return sender;
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
106
|
FirefoxRTCPeerConnection.prototype.createAnswer = function createAnswer() {
|
|
121
107
|
var args = [].slice.call(arguments);
|
|
122
108
|
var promise;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firefox.js","sourceRoot":"","sources":["../../../lib/webrtc/rtcpeerconnection/firefox.js"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,YAAY,CAAC;AAEb,IAAI,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AACjD,IAAI,4BAA4B,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;AAC/E,IAAI,QAAQ,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAChD,IAAI,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,gCAAgC,CAAC;AAClF,IAAI,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAE9B
|
|
1
|
+
{"version":3,"file":"firefox.js","sourceRoot":"","sources":["../../../lib/webrtc/rtcpeerconnection/firefox.js"],"names":[],"mappings":"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"}
|
package/lib/createlocaltrack.js
CHANGED
|
@@ -124,8 +124,16 @@ const NoiseCancellationVendor = {
|
|
|
124
124
|
* @property {boolean} [workaroundWebKitBug180748=false] - setting this
|
|
125
125
|
* attempts to workaround WebKit Bug 180748, where, in Safari, getUserMedia may return a silent audio
|
|
126
126
|
* MediaStreamTrack.
|
|
127
|
-
* @property {
|
|
128
|
-
*
|
|
127
|
+
* @property {DefaultDeviceCaptureMode} [defaultDeviceCaptureMode="auto"] - This optional property only applies if the
|
|
128
|
+
* {@link LocalAudioTrack} is capturing from the default audio input device connected to a desktop or laptop. When the
|
|
129
|
+
* property is set to "auto", the LocalAudioTrack restarts whenever the default audio input device changes, in order to
|
|
130
|
+
* capture audio from the new default audio input device. For example, when a bluetooth audio headset is connected to a
|
|
131
|
+
* Macbook, the LocalAudioTrack will start capturing audio from the headset microphone. When the headset is disconnected,
|
|
132
|
+
* the LocalAudioTrack will start capturing audio from the Macbook microphone. When the property is set to "manual", the
|
|
133
|
+
* LocalAudioTrack continues to capture from the same audio input device even after the default audio input device changes.
|
|
134
|
+
* When the property is not specified, it defaults to "auto".
|
|
135
|
+
* @property {NoiseCancellationOptions} [noiseCancellationOptions] - This optional property enables using 3rd party plugins
|
|
136
|
+
* for noise cancellation.
|
|
129
137
|
*/
|
|
130
138
|
|
|
131
139
|
/**
|
package/lib/createlocaltracks.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CreateLocalAudioTrackOptions,
|
|
6
|
+
CreateLocalTrackOptions,
|
|
7
|
+
CreateLocalTracksOptions,
|
|
8
|
+
DefaultDeviceCaptureMode,
|
|
9
|
+
LocalTrack,
|
|
10
|
+
NoiseCancellationOptions
|
|
11
|
+
} from '../tsdef';
|
|
12
|
+
|
|
5
13
|
import { applyNoiseCancellation } from './media/track/noisecancellationimpl';
|
|
6
14
|
|
|
7
15
|
const { buildLogLevels } = require('./util');
|
|
@@ -14,7 +22,7 @@ const {
|
|
|
14
22
|
} = require('./media/track/es5');
|
|
15
23
|
|
|
16
24
|
const Log = require('./util/log');
|
|
17
|
-
const { DEFAULT_LOG_LEVEL, DEFAULT_LOGGER_NAME } = require('./util/constants');
|
|
25
|
+
const { DEFAULT_LOG_LEVEL, DEFAULT_LOGGER_NAME, typeErrors: { INVALID_VALUE } } = require('./util/constants');
|
|
18
26
|
const workaround180748 = require('./webaudio/workaround180748');
|
|
19
27
|
|
|
20
28
|
// This is used to make out which createLocalTracks() call a particular Log
|
|
@@ -24,7 +32,8 @@ let createLocalTrackCalls = 0;
|
|
|
24
32
|
|
|
25
33
|
|
|
26
34
|
type ExtraLocalTrackOption = CreateLocalTrackOptions & { isCreatedByCreateLocalTracks?: boolean };
|
|
27
|
-
type
|
|
35
|
+
type ExtraLocalAudioTrackOption = ExtraLocalTrackOption & { defaultDeviceCaptureMode? : DefaultDeviceCaptureMode };
|
|
36
|
+
type ExtraLocalTrackOptions = { audio: ExtraLocalAudioTrackOption; video: ExtraLocalTrackOption; };
|
|
28
37
|
|
|
29
38
|
interface InternalOptions extends CreateLocalTracksOptions {
|
|
30
39
|
getUserMedia: any;
|
|
@@ -138,7 +147,7 @@ export async function createLocalTracks(options?: CreateLocalTracksOptions): Pro
|
|
|
138
147
|
const extraLocalTrackOptions: ExtraLocalTrackOptions = {
|
|
139
148
|
audio: typeof fullOptions.audio === 'object' && fullOptions.audio.name
|
|
140
149
|
? { name: fullOptions.audio.name }
|
|
141
|
-
: {},
|
|
150
|
+
: { defaultDeviceCaptureMode: 'auto' },
|
|
142
151
|
video: typeof fullOptions.video === 'object' && fullOptions.video.name
|
|
143
152
|
? { name: fullOptions.video.name }
|
|
144
153
|
: {}
|
|
@@ -147,14 +156,26 @@ export async function createLocalTracks(options?: CreateLocalTracksOptions): Pro
|
|
|
147
156
|
extraLocalTrackOptions.audio.isCreatedByCreateLocalTracks = true;
|
|
148
157
|
extraLocalTrackOptions.video.isCreatedByCreateLocalTracks = true;
|
|
149
158
|
|
|
150
|
-
|
|
151
|
-
extraLocalTrackOptions.audio.workaroundWebKitBug1208516 = fullOptions.audio.workaroundWebKitBug1208516;
|
|
152
|
-
}
|
|
159
|
+
let noiseCancellationOptions: NoiseCancellationOptions | undefined;
|
|
153
160
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
161
|
+
if (typeof fullOptions.audio === 'object') {
|
|
162
|
+
if (typeof fullOptions.audio.workaroundWebKitBug1208516 === 'boolean') {
|
|
163
|
+
extraLocalTrackOptions.audio.workaroundWebKitBug1208516 = fullOptions.audio.workaroundWebKitBug1208516;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if ('noiseCancellationOptions' in fullOptions.audio) {
|
|
167
|
+
noiseCancellationOptions = fullOptions.audio.noiseCancellationOptions;
|
|
168
|
+
delete fullOptions.audio.noiseCancellationOptions;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!('defaultDeviceCaptureMode' in fullOptions.audio)) {
|
|
172
|
+
extraLocalTrackOptions.audio.defaultDeviceCaptureMode = 'auto';
|
|
173
|
+
} else if (['auto', 'manual'].every(mode => mode !== (fullOptions.audio as CreateLocalAudioTrackOptions).defaultDeviceCaptureMode)) {
|
|
174
|
+
// eslint-disable-next-line new-cap
|
|
175
|
+
throw INVALID_VALUE('CreateLocalAudioTrackOptions.defaultDeviceCaptureMode', ['auto', 'manual']);
|
|
176
|
+
} else {
|
|
177
|
+
extraLocalTrackOptions.audio.defaultDeviceCaptureMode = fullOptions.audio.defaultDeviceCaptureMode;
|
|
178
|
+
}
|
|
158
179
|
}
|
|
159
180
|
|
|
160
181
|
if (typeof fullOptions.video === 'object' && typeof fullOptions.video.workaroundWebKitBug1208516 === 'boolean') {
|
|
@@ -28,18 +28,6 @@ class AudioTrack extends MediaTrack {
|
|
|
28
28
|
super(mediaTrackTransceiver, options);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/**
|
|
32
|
-
* @private
|
|
33
|
-
*/
|
|
34
|
-
_start() {
|
|
35
|
-
super._start();
|
|
36
|
-
if (this._dummyEl) {
|
|
37
|
-
// once started let go of dummy element
|
|
38
|
-
this._dummyEl.srcObject = null;
|
|
39
|
-
this._dummyEl = null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
31
|
/**
|
|
44
32
|
* Create an HTMLAudioElement and attach the {@link AudioTrack} to it.
|
|
45
33
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { isIOS } = require('../../util/browserdetection');
|
|
3
4
|
const AudioTrack = require('./audiotrack');
|
|
4
5
|
const mixinLocalMediaTrack = require('./localmediatrack');
|
|
5
6
|
|
|
@@ -33,13 +34,63 @@ class LocalAudioTrack extends LocalMediaAudioTrack {
|
|
|
33
34
|
const noiseCancellation = options?.noiseCancellation || null;
|
|
34
35
|
super(mediaStreamTrack, options);
|
|
35
36
|
|
|
37
|
+
const { _log: log } = this;
|
|
38
|
+
const { label: defaultDeviceLabel = '' } = mediaStreamTrack;
|
|
39
|
+
const { deviceId: defaultDeviceId = '', groupId: defaultGroupId = '' } = mediaStreamTrack.getSettings();
|
|
40
|
+
|
|
36
41
|
Object.defineProperties(this, {
|
|
42
|
+
_currentDefaultDeviceInfo: {
|
|
43
|
+
value: { deviceId: defaultDeviceId, groupId: defaultGroupId, label: defaultDeviceLabel },
|
|
44
|
+
writable: true
|
|
45
|
+
},
|
|
46
|
+
_defaultDeviceCaptureMode: {
|
|
47
|
+
value: !isIOS()
|
|
48
|
+
&& this._isCreatedByCreateLocalTracks
|
|
49
|
+
&& typeof navigator === 'object'
|
|
50
|
+
&& typeof navigator.mediaDevices === 'object'
|
|
51
|
+
&& typeof navigator.mediaDevices.addEventListener === 'function'
|
|
52
|
+
&& typeof navigator.mediaDevices.enumerateDevices === 'function'
|
|
53
|
+
? options?.defaultDeviceCaptureMode || 'auto'
|
|
54
|
+
: 'manual'
|
|
55
|
+
},
|
|
56
|
+
_onDeviceChange: {
|
|
57
|
+
value: () => {
|
|
58
|
+
navigator.mediaDevices.enumerateDevices().then(deviceInfos => {
|
|
59
|
+
// NOTE(mmalavalli): In Chrome, when the default device changes, and we restart the LocalAudioTrack with
|
|
60
|
+
// device ID "default", it will not switch to the new default device unless all LocalAudioTracks capturing
|
|
61
|
+
// from the old default device are stopped. So, we restart the LocalAudioTrack with the actual device ID of
|
|
62
|
+
// the new default device instead.
|
|
63
|
+
const defaultDeviceInfo = deviceInfos.find(({ deviceId, kind }) => {
|
|
64
|
+
return kind === 'audioinput' && deviceId !== 'default';
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (defaultDeviceInfo && ['deviceId', 'groupId'].some(prop => {
|
|
68
|
+
return defaultDeviceInfo[prop] !== this._currentDefaultDeviceInfo[prop];
|
|
69
|
+
})) {
|
|
70
|
+
log.info('Default device changed, restarting the LocalAudioTrack');
|
|
71
|
+
log.debug(`Old default device: "${this._currentDefaultDeviceInfo.deviceId}" => "${this._currentDefaultDeviceInfo.label}"`);
|
|
72
|
+
log.debug(`New default device: "${defaultDeviceInfo.deviceId}" => "${defaultDeviceInfo.label}"`);
|
|
73
|
+
this._currentDefaultDeviceInfo = defaultDeviceInfo;
|
|
74
|
+
this._restartDefaultDevice().catch(error => log.warn(`Failed to restart: ${error.message}`));
|
|
75
|
+
}
|
|
76
|
+
}, error => {
|
|
77
|
+
log.warn(`Failed to run enumerateDevices(): ${error.message}`);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
_restartOnDefaultDeviceChangeCleanup: {
|
|
82
|
+
value: null,
|
|
83
|
+
writable: true
|
|
84
|
+
},
|
|
37
85
|
noiseCancellation: {
|
|
38
86
|
enumerable: true,
|
|
39
87
|
value: noiseCancellation,
|
|
40
88
|
writable: false
|
|
41
89
|
},
|
|
42
90
|
});
|
|
91
|
+
|
|
92
|
+
log.debug('defaultDeviceCaptureMode:', this._defaultDeviceCaptureMode);
|
|
93
|
+
this._maybeRestartOnDefaultDeviceChange();
|
|
43
94
|
}
|
|
44
95
|
|
|
45
96
|
toString() {
|
|
@@ -59,6 +110,49 @@ class LocalAudioTrack extends LocalMediaAudioTrack {
|
|
|
59
110
|
return super._end.apply(this, arguments);
|
|
60
111
|
}
|
|
61
112
|
|
|
113
|
+
/**
|
|
114
|
+
* @private
|
|
115
|
+
*/
|
|
116
|
+
_maybeRestartOnDefaultDeviceChange() {
|
|
117
|
+
const { _constraints: constraints, _defaultDeviceCaptureMode: defaultDeviceCaptureMode, _log: log } = this;
|
|
118
|
+
const mediaStreamTrack = this.noiseCancellation ? this.noiseCancellation.sourceTrack : this.mediaStreamTrack;
|
|
119
|
+
const { deviceId } = mediaStreamTrack.getSettings();
|
|
120
|
+
|
|
121
|
+
const isNotEqualToCapturedDeviceIdOrEqualToDefault = requestedDeviceId => {
|
|
122
|
+
return requestedDeviceId !== deviceId || requestedDeviceId === 'default';
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const isCapturingFromDefaultDevice = (function checkIfCapturingFromDefaultDevice(deviceIdConstraint = {}) {
|
|
126
|
+
if (typeof deviceIdConstraint === 'string') {
|
|
127
|
+
return isNotEqualToCapturedDeviceIdOrEqualToDefault(deviceIdConstraint);
|
|
128
|
+
} else if (Array.isArray(deviceIdConstraint)) {
|
|
129
|
+
return deviceIdConstraint.every(isNotEqualToCapturedDeviceIdOrEqualToDefault);
|
|
130
|
+
} else if (deviceIdConstraint.exact) {
|
|
131
|
+
return checkIfCapturingFromDefaultDevice(deviceIdConstraint.exact);
|
|
132
|
+
} else if (deviceIdConstraint.ideal) {
|
|
133
|
+
return checkIfCapturingFromDefaultDevice(deviceIdConstraint.ideal);
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}(constraints.deviceId));
|
|
137
|
+
|
|
138
|
+
if (defaultDeviceCaptureMode === 'auto' && isCapturingFromDefaultDevice) {
|
|
139
|
+
if (!this._restartOnDefaultDeviceChangeCleanup) {
|
|
140
|
+
log.info('LocalAudioTrack will be restarted if the default device changes');
|
|
141
|
+
navigator.mediaDevices.addEventListener('devicechange', this._onDeviceChange);
|
|
142
|
+
this._restartOnDefaultDeviceChangeCleanup = () => {
|
|
143
|
+
log.info('Cleaning up the listener to restart the LocalAudioTrack if the default device changes');
|
|
144
|
+
navigator.mediaDevices.removeEventListener('devicechange', this._onDeviceChange);
|
|
145
|
+
this._restartOnDefaultDeviceChangeCleanup = null;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
log.info('LocalAudioTrack will NOT be restarted if the default device changes');
|
|
150
|
+
if (this._restartOnDefaultDeviceChangeCleanup) {
|
|
151
|
+
this._restartOnDefaultDeviceChangeCleanup();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
62
156
|
/**
|
|
63
157
|
* @private
|
|
64
158
|
*/
|
|
@@ -73,6 +167,21 @@ class LocalAudioTrack extends LocalMediaAudioTrack {
|
|
|
73
167
|
return super._reacquireTrack.call(this, constraints);
|
|
74
168
|
}
|
|
75
169
|
|
|
170
|
+
/**
|
|
171
|
+
* @private
|
|
172
|
+
*/
|
|
173
|
+
_restartDefaultDevice() {
|
|
174
|
+
const constraints = Object.assign({}, this._constraints);
|
|
175
|
+
const restartConstraints = Object.assign({}, constraints, { deviceId: this._currentDefaultDeviceInfo.deviceId });
|
|
176
|
+
return this.restart(restartConstraints).then(() => {
|
|
177
|
+
// NOTE(mmalavalli): Since we used the new default device's ID while restarting the LocalAudioTrack,
|
|
178
|
+
// we reset the constraints to the original constraints so that the default device detection logic in
|
|
179
|
+
// _maybeRestartOnDefaultDeviceChange() still works.
|
|
180
|
+
this._constraints = constraints;
|
|
181
|
+
this._maybeRestartOnDefaultDeviceChange();
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
76
185
|
/**
|
|
77
186
|
* Disable the {@link LocalAudioTrack}. This is effectively "mute".
|
|
78
187
|
* @returns {this}
|
|
@@ -147,6 +256,9 @@ class LocalAudioTrack extends LocalMediaAudioTrack {
|
|
|
147
256
|
if (this.noiseCancellation) {
|
|
148
257
|
this.noiseCancellation.stop();
|
|
149
258
|
}
|
|
259
|
+
if (this._restartOnDefaultDeviceChangeCleanup) {
|
|
260
|
+
this._restartOnDefaultDeviceChangeCleanup();
|
|
261
|
+
}
|
|
150
262
|
return super.stop.apply(this, arguments);
|
|
151
263
|
}
|
|
152
264
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const { getUserMedia } = require('../../webrtc');
|
|
5
|
-
const {
|
|
5
|
+
const { isIOS } = require('../../util/browserdetection');
|
|
6
6
|
|
|
7
7
|
const { capitalize, defer, isUserMediaTrack, waitForSometime, waitForEvent } = require('../../util');
|
|
8
8
|
const { typeErrors: { ILLEGAL_INVOKE } } = require('../../util/constants');
|
|
@@ -29,10 +29,7 @@ function mixinLocalMediaTrack(AudioOrVideoTrack) {
|
|
|
29
29
|
* @param {LocalTrackOptions} [options] - {@link LocalTrack} options
|
|
30
30
|
*/
|
|
31
31
|
constructor(mediaStreamTrack, options) {
|
|
32
|
-
|
|
33
|
-
// although the bug is seen mainly on iOS devices, we do not have a reliable way to tell iOS from MacOs
|
|
34
|
-
// userAgent on iOS pretends its macOs if Safari is set to request desktop pages.
|
|
35
|
-
const workaroundWebKitBug1208516 = (guessBrowser() === 'safari' || isIOSChrome())
|
|
32
|
+
const workaroundWebKitBug1208516 = isIOS()
|
|
36
33
|
&& isUserMediaTrack(mediaStreamTrack)
|
|
37
34
|
&& typeof document === 'object'
|
|
38
35
|
&& typeof document.addEventListener === 'function'
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
|
|
3
|
+
const { isIOS } = require('../../util/browserdetection');
|
|
5
4
|
const detectSilentVideo = require('../../util/detectsilentvideo');
|
|
6
5
|
const mixinLocalMediaTrack = require('./localmediatrack');
|
|
7
6
|
const VideoTrack = require('./videotrack');
|
|
@@ -32,7 +31,7 @@ class LocalVideoTrack extends LocalMediaVideoTrack {
|
|
|
32
31
|
*/
|
|
33
32
|
constructor(mediaStreamTrack, options) {
|
|
34
33
|
options = Object.assign({
|
|
35
|
-
workaroundSilentLocalVideo: (
|
|
34
|
+
workaroundSilentLocalVideo: isIOS()
|
|
36
35
|
&& isUserMediaTrack(mediaStreamTrack)
|
|
37
36
|
&& typeof document !== 'undefined'
|
|
38
37
|
&& typeof document.createElement === 'function'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { isIOS } = require('../../util/browserdetection');
|
|
4
4
|
const { MediaStream } = require('../../webrtc');
|
|
5
5
|
|
|
6
6
|
const { waitForEvent, waitForSometime } = require('../../util');
|
|
@@ -32,7 +32,7 @@ class MediaTrack extends Track {
|
|
|
32
32
|
*/
|
|
33
33
|
constructor(mediaTrackTransceiver, options) {
|
|
34
34
|
options = Object.assign({
|
|
35
|
-
playPausedElementsIfNotBackgrounded: (
|
|
35
|
+
playPausedElementsIfNotBackgrounded: isIOS()
|
|
36
36
|
&& typeof document === 'object'
|
|
37
37
|
&& typeof document.addEventListener === 'function'
|
|
38
38
|
&& typeof document.visibilityState === 'string'
|
|
@@ -39,6 +39,19 @@ class RemoteAudioTrack extends RemoteMediaAudioTrack {
|
|
|
39
39
|
return `[RemoteAudioTrack #${this._instanceId}: ${this.sid}]`;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
_start() {
|
|
46
|
+
super._start();
|
|
47
|
+
if (this._dummyEl) {
|
|
48
|
+
// NOTE(mpatwardhan): To fix VIDEO-6336, clear dummy element after the
|
|
49
|
+
// RemoteAudioTrack has started.
|
|
50
|
+
this._dummyEl.srcObject = null;
|
|
51
|
+
this._dummyEl = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
/**
|
|
43
56
|
* Update the subscribe {@link Track.Priority} of the {@link RemoteAudioTrack}.
|
|
44
57
|
* @param {?Track.Priority} priority - the new subscribe {@link Track.Priority};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { typeErrors: E, trackPriority } = require('../../util/constants');
|
|
4
|
-
const {
|
|
4
|
+
const { isIOS } = require('../../util/browserdetection');
|
|
5
5
|
const documentVisibilityMonitor = require('../../util/documentvisibilitymonitor.js');
|
|
6
6
|
|
|
7
7
|
function mixinRemoteMediaTrack(AudioOrVideoTrack) {
|
|
@@ -34,7 +34,7 @@ function mixinRemoteMediaTrack(AudioOrVideoTrack) {
|
|
|
34
34
|
// NOTE(mpatwardhan): WebKit bug: 212780 sometimes causes the audio/video elements to stay paused when safari
|
|
35
35
|
// regains foreground. To workaround it, when safari gains foreground - we will play any elements that were
|
|
36
36
|
// playing before safari lost foreground.
|
|
37
|
-
workaroundWebKitBug212780: (
|
|
37
|
+
workaroundWebKitBug212780: isIOS()
|
|
38
38
|
&& typeof document === 'object'
|
|
39
39
|
&& typeof document.addEventListener === 'function'
|
|
40
40
|
&& typeof document.visibilityState === 'string'
|
|
@@ -10,38 +10,39 @@ function isAndroid() {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Detects whether or not a device is an Apple touch screen device.
|
|
14
14
|
* @returns {boolean}
|
|
15
15
|
*/
|
|
16
|
-
function
|
|
17
|
-
return
|
|
16
|
+
function hasTouchScreen() {
|
|
17
|
+
return !!(navigator && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* Detects whether or not a device is an
|
|
21
|
+
* Detects whether or not a device is an iPad.
|
|
22
22
|
* @returns {boolean}
|
|
23
23
|
*/
|
|
24
|
-
function
|
|
25
|
-
return
|
|
26
|
-
|
|
24
|
+
function isIpad() {
|
|
25
|
+
return hasTouchScreen() && window.screen.width >= 744 && (/Macintosh/i.test(navigator.userAgent)
|
|
26
|
+
|| /iPad/.test(navigator.userAgent)
|
|
27
|
+
|| /iPad/.test(navigator.platform));
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
|
-
* Detects whether or not a device is an
|
|
31
|
+
* Detects whether or not a device is an iPhone.
|
|
31
32
|
* @returns {boolean}
|
|
32
33
|
*/
|
|
33
|
-
function
|
|
34
|
-
return hasTouchScreen() && window.screen.width
|
|
35
|
-
|
|
34
|
+
function isIphone() {
|
|
35
|
+
return hasTouchScreen() && window.screen.width <= 476 && (/Macintosh/i.test(navigator.userAgent)
|
|
36
|
+
|| /iPhone/.test(navigator.userAgent)
|
|
37
|
+
|| /iPhone/.test(navigator.platform));
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
41
|
+
* Check whether the current device is an iOS device.
|
|
40
42
|
* @returns {boolean}
|
|
41
43
|
*/
|
|
42
|
-
function
|
|
43
|
-
return
|
|
44
|
-
(/Macintosh/i.test(navigator.userAgent) || /iPhone/.test(navigator.userAgent) || /iPhone/.test(navigator.platform));
|
|
44
|
+
function isIOS() {
|
|
45
|
+
return isIpad() || isIphone();
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
/**
|
|
@@ -7,13 +7,6 @@ var inherits = require('../../vendor/inherits');
|
|
|
7
7
|
var updateTracksToSSRCs = require('../util/sdp').updateUnifiedPlanTrackIdsToSSRCs;
|
|
8
8
|
var util = require('../util');
|
|
9
9
|
|
|
10
|
-
// NOTE(mroberts): This is a short-lived workaround. Checking the user agent
|
|
11
|
-
// string might not fix every affected Firefox instance, but it should be good
|
|
12
|
-
// enough for this bug.
|
|
13
|
-
var needsWorkaroundForBug1480277 = typeof navigator === 'object'
|
|
14
|
-
&& navigator.userAgent
|
|
15
|
-
&& (navigator.userAgent.match(/Firefox\/61/) || navigator.userAgent.match(/Firefox\/62/));
|
|
16
|
-
|
|
17
10
|
// NOTE(mroberts): This class wraps Firefox's RTCPeerConnection implementation.
|
|
18
11
|
// It provides some functionality not currently present in Firefox, namely the
|
|
19
12
|
// abilities to
|
|
@@ -122,15 +115,6 @@ Object.defineProperty(FirefoxRTCPeerConnection.prototype, 'peerIdentity', {
|
|
|
122
115
|
})
|
|
123
116
|
});
|
|
124
117
|
|
|
125
|
-
if (needsWorkaroundForBug1480277) {
|
|
126
|
-
FirefoxRTCPeerConnection.prototype.addTrack = function addTrack() {
|
|
127
|
-
var track = arguments[0];
|
|
128
|
-
var sender = this._peerConnection.addTrack.apply(this._peerConnection, arguments);
|
|
129
|
-
sender.replaceTrack(track);
|
|
130
|
-
return sender;
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
118
|
FirefoxRTCPeerConnection.prototype.createAnswer = function createAnswer() {
|
|
135
119
|
var args = [].slice.call(arguments);
|
|
136
120
|
var promise;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "twilio-video",
|
|
3
3
|
"title": "Twilio Video",
|
|
4
4
|
"description": "Twilio Video JavaScript Library",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.25.0",
|
|
6
6
|
"homepage": "https://twilio.com",
|
|
7
7
|
"author": "Mark Andrus Roberts <mroberts@twilio.com>",
|
|
8
8
|
"contributors": [
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"test:serversiderender": "mocha ./test/serversiderender/index.js",
|
|
104
104
|
"test:integration:adapter": "node ./scripts/karma.js karma/integration.adapter.conf.js",
|
|
105
105
|
"test:integration": "npm run build:es5 && node ./scripts/karma.js karma/integration.conf.js",
|
|
106
|
-
"test:umd:install": "npm install puppeteer@
|
|
106
|
+
"test:umd:install": "npm install puppeteer@19.2.2",
|
|
107
107
|
"test:umd": "mocha ./test/umd/index.js",
|
|
108
108
|
"test:crossbrowser:build:clean": "rimraf ./test/crossbrowser/lib ./test/crossbrowser/src/browser/index.js",
|
|
109
109
|
"test:crossbrowser:build:lint": "cd ./test/crossbrowser && tslint --project tsconfig.json",
|
package/tsdef/index.d.ts
CHANGED
package/tsdef/types.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ export type BandwidthProfileMode = 'grid' | 'collaboration' | 'presentation';
|
|
|
97
97
|
|
|
98
98
|
export type VideoContentPreferencesMode = 'auto' | 'manual';
|
|
99
99
|
export type ClientTrackSwitchOffControl = 'auto' | 'manual';
|
|
100
|
+
export type DefaultDeviceCaptureMode = 'auto' | 'manual';
|
|
100
101
|
|
|
101
102
|
export type NotifyWarning = 'recording-media-lost';
|
|
102
103
|
|
|
@@ -184,6 +185,7 @@ export interface NoiseCancellationOptions {
|
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
export interface CreateLocalAudioTrackOptions extends CreateLocalTrackOptions {
|
|
188
|
+
defaultDeviceCaptureMode?: DefaultDeviceCaptureMode;
|
|
187
189
|
noiseCancellationOptions?: NoiseCancellationOptions;
|
|
188
190
|
}
|
|
189
191
|
|