@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/esm/index.js
CHANGED
|
@@ -974,6 +974,10 @@ var LocalTrackEvents;
|
|
|
974
974
|
* Fires when there has been a change in the underlying track.
|
|
975
975
|
*/
|
|
976
976
|
LocalTrackEvents["UnderlyingTrackChange"] = "underlying-track-change";
|
|
977
|
+
/**
|
|
978
|
+
* Fires when the applyConstraints() has been called for the track.
|
|
979
|
+
*/
|
|
980
|
+
LocalTrackEvents["TrackConstraintsChange"] = "track-constraints-change";
|
|
977
981
|
})(LocalTrackEvents || (LocalTrackEvents = {}));
|
|
978
982
|
// TBD: Fix this once types are published separately
|
|
979
983
|
// export type TrackEffect = BaseMicrophoneEffect | BaseCameraEffect;
|
|
@@ -1147,7 +1151,7 @@ class LocalTrack extends EventEmitter$2 {
|
|
|
1147
1151
|
return effect;
|
|
1148
1152
|
}
|
|
1149
1153
|
/**
|
|
1150
|
-
* Cleanup local microphone track.
|
|
1154
|
+
* Cleanup the local microphone track.
|
|
1151
1155
|
*/
|
|
1152
1156
|
disposeEffects() {
|
|
1153
1157
|
if (this.effects.size > 0) {
|
|
@@ -1157,6 +1161,59 @@ class LocalTrack extends EventEmitter$2 {
|
|
|
1157
1161
|
this.emit(LocalTrackEvents.UnderlyingTrackChange);
|
|
1158
1162
|
}
|
|
1159
1163
|
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Apply constraints to the track.
|
|
1166
|
+
*
|
|
1167
|
+
* @param constraints - The constraints to apply to the track.
|
|
1168
|
+
* @returns A promise which resolves when the constraints have been successfully applied.
|
|
1169
|
+
*/
|
|
1170
|
+
applyConstraints(constraints) {
|
|
1171
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1172
|
+
logger$3.log(`Applying constraints to local track:`, constraints);
|
|
1173
|
+
const ret = this.underlyingTrack.applyConstraints(constraints).then(() => {
|
|
1174
|
+
this.emit(LocalTrackEvents.TrackConstraintsChange);
|
|
1175
|
+
});
|
|
1176
|
+
return ret;
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Get the current constraints of the track.
|
|
1181
|
+
*
|
|
1182
|
+
* @returns The constraints of the track.
|
|
1183
|
+
*/
|
|
1184
|
+
getConstraints() {
|
|
1185
|
+
return this.underlyingTrack.getConstraints();
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Get the current settings of the track.
|
|
1189
|
+
*
|
|
1190
|
+
* @returns The settings of the track.
|
|
1191
|
+
*/
|
|
1192
|
+
getSettings() {
|
|
1193
|
+
return this.underlyingTrack.getSettings();
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Check the resolution and then return how many layers will be active.
|
|
1197
|
+
*
|
|
1198
|
+
* @returns The active layers count.
|
|
1199
|
+
*/
|
|
1200
|
+
getNumActiveSimulcastLayers() {
|
|
1201
|
+
let activeSimulcastLayersNumber = 0;
|
|
1202
|
+
if (this.trackState.type === 'audio') {
|
|
1203
|
+
return activeSimulcastLayersNumber;
|
|
1204
|
+
}
|
|
1205
|
+
const videoHeight = this.underlyingTrack.getSettings().height;
|
|
1206
|
+
if (videoHeight <= 180) {
|
|
1207
|
+
activeSimulcastLayersNumber = 1;
|
|
1208
|
+
}
|
|
1209
|
+
else if (videoHeight <= 360) {
|
|
1210
|
+
activeSimulcastLayersNumber = 2;
|
|
1211
|
+
}
|
|
1212
|
+
else {
|
|
1213
|
+
activeSimulcastLayersNumber = 3;
|
|
1214
|
+
}
|
|
1215
|
+
return activeSimulcastLayersNumber;
|
|
1216
|
+
}
|
|
1160
1217
|
}
|
|
1161
1218
|
LocalTrack.Events = LocalTrackEvents;
|
|
1162
1219
|
|
|
@@ -1200,7 +1257,10 @@ class WcmeError {
|
|
|
1200
1257
|
}
|
|
1201
1258
|
}
|
|
1202
1259
|
/**
|
|
1203
|
-
* Creates a camera video track.
|
|
1260
|
+
* Creates a camera video track. Please note that the constraint params in second getUserMedia call would NOT take effect when:
|
|
1261
|
+
*
|
|
1262
|
+
* 1. Previous captured video track from the same device is not stopped .
|
|
1263
|
+
* 2. Previous createCameraTrack() call for the same device is in progress.
|
|
1204
1264
|
*
|
|
1205
1265
|
* @param constraints - Video device constraints.
|
|
1206
1266
|
* @returns A LocalTrack object or an error.
|
|
@@ -4991,6 +5051,44 @@ class PeerConnection extends EventEmitter$2 {
|
|
|
4991
5051
|
get iceGatheringState() {
|
|
4992
5052
|
return this.pc.iceGatheringState;
|
|
4993
5053
|
}
|
|
5054
|
+
/**
|
|
5055
|
+
* Returns the type of a connection that has been established.
|
|
5056
|
+
*
|
|
5057
|
+
* @returns The connection type which would be `ConnectionType`.
|
|
5058
|
+
*/
|
|
5059
|
+
getCurrentConnectionType() {
|
|
5060
|
+
var _a;
|
|
5061
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
5062
|
+
// make sure this method only can be called when the ice connection is established;
|
|
5063
|
+
const isIceConnected = this.pc.iceConnectionState === 'connected' || this.pc.iceConnectionState === 'completed';
|
|
5064
|
+
if (!isIceConnected) {
|
|
5065
|
+
throw new Error('Ice connection is not established');
|
|
5066
|
+
}
|
|
5067
|
+
const succeededLocalCandidateIds = new Set();
|
|
5068
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5069
|
+
const localCandidateStatsReports = [];
|
|
5070
|
+
(yield this.pc.getStats()).forEach((report) => {
|
|
5071
|
+
var _a;
|
|
5072
|
+
// collect all local candidate ids from `candidate-pair` stats reports with `succeeded` state.
|
|
5073
|
+
if (report.type === 'candidate-pair' && ((_a = report.state) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'succeeded') {
|
|
5074
|
+
succeededLocalCandidateIds.add(report.localCandidateId);
|
|
5075
|
+
}
|
|
5076
|
+
// collect all `local-candidate` stats.
|
|
5077
|
+
if (report.type === 'local-candidate') {
|
|
5078
|
+
localCandidateStatsReports.push(report);
|
|
5079
|
+
}
|
|
5080
|
+
});
|
|
5081
|
+
// find the `local-candidate` stats which report id contains in `succeededLocalCandidateIds`.
|
|
5082
|
+
const localCandidate = localCandidateStatsReports.find((report) => succeededLocalCandidateIds.has(report.id));
|
|
5083
|
+
if (!localCandidate) {
|
|
5084
|
+
return 'unknown';
|
|
5085
|
+
}
|
|
5086
|
+
if (localCandidate.relayProtocol) {
|
|
5087
|
+
return `TURN-${localCandidate.relayProtocol.toUpperCase()}`;
|
|
5088
|
+
}
|
|
5089
|
+
return (_a = localCandidate.protocol) === null || _a === void 0 ? void 0 : _a.toUpperCase();
|
|
5090
|
+
});
|
|
5091
|
+
}
|
|
4994
5092
|
}
|
|
4995
5093
|
PeerConnection.Events = PeerConnectionEvents;
|
|
4996
5094
|
|
|
@@ -8860,7 +8958,7 @@ function injectContentTypes(sdp, contentTypeMap) {
|
|
|
8860
8958
|
}
|
|
8861
8959
|
function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
|
|
8862
8960
|
parsedSdp.avMedia
|
|
8863
|
-
.filter((mLine) => mLine.direction === 'sendrecv' || mLine.direction === '
|
|
8961
|
+
.filter((mLine) => mLine.direction === 'sendrecv' || mLine.direction === 'inactive')
|
|
8864
8962
|
.forEach((mLine) => {
|
|
8865
8963
|
if (!mLine.otherLines.find((line) => line instanceof JmpLine)) {
|
|
8866
8964
|
mLine.addLine(new JmpLine());
|
|
@@ -8884,6 +8982,7 @@ class SendOnlyTransceiver extends Transceiver {
|
|
|
8884
8982
|
super(rtcpRtpTransceiver);
|
|
8885
8983
|
this.requested = false;
|
|
8886
8984
|
this.csi = csi;
|
|
8985
|
+
this.direction = 'sendrecv';
|
|
8887
8986
|
this.handleTrackChange = this.handleTrackChange.bind(this);
|
|
8888
8987
|
}
|
|
8889
8988
|
handleTrackChange() {
|
|
@@ -8901,6 +9000,7 @@ class SendOnlyTransceiver extends Transceiver {
|
|
|
8901
9000
|
var _a;
|
|
8902
9001
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8903
9002
|
_super.replaceTransceiver.call(this, newRtcRtpTransceiver);
|
|
9003
|
+
newRtcRtpTransceiver.direction = this.direction;
|
|
8904
9004
|
if (this.requested) {
|
|
8905
9005
|
yield this.sender.replaceTrack(((_a = this.publishedTrack) === null || _a === void 0 ? void 0 : _a.underlyingTrack) || null);
|
|
8906
9006
|
}
|
|
@@ -8971,8 +9071,8 @@ class SendOnlyTransceiver extends Transceiver {
|
|
|
8971
9071
|
return this.replacePublishedTrack();
|
|
8972
9072
|
}
|
|
8973
9073
|
setActive(enabled) {
|
|
8974
|
-
|
|
8975
|
-
this._rtcRtpTransceiver.direction = direction;
|
|
9074
|
+
this.direction = enabled ? 'sendrecv' : 'inactive';
|
|
9075
|
+
this._rtcRtpTransceiver.direction = this.direction;
|
|
8976
9076
|
return this._rtcRtpTransceiver.direction !== this._rtcRtpTransceiver.currentDirection;
|
|
8977
9077
|
}
|
|
8978
9078
|
getStats() {
|
|
@@ -9595,9 +9695,16 @@ const defaultMultistreamConnectionOptions = {
|
|
|
9595
9695
|
bundlePolicy: 'max-compat',
|
|
9596
9696
|
iceServers: undefined,
|
|
9597
9697
|
disableContentSimulcast: true,
|
|
9698
|
+
enableMainAudio: true,
|
|
9699
|
+
enableMainVideo: true,
|
|
9700
|
+
};
|
|
9701
|
+
const defaultVideoCodecParameters = {
|
|
9702
|
+
'max-mbps': `${defaultMaxVideoEncodeMbps}`,
|
|
9703
|
+
'max-fs': `${defaultMaxVideoEncodeFrameSize}`,
|
|
9598
9704
|
};
|
|
9599
9705
|
class MultistreamConnection extends EventEmitter {
|
|
9600
9706
|
constructor(userOptions = {}) {
|
|
9707
|
+
var _a, _b;
|
|
9601
9708
|
super();
|
|
9602
9709
|
this.sendTransceivers = new Map();
|
|
9603
9710
|
this.recvTransceivers = new Map();
|
|
@@ -9605,6 +9712,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9605
9712
|
this.pendingJmpTasks = [];
|
|
9606
9713
|
this.metricsCallback = () => { };
|
|
9607
9714
|
this.overuseUpdateCallback = () => { };
|
|
9715
|
+
this.customCodecParameters = new Map();
|
|
9608
9716
|
this.midMap = new Map();
|
|
9609
9717
|
this.currentMid = 0;
|
|
9610
9718
|
this.options = Object.assign(Object.assign({}, defaultMultistreamConnectionOptions), userOptions);
|
|
@@ -9617,11 +9725,15 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9617
9725
|
const mainSceneId = generateSceneId();
|
|
9618
9726
|
const videoMainEncodingOptions = this.getVideoEncodingOptions(MediaContent.Main);
|
|
9619
9727
|
this.createSendTransceiver(MediaType.VideoMain, mainSceneId, videoMainEncodingOptions);
|
|
9728
|
+
this.setCodecParameters(MediaType.VideoMain, defaultVideoCodecParameters);
|
|
9620
9729
|
this.createSendTransceiver(MediaType.AudioMain, mainSceneId);
|
|
9730
|
+
(_a = this.sendTransceivers.get(MediaType.VideoMain)) === null || _a === void 0 ? void 0 : _a.setActive(this.options.enableMainVideo);
|
|
9731
|
+
(_b = this.sendTransceivers.get(MediaType.AudioMain)) === null || _b === void 0 ? void 0 : _b.setActive(this.options.enableMainAudio);
|
|
9621
9732
|
if (this.options.floorControlledPresentation) {
|
|
9622
9733
|
const videoPresentationEncodingOptions = this.getVideoEncodingOptions(MediaContent.Slides);
|
|
9623
9734
|
const contentSceneId = generateSceneId();
|
|
9624
9735
|
this.createSendTransceiver(MediaType.VideoSlides, contentSceneId, videoPresentationEncodingOptions);
|
|
9736
|
+
this.setCodecParameters(MediaType.VideoSlides, defaultVideoCodecParameters);
|
|
9625
9737
|
this.createSendTransceiver(MediaType.AudioSlides, contentSceneId);
|
|
9626
9738
|
}
|
|
9627
9739
|
}
|
|
@@ -9986,20 +10098,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9986
10098
|
return ingressSignaler.getReceiverId();
|
|
9987
10099
|
});
|
|
9988
10100
|
if (this.pc.getRemoteDescription()) {
|
|
9989
|
-
yield this.
|
|
9990
|
-
.createOffer()
|
|
9991
|
-
.then((offer) => {
|
|
9992
|
-
if (!offer.sdp) {
|
|
9993
|
-
throw new Error('No SDP offer');
|
|
9994
|
-
}
|
|
9995
|
-
offer.sdp = this.preProcessLocalOffer(offer.sdp);
|
|
9996
|
-
return this.pc.setLocalDescription(offer);
|
|
9997
|
-
})
|
|
9998
|
-
.then(() => {
|
|
9999
|
-
var _a;
|
|
10000
|
-
const answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
|
|
10001
|
-
return this.pc.setRemoteDescription({ type: 'answer', sdp: answer });
|
|
10002
|
-
});
|
|
10101
|
+
yield this.doLocalOfferAnswer();
|
|
10003
10102
|
}
|
|
10004
10103
|
this.recvTransceivers.set(mediaType, [
|
|
10005
10104
|
...(this.recvTransceivers.get(mediaType) || []),
|
|
@@ -10065,8 +10164,26 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10065
10164
|
}
|
|
10066
10165
|
setAnswer(answer) {
|
|
10067
10166
|
return __awaiter(this, void 0, void 0, function* () {
|
|
10167
|
+
const isInitialAnswer = !this.pc.getRemoteDescription();
|
|
10068
10168
|
const sdp = this.preProcessRemoteAnswer(answer);
|
|
10069
|
-
return this.pc.setRemoteDescription({ type: 'answer', sdp })
|
|
10169
|
+
return this.pc.setRemoteDescription({ type: 'answer', sdp }).then(() => {
|
|
10170
|
+
if (isInitialAnswer && this.customCodecParameters.size > 0) {
|
|
10171
|
+
this.doLocalOfferAnswer();
|
|
10172
|
+
}
|
|
10173
|
+
});
|
|
10174
|
+
});
|
|
10175
|
+
}
|
|
10176
|
+
doLocalOfferAnswer() {
|
|
10177
|
+
var _a;
|
|
10178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10179
|
+
const offer = yield this.pc.createOffer();
|
|
10180
|
+
if (!offer.sdp) {
|
|
10181
|
+
throw new Error('No SDP offer');
|
|
10182
|
+
}
|
|
10183
|
+
offer.sdp = this.preProcessLocalOffer(offer.sdp);
|
|
10184
|
+
yield this.pc.setLocalDescription(offer);
|
|
10185
|
+
const answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
|
|
10186
|
+
return this.pc.setRemoteDescription({ type: 'answer', sdp: answer });
|
|
10070
10187
|
});
|
|
10071
10188
|
}
|
|
10072
10189
|
enableMultistreamAudio(enabled) {
|
|
@@ -10093,12 +10210,20 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10093
10210
|
const simulcastEnabled = !!av.simulcast;
|
|
10094
10211
|
const rtxEnabled = av.type === 'video';
|
|
10095
10212
|
egressSignaler.signalStreams(simulcastEnabled, rtxEnabled, av);
|
|
10096
|
-
|
|
10213
|
+
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; });
|
|
10214
|
+
if (mediaType && this.customCodecParameters.has(mediaType)) {
|
|
10097
10215
|
[...av.codecs.values()]
|
|
10098
|
-
.filter((ci) => ci.name === 'H264')
|
|
10216
|
+
.filter((ci) => ci.name === (av.type === 'audio' ? 'opus' : 'H264'))
|
|
10099
10217
|
.forEach((ci) => {
|
|
10100
|
-
|
|
10101
|
-
|
|
10218
|
+
var _a;
|
|
10219
|
+
(_a = this.customCodecParameters.get(mediaType)) === null || _a === void 0 ? void 0 : _a.forEach((value, param) => {
|
|
10220
|
+
if (value === null) {
|
|
10221
|
+
ci.fmtParams.delete(param);
|
|
10222
|
+
}
|
|
10223
|
+
else {
|
|
10224
|
+
ci.fmtParams.set(param, `${value}`);
|
|
10225
|
+
}
|
|
10226
|
+
});
|
|
10102
10227
|
});
|
|
10103
10228
|
}
|
|
10104
10229
|
});
|
|
@@ -10154,6 +10279,30 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10154
10279
|
.map((transceiver) => transceiver.publishedTrack)
|
|
10155
10280
|
.filter(Boolean);
|
|
10156
10281
|
}
|
|
10282
|
+
setCodecParameters(mediaType, parameters) {
|
|
10283
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10284
|
+
const currentParams = this.customCodecParameters.get(mediaType) || new Map();
|
|
10285
|
+
Object.entries(parameters).forEach(([param, value]) => {
|
|
10286
|
+
currentParams.set(param, value);
|
|
10287
|
+
});
|
|
10288
|
+
this.customCodecParameters.set(mediaType, currentParams);
|
|
10289
|
+
if (this.pc.getRemoteDescription()) {
|
|
10290
|
+
yield this.doLocalOfferAnswer();
|
|
10291
|
+
}
|
|
10292
|
+
});
|
|
10293
|
+
}
|
|
10294
|
+
deleteCodecParameters(mediaType, parameters) {
|
|
10295
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10296
|
+
const currentParams = this.customCodecParameters.get(mediaType) || new Map();
|
|
10297
|
+
parameters.forEach((param) => {
|
|
10298
|
+
currentParams.set(param, null);
|
|
10299
|
+
});
|
|
10300
|
+
this.customCodecParameters.set(mediaType, currentParams);
|
|
10301
|
+
if (this.pc.getRemoteDescription()) {
|
|
10302
|
+
yield this.doLocalOfferAnswer();
|
|
10303
|
+
}
|
|
10304
|
+
});
|
|
10305
|
+
}
|
|
10157
10306
|
requestMedia(mediaType, mediaRequests) {
|
|
10158
10307
|
var _a;
|
|
10159
10308
|
const task = () => {
|