@webex/web-client-media-engine 1.38.4 → 1.40.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/dist/cjs/index.js +173 -24
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +173 -24
- package/dist/esm/index.js.map +1 -1
- package/dist/types/index.d.ts +9 -0
- package/package.json +2 -2
package/dist/cjs/index.js
CHANGED
|
@@ -978,6 +978,10 @@ exports.LocalTrackEvents = void 0;
|
|
|
978
978
|
* Fires when there has been a change in the underlying track.
|
|
979
979
|
*/
|
|
980
980
|
LocalTrackEvents["UnderlyingTrackChange"] = "underlying-track-change";
|
|
981
|
+
/**
|
|
982
|
+
* Fires when the applyConstraints() has been called for the track.
|
|
983
|
+
*/
|
|
984
|
+
LocalTrackEvents["TrackConstraintsChange"] = "track-constraints-change";
|
|
981
985
|
})(exports.LocalTrackEvents || (exports.LocalTrackEvents = {}));
|
|
982
986
|
// TBD: Fix this once types are published separately
|
|
983
987
|
// export type TrackEffect = BaseMicrophoneEffect | BaseCameraEffect;
|
|
@@ -1151,7 +1155,7 @@ class LocalTrack extends EventEmitter$2 {
|
|
|
1151
1155
|
return effect;
|
|
1152
1156
|
}
|
|
1153
1157
|
/**
|
|
1154
|
-
* Cleanup local microphone track.
|
|
1158
|
+
* Cleanup the local microphone track.
|
|
1155
1159
|
*/
|
|
1156
1160
|
disposeEffects() {
|
|
1157
1161
|
if (this.effects.size > 0) {
|
|
@@ -1161,6 +1165,59 @@ class LocalTrack extends EventEmitter$2 {
|
|
|
1161
1165
|
this.emit(exports.LocalTrackEvents.UnderlyingTrackChange);
|
|
1162
1166
|
}
|
|
1163
1167
|
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Apply constraints to the track.
|
|
1170
|
+
*
|
|
1171
|
+
* @param constraints - The constraints to apply to the track.
|
|
1172
|
+
* @returns A promise which resolves when the constraints have been successfully applied.
|
|
1173
|
+
*/
|
|
1174
|
+
applyConstraints(constraints) {
|
|
1175
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1176
|
+
logger$3.log(`Applying constraints to local track:`, constraints);
|
|
1177
|
+
const ret = this.underlyingTrack.applyConstraints(constraints).then(() => {
|
|
1178
|
+
this.emit(exports.LocalTrackEvents.TrackConstraintsChange);
|
|
1179
|
+
});
|
|
1180
|
+
return ret;
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Get the current constraints of the track.
|
|
1185
|
+
*
|
|
1186
|
+
* @returns The constraints of the track.
|
|
1187
|
+
*/
|
|
1188
|
+
getConstraints() {
|
|
1189
|
+
return this.underlyingTrack.getConstraints();
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Get the current settings of the track.
|
|
1193
|
+
*
|
|
1194
|
+
* @returns The settings of the track.
|
|
1195
|
+
*/
|
|
1196
|
+
getSettings() {
|
|
1197
|
+
return this.underlyingTrack.getSettings();
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Check the resolution and then return how many layers will be active.
|
|
1201
|
+
*
|
|
1202
|
+
* @returns The active layers count.
|
|
1203
|
+
*/
|
|
1204
|
+
getNumActiveSimulcastLayers() {
|
|
1205
|
+
let activeSimulcastLayersNumber = 0;
|
|
1206
|
+
if (this.trackState.type === 'audio') {
|
|
1207
|
+
return activeSimulcastLayersNumber;
|
|
1208
|
+
}
|
|
1209
|
+
const videoHeight = this.underlyingTrack.getSettings().height;
|
|
1210
|
+
if (videoHeight <= 180) {
|
|
1211
|
+
activeSimulcastLayersNumber = 1;
|
|
1212
|
+
}
|
|
1213
|
+
else if (videoHeight <= 360) {
|
|
1214
|
+
activeSimulcastLayersNumber = 2;
|
|
1215
|
+
}
|
|
1216
|
+
else {
|
|
1217
|
+
activeSimulcastLayersNumber = 3;
|
|
1218
|
+
}
|
|
1219
|
+
return activeSimulcastLayersNumber;
|
|
1220
|
+
}
|
|
1164
1221
|
}
|
|
1165
1222
|
LocalTrack.Events = exports.LocalTrackEvents;
|
|
1166
1223
|
|
|
@@ -1204,7 +1261,10 @@ class WcmeError {
|
|
|
1204
1261
|
}
|
|
1205
1262
|
}
|
|
1206
1263
|
/**
|
|
1207
|
-
* Creates a camera video track.
|
|
1264
|
+
* Creates a camera video track. Please note that the constraint params in second getUserMedia call would NOT take effect when:
|
|
1265
|
+
*
|
|
1266
|
+
* 1. Previous captured video track from the same device is not stopped .
|
|
1267
|
+
* 2. Previous createCameraTrack() call for the same device is in progress.
|
|
1208
1268
|
*
|
|
1209
1269
|
* @param constraints - Video device constraints.
|
|
1210
1270
|
* @returns A LocalTrack object or an error.
|
|
@@ -4995,6 +5055,44 @@ class PeerConnection extends EventEmitter$2 {
|
|
|
4995
5055
|
get iceGatheringState() {
|
|
4996
5056
|
return this.pc.iceGatheringState;
|
|
4997
5057
|
}
|
|
5058
|
+
/**
|
|
5059
|
+
* Returns the type of a connection that has been established.
|
|
5060
|
+
*
|
|
5061
|
+
* @returns The connection type which would be `ConnectionType`.
|
|
5062
|
+
*/
|
|
5063
|
+
getCurrentConnectionType() {
|
|
5064
|
+
var _a;
|
|
5065
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
5066
|
+
// make sure this method only can be called when the ice connection is established;
|
|
5067
|
+
const isIceConnected = this.pc.iceConnectionState === 'connected' || this.pc.iceConnectionState === 'completed';
|
|
5068
|
+
if (!isIceConnected) {
|
|
5069
|
+
throw new Error('Ice connection is not established');
|
|
5070
|
+
}
|
|
5071
|
+
const succeededLocalCandidateIds = new Set();
|
|
5072
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5073
|
+
const localCandidateStatsReports = [];
|
|
5074
|
+
(yield this.pc.getStats()).forEach((report) => {
|
|
5075
|
+
var _a;
|
|
5076
|
+
// collect all local candidate ids from `candidate-pair` stats reports with `succeeded` state.
|
|
5077
|
+
if (report.type === 'candidate-pair' && ((_a = report.state) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'succeeded') {
|
|
5078
|
+
succeededLocalCandidateIds.add(report.localCandidateId);
|
|
5079
|
+
}
|
|
5080
|
+
// collect all `local-candidate` stats.
|
|
5081
|
+
if (report.type === 'local-candidate') {
|
|
5082
|
+
localCandidateStatsReports.push(report);
|
|
5083
|
+
}
|
|
5084
|
+
});
|
|
5085
|
+
// find the `local-candidate` stats which report id contains in `succeededLocalCandidateIds`.
|
|
5086
|
+
const localCandidate = localCandidateStatsReports.find((report) => succeededLocalCandidateIds.has(report.id));
|
|
5087
|
+
if (!localCandidate) {
|
|
5088
|
+
return 'unknown';
|
|
5089
|
+
}
|
|
5090
|
+
if (localCandidate.relayProtocol) {
|
|
5091
|
+
return `TURN-${localCandidate.relayProtocol.toUpperCase()}`;
|
|
5092
|
+
}
|
|
5093
|
+
return (_a = localCandidate.protocol) === null || _a === void 0 ? void 0 : _a.toUpperCase();
|
|
5094
|
+
});
|
|
5095
|
+
}
|
|
4998
5096
|
}
|
|
4999
5097
|
PeerConnection.Events = PeerConnectionEvents;
|
|
5000
5098
|
|
|
@@ -8864,7 +8962,7 @@ function injectContentTypes(sdp, contentTypeMap) {
|
|
|
8864
8962
|
}
|
|
8865
8963
|
function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
|
|
8866
8964
|
parsedSdp.avMedia
|
|
8867
|
-
.filter((mLine) => mLine.direction === 'sendrecv' || mLine.direction === '
|
|
8965
|
+
.filter((mLine) => mLine.direction === 'sendrecv' || mLine.direction === 'inactive')
|
|
8868
8966
|
.forEach((mLine) => {
|
|
8869
8967
|
if (!mLine.otherLines.find((line) => line instanceof JmpLine)) {
|
|
8870
8968
|
mLine.addLine(new JmpLine());
|
|
@@ -8888,6 +8986,7 @@ class SendOnlyTransceiver extends Transceiver {
|
|
|
8888
8986
|
super(rtcpRtpTransceiver);
|
|
8889
8987
|
this.requested = false;
|
|
8890
8988
|
this.csi = csi;
|
|
8989
|
+
this.direction = 'sendrecv';
|
|
8891
8990
|
this.handleTrackChange = this.handleTrackChange.bind(this);
|
|
8892
8991
|
}
|
|
8893
8992
|
handleTrackChange() {
|
|
@@ -8905,6 +9004,7 @@ class SendOnlyTransceiver extends Transceiver {
|
|
|
8905
9004
|
var _a;
|
|
8906
9005
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8907
9006
|
_super.replaceTransceiver.call(this, newRtcRtpTransceiver);
|
|
9007
|
+
newRtcRtpTransceiver.direction = this.direction;
|
|
8908
9008
|
if (this.requested) {
|
|
8909
9009
|
yield this.sender.replaceTrack(((_a = this.publishedTrack) === null || _a === void 0 ? void 0 : _a.underlyingTrack) || null);
|
|
8910
9010
|
}
|
|
@@ -8975,8 +9075,8 @@ class SendOnlyTransceiver extends Transceiver {
|
|
|
8975
9075
|
return this.replacePublishedTrack();
|
|
8976
9076
|
}
|
|
8977
9077
|
setActive(enabled) {
|
|
8978
|
-
|
|
8979
|
-
this._rtcRtpTransceiver.direction = direction;
|
|
9078
|
+
this.direction = enabled ? 'sendrecv' : 'inactive';
|
|
9079
|
+
this._rtcRtpTransceiver.direction = this.direction;
|
|
8980
9080
|
return this._rtcRtpTransceiver.direction !== this._rtcRtpTransceiver.currentDirection;
|
|
8981
9081
|
}
|
|
8982
9082
|
getStats() {
|
|
@@ -9599,9 +9699,16 @@ const defaultMultistreamConnectionOptions = {
|
|
|
9599
9699
|
bundlePolicy: 'max-compat',
|
|
9600
9700
|
iceServers: undefined,
|
|
9601
9701
|
disableContentSimulcast: true,
|
|
9702
|
+
enableMainAudio: true,
|
|
9703
|
+
enableMainVideo: true,
|
|
9704
|
+
};
|
|
9705
|
+
const defaultVideoCodecParameters = {
|
|
9706
|
+
'max-mbps': `${defaultMaxVideoEncodeMbps}`,
|
|
9707
|
+
'max-fs': `${defaultMaxVideoEncodeFrameSize}`,
|
|
9602
9708
|
};
|
|
9603
9709
|
class MultistreamConnection extends EventEmitter {
|
|
9604
9710
|
constructor(userOptions = {}) {
|
|
9711
|
+
var _a, _b;
|
|
9605
9712
|
super();
|
|
9606
9713
|
this.sendTransceivers = new Map();
|
|
9607
9714
|
this.recvTransceivers = new Map();
|
|
@@ -9609,6 +9716,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9609
9716
|
this.pendingJmpTasks = [];
|
|
9610
9717
|
this.metricsCallback = () => { };
|
|
9611
9718
|
this.overuseUpdateCallback = () => { };
|
|
9719
|
+
this.customCodecParameters = new Map();
|
|
9612
9720
|
this.midMap = new Map();
|
|
9613
9721
|
this.currentMid = 0;
|
|
9614
9722
|
this.options = Object.assign(Object.assign({}, defaultMultistreamConnectionOptions), userOptions);
|
|
@@ -9621,11 +9729,15 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9621
9729
|
const mainSceneId = generateSceneId();
|
|
9622
9730
|
const videoMainEncodingOptions = this.getVideoEncodingOptions(MediaContent.Main);
|
|
9623
9731
|
this.createSendTransceiver(MediaType.VideoMain, mainSceneId, videoMainEncodingOptions);
|
|
9732
|
+
this.setCodecParameters(MediaType.VideoMain, defaultVideoCodecParameters);
|
|
9624
9733
|
this.createSendTransceiver(MediaType.AudioMain, mainSceneId);
|
|
9734
|
+
(_a = this.sendTransceivers.get(MediaType.VideoMain)) === null || _a === void 0 ? void 0 : _a.setActive(this.options.enableMainVideo);
|
|
9735
|
+
(_b = this.sendTransceivers.get(MediaType.AudioMain)) === null || _b === void 0 ? void 0 : _b.setActive(this.options.enableMainAudio);
|
|
9625
9736
|
if (this.options.floorControlledPresentation) {
|
|
9626
9737
|
const videoPresentationEncodingOptions = this.getVideoEncodingOptions(MediaContent.Slides);
|
|
9627
9738
|
const contentSceneId = generateSceneId();
|
|
9628
9739
|
this.createSendTransceiver(MediaType.VideoSlides, contentSceneId, videoPresentationEncodingOptions);
|
|
9740
|
+
this.setCodecParameters(MediaType.VideoSlides, defaultVideoCodecParameters);
|
|
9629
9741
|
this.createSendTransceiver(MediaType.AudioSlides, contentSceneId);
|
|
9630
9742
|
}
|
|
9631
9743
|
}
|
|
@@ -9990,20 +10102,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9990
10102
|
return ingressSignaler.getReceiverId();
|
|
9991
10103
|
});
|
|
9992
10104
|
if (this.pc.getRemoteDescription()) {
|
|
9993
|
-
yield this.
|
|
9994
|
-
.createOffer()
|
|
9995
|
-
.then((offer) => {
|
|
9996
|
-
if (!offer.sdp) {
|
|
9997
|
-
throw new Error('No SDP offer');
|
|
9998
|
-
}
|
|
9999
|
-
offer.sdp = this.preProcessLocalOffer(offer.sdp);
|
|
10000
|
-
return this.pc.setLocalDescription(offer);
|
|
10001
|
-
})
|
|
10002
|
-
.then(() => {
|
|
10003
|
-
var _a;
|
|
10004
|
-
const answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
|
|
10005
|
-
return this.pc.setRemoteDescription({ type: 'answer', sdp: answer });
|
|
10006
|
-
});
|
|
10105
|
+
yield this.doLocalOfferAnswer();
|
|
10007
10106
|
}
|
|
10008
10107
|
this.recvTransceivers.set(mediaType, [
|
|
10009
10108
|
...(this.recvTransceivers.get(mediaType) || []),
|
|
@@ -10069,8 +10168,26 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10069
10168
|
}
|
|
10070
10169
|
setAnswer(answer) {
|
|
10071
10170
|
return __awaiter(this, void 0, void 0, function* () {
|
|
10171
|
+
const isInitialAnswer = !this.pc.getRemoteDescription();
|
|
10072
10172
|
const sdp = this.preProcessRemoteAnswer(answer);
|
|
10073
|
-
return this.pc.setRemoteDescription({ type: 'answer', sdp })
|
|
10173
|
+
return this.pc.setRemoteDescription({ type: 'answer', sdp }).then(() => {
|
|
10174
|
+
if (isInitialAnswer && this.customCodecParameters.size > 0) {
|
|
10175
|
+
this.doLocalOfferAnswer();
|
|
10176
|
+
}
|
|
10177
|
+
});
|
|
10178
|
+
});
|
|
10179
|
+
}
|
|
10180
|
+
doLocalOfferAnswer() {
|
|
10181
|
+
var _a;
|
|
10182
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10183
|
+
const offer = yield this.pc.createOffer();
|
|
10184
|
+
if (!offer.sdp) {
|
|
10185
|
+
throw new Error('No SDP offer');
|
|
10186
|
+
}
|
|
10187
|
+
offer.sdp = this.preProcessLocalOffer(offer.sdp);
|
|
10188
|
+
yield this.pc.setLocalDescription(offer);
|
|
10189
|
+
const answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
|
|
10190
|
+
return this.pc.setRemoteDescription({ type: 'answer', sdp: answer });
|
|
10074
10191
|
});
|
|
10075
10192
|
}
|
|
10076
10193
|
enableMultistreamAudio(enabled) {
|
|
@@ -10097,12 +10214,20 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10097
10214
|
const simulcastEnabled = !!av.simulcast;
|
|
10098
10215
|
const rtxEnabled = av.type === 'video';
|
|
10099
10216
|
egressSignaler.signalStreams(simulcastEnabled, rtxEnabled, av);
|
|
10100
|
-
|
|
10217
|
+
const mediaType = [...this.sendTransceivers.keys()].find((key) => { var _a; return ((_a = this.sendTransceivers.get(key)) === null || _a === void 0 ? void 0 : _a.mid) === av.mid; });
|
|
10218
|
+
if (mediaType && this.customCodecParameters.has(mediaType)) {
|
|
10101
10219
|
[...av.codecs.values()]
|
|
10102
|
-
.filter((ci) => ci.name === 'H264')
|
|
10220
|
+
.filter((ci) => ci.name === (av.type === 'audio' ? 'opus' : 'H264'))
|
|
10103
10221
|
.forEach((ci) => {
|
|
10104
|
-
|
|
10105
|
-
|
|
10222
|
+
var _a;
|
|
10223
|
+
(_a = this.customCodecParameters.get(mediaType)) === null || _a === void 0 ? void 0 : _a.forEach((value, param) => {
|
|
10224
|
+
if (value === null) {
|
|
10225
|
+
ci.fmtParams.delete(param);
|
|
10226
|
+
}
|
|
10227
|
+
else {
|
|
10228
|
+
ci.fmtParams.set(param, `${value}`);
|
|
10229
|
+
}
|
|
10230
|
+
});
|
|
10106
10231
|
});
|
|
10107
10232
|
}
|
|
10108
10233
|
});
|
|
@@ -10158,6 +10283,30 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10158
10283
|
.map((transceiver) => transceiver.publishedTrack)
|
|
10159
10284
|
.filter(Boolean);
|
|
10160
10285
|
}
|
|
10286
|
+
setCodecParameters(mediaType, parameters) {
|
|
10287
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10288
|
+
const currentParams = this.customCodecParameters.get(mediaType) || new Map();
|
|
10289
|
+
Object.entries(parameters).forEach(([param, value]) => {
|
|
10290
|
+
currentParams.set(param, value);
|
|
10291
|
+
});
|
|
10292
|
+
this.customCodecParameters.set(mediaType, currentParams);
|
|
10293
|
+
if (this.pc.getRemoteDescription()) {
|
|
10294
|
+
yield this.doLocalOfferAnswer();
|
|
10295
|
+
}
|
|
10296
|
+
});
|
|
10297
|
+
}
|
|
10298
|
+
deleteCodecParameters(mediaType, parameters) {
|
|
10299
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10300
|
+
const currentParams = this.customCodecParameters.get(mediaType) || new Map();
|
|
10301
|
+
parameters.forEach((param) => {
|
|
10302
|
+
currentParams.set(param, null);
|
|
10303
|
+
});
|
|
10304
|
+
this.customCodecParameters.set(mediaType, currentParams);
|
|
10305
|
+
if (this.pc.getRemoteDescription()) {
|
|
10306
|
+
yield this.doLocalOfferAnswer();
|
|
10307
|
+
}
|
|
10308
|
+
});
|
|
10309
|
+
}
|
|
10161
10310
|
requestMedia(mediaType, mediaRequests) {
|
|
10162
10311
|
var _a;
|
|
10163
10312
|
const task = () => {
|