@webex/web-client-media-engine 1.40.4 → 1.40.5
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 +110 -62
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +110 -62
- package/dist/esm/index.js.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/package.json +3 -3
package/dist/esm/index.js
CHANGED
|
@@ -543,12 +543,13 @@ function createMicrophoneTrack(constructor, constraints) {
|
|
|
543
543
|
* Creates a display video track.
|
|
544
544
|
*
|
|
545
545
|
* @param constructor - Constructor for the local display track.
|
|
546
|
+
* @param videoContentHint - An optional parameters to give a hint for the content of the track.
|
|
546
547
|
* @returns A Promise that resolves to a LocalDisplayTrack.
|
|
547
548
|
*/
|
|
548
|
-
function createDisplayTrack(constructor) {
|
|
549
|
+
function createDisplayTrack(constructor, videoContentHint) {
|
|
549
550
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
550
551
|
const stream = yield getDisplayMedia({ video: true });
|
|
551
|
-
return new constructor(stream);
|
|
552
|
+
return new constructor(stream, videoContentHint);
|
|
552
553
|
});
|
|
553
554
|
}
|
|
554
555
|
/**
|
|
@@ -1354,6 +1355,25 @@ class LocalCameraTrack extends LocalTrack {
|
|
|
1354
1355
|
* Represents a local track for a display source.
|
|
1355
1356
|
*/
|
|
1356
1357
|
class LocalDisplayTrack extends LocalTrack {
|
|
1358
|
+
/**
|
|
1359
|
+
* Create a LocalDisplayTrack from the given values.
|
|
1360
|
+
*
|
|
1361
|
+
* @param stream - The MediaStream for this track.
|
|
1362
|
+
* @param videoContentHint - An optional content hint, describing the content of the track.
|
|
1363
|
+
*/
|
|
1364
|
+
constructor(stream, videoContentHint) {
|
|
1365
|
+
super(stream);
|
|
1366
|
+
this._videoContentHint = videoContentHint;
|
|
1367
|
+
this.underlyingTrack.contentHint = videoContentHint || '';
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Get the VideoContentHint for this track.
|
|
1371
|
+
*
|
|
1372
|
+
* @returns The VideoContentHint for this track.
|
|
1373
|
+
*/
|
|
1374
|
+
get videoContentHint() {
|
|
1375
|
+
return this._videoContentHint;
|
|
1376
|
+
}
|
|
1357
1377
|
}
|
|
1358
1378
|
|
|
1359
1379
|
/**
|
|
@@ -5705,11 +5725,12 @@ function compareStreamIds(id1, id2) {
|
|
|
5705
5725
|
}
|
|
5706
5726
|
|
|
5707
5727
|
class SourceIndicationMsg {
|
|
5708
|
-
constructor(seqNum, numTotalSources, numLiveSources, sources) {
|
|
5728
|
+
constructor(seqNum, numTotalSources, numLiveSources, sources, videoContentHint) {
|
|
5709
5729
|
this.seqNum = seqNum;
|
|
5710
5730
|
this.numTotalSources = numTotalSources;
|
|
5711
5731
|
this.numLiveSources = numLiveSources;
|
|
5712
5732
|
this.sources = sources;
|
|
5733
|
+
this.videoContentHint = videoContentHint;
|
|
5713
5734
|
}
|
|
5714
5735
|
sourcesToString() {
|
|
5715
5736
|
return this.sources
|
|
@@ -5805,13 +5826,13 @@ class JmpSession extends EventEmitter$3 {
|
|
|
5805
5826
|
this.logger.warn(`Retransmits for message expired: ${expiredJmpMsg}`);
|
|
5806
5827
|
});
|
|
5807
5828
|
}
|
|
5808
|
-
updateSourceIndication(numTotalSources, numLiveSources, sources) {
|
|
5829
|
+
updateSourceIndication(numTotalSources, numLiveSources, sources, videoContentHint) {
|
|
5809
5830
|
var _a;
|
|
5810
5831
|
const filteredSources = sources.filter((source) => {
|
|
5811
5832
|
var _a;
|
|
5812
5833
|
return (_a = this.lastReceivedScr) === null || _a === void 0 ? void 0 : _a.requests.some((req) => req.ids.find((streamId) => compareStreamIds(streamId, source.id)));
|
|
5813
5834
|
});
|
|
5814
|
-
const sourceIndicationMsg = new SourceIndicationMsg(this.currSourceIndicationSeqNum++, numTotalSources, numLiveSources, filteredSources);
|
|
5835
|
+
const sourceIndicationMsg = new SourceIndicationMsg(this.currSourceIndicationSeqNum++, numTotalSources, numLiveSources, filteredSources, videoContentHint);
|
|
5815
5836
|
const jmpMsg = new JmpMsg(this.mediaFamily, this.mediaContent, {
|
|
5816
5837
|
msgType: JmpMsgType.SourceIndication,
|
|
5817
5838
|
payload: sourceIndicationMsg,
|
|
@@ -9197,23 +9218,58 @@ class SsrcEgressStreamSignaler {
|
|
|
9197
9218
|
this.streamIds = [];
|
|
9198
9219
|
}
|
|
9199
9220
|
signalStreams(simulcastEnabled, rtxEnabled, mLine) {
|
|
9221
|
+
var _a;
|
|
9200
9222
|
mLine.rids = [];
|
|
9201
9223
|
mLine.simulcast = undefined;
|
|
9202
|
-
mLine.ssrcs = [];
|
|
9203
|
-
mLine.ssrcGroups = [];
|
|
9204
9224
|
mLine.extMaps = mLine.extMaps.filter((extMapLine) => !/^urn:ietf:params:rtp-hdrext:sdes:(?:mid|rtp-stream-id|repaired-rtp-stream-id)$/.test(extMapLine.uri));
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
const
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9225
|
+
const numStreams = simulcastEnabled ? 3 : 1;
|
|
9226
|
+
if (!this.streamIds.length) {
|
|
9227
|
+
if (mLine.ssrcs.length) {
|
|
9228
|
+
const ssrcs = [...new Set(mLine.ssrcs.map((ssrcLine) => ssrcLine.ssrcId))];
|
|
9229
|
+
mLine.ssrcGroups.forEach((sg) => {
|
|
9230
|
+
if (!sg.ssrcs.every((ssrc) => ssrcs.includes(ssrc))) {
|
|
9231
|
+
throw new Error('SSRC present in SSRC groups is missing from SSRC lines');
|
|
9232
|
+
}
|
|
9233
|
+
});
|
|
9234
|
+
const rtxSsrcGroups = mLine.ssrcGroups.filter((sg) => sg.semantics === 'FID');
|
|
9235
|
+
if (rtxSsrcGroups.length && rtxSsrcGroups.length !== numStreams) {
|
|
9236
|
+
throw new Error(`Expect ${numStreams} RTX SSRC groups, got ${rtxSsrcGroups.length}`);
|
|
9213
9237
|
}
|
|
9214
|
-
|
|
9215
|
-
|
|
9238
|
+
rtxSsrcGroups.forEach((sg) => {
|
|
9239
|
+
this.streamIds.push({
|
|
9240
|
+
ssrc: sg.ssrcs[0],
|
|
9241
|
+
rtxSsrc: sg.ssrcs[1],
|
|
9242
|
+
});
|
|
9243
|
+
});
|
|
9244
|
+
const simulcastSsrcs = (_a = mLine.ssrcGroups.find((sg) => sg.semantics === 'SIM')) === null || _a === void 0 ? void 0 : _a.ssrcs;
|
|
9245
|
+
if (simulcastSsrcs) {
|
|
9246
|
+
if (simulcastSsrcs.length !== numStreams ||
|
|
9247
|
+
!this.streamIds.every((streamId) => simulcastSsrcs.includes(streamId.ssrc))) {
|
|
9248
|
+
throw new Error('SSRCs in simulcast SSRC group do not match primary SSRCs in RTX SSRC groups');
|
|
9249
|
+
}
|
|
9250
|
+
this.streamIds.sort((a, b) => simulcastSsrcs.indexOf(a.ssrc) - simulcastSsrcs.indexOf(b.ssrc));
|
|
9251
|
+
}
|
|
9252
|
+
else if (rtxSsrcGroups.length > 1) {
|
|
9253
|
+
throw new Error('Multiple RTX SSRC groups but no simulcast SSRC group found');
|
|
9254
|
+
}
|
|
9255
|
+
if (!this.streamIds.length) {
|
|
9256
|
+
this.streamIds.push({ ssrc: ssrcs[0] });
|
|
9257
|
+
}
|
|
9258
|
+
}
|
|
9259
|
+
else {
|
|
9260
|
+
[...Array(numStreams).keys()].forEach(() => {
|
|
9261
|
+
const newStreamId = {
|
|
9262
|
+
ssrc: generateSsrc(),
|
|
9263
|
+
};
|
|
9264
|
+
if (rtxEnabled) {
|
|
9265
|
+
newStreamId.rtxSsrc = generateSsrc();
|
|
9266
|
+
}
|
|
9267
|
+
this.streamIds.push(newStreamId);
|
|
9268
|
+
});
|
|
9269
|
+
}
|
|
9216
9270
|
}
|
|
9271
|
+
mLine.ssrcs = [];
|
|
9272
|
+
mLine.ssrcGroups = [];
|
|
9217
9273
|
this.streamIds.forEach((streamId) => {
|
|
9218
9274
|
const rtpSsrc = streamId.ssrc;
|
|
9219
9275
|
mLine.addLine(new SsrcLine(rtpSsrc, 'cname', `${rtpSsrc}-cname`));
|
|
@@ -9681,6 +9737,15 @@ function toMediaStreamTrackKind(mediaType) {
|
|
|
9681
9737
|
? MediaStreamTrackKind.Video
|
|
9682
9738
|
: MediaStreamTrackKind.Audio;
|
|
9683
9739
|
}
|
|
9740
|
+
function webRtcVideoContentHintToJmpVideoContentHint(hint) {
|
|
9741
|
+
if (hint === 'motion') {
|
|
9742
|
+
return 'motion';
|
|
9743
|
+
}
|
|
9744
|
+
if (hint === 'detail') {
|
|
9745
|
+
return 'sharpness';
|
|
9746
|
+
}
|
|
9747
|
+
return undefined;
|
|
9748
|
+
}
|
|
9684
9749
|
function toMediaFamily(kind) {
|
|
9685
9750
|
if (kind === MediaStreamTrackKind.Video) {
|
|
9686
9751
|
return MediaFamily.Video;
|
|
@@ -9929,24 +9994,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9929
9994
|
const dataChannel = this.pc.createDataChannel('datachannel', {});
|
|
9930
9995
|
dataChannel.onopen = (e) => {
|
|
9931
9996
|
logger.info('DataChannel opened: ', e);
|
|
9932
|
-
this.sendTransceivers.forEach((
|
|
9933
|
-
|
|
9934
|
-
if (track) {
|
|
9935
|
-
if (getMediaFamily(mediaType) === MediaFamily.Audio) {
|
|
9936
|
-
this.sendSourceIndication(mediaType, +!track.muted);
|
|
9937
|
-
}
|
|
9938
|
-
else {
|
|
9939
|
-
const signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(transceiver.mid);
|
|
9940
|
-
const state = track.muted ? 'avatar' : 'live';
|
|
9941
|
-
const sources = signaler
|
|
9942
|
-
.getSenderIds()
|
|
9943
|
-
.map((id) => ({ id, state, csi: transceiver.csi }));
|
|
9944
|
-
this.sendSourceIndication(mediaType, +!track.muted, sources);
|
|
9945
|
-
}
|
|
9946
|
-
}
|
|
9947
|
-
else {
|
|
9948
|
-
this.sendSourceIndication(mediaType, 0);
|
|
9949
|
-
}
|
|
9997
|
+
[...this.sendTransceivers.keys()].forEach((mediaType) => {
|
|
9998
|
+
this.maybeSendSourceIndication(mediaType);
|
|
9950
9999
|
});
|
|
9951
10000
|
logger.info(`Flushing pending JMP task queue`);
|
|
9952
10001
|
this.pendingJmpTasks.forEach((t) => t());
|
|
@@ -9995,11 +10044,31 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9995
10044
|
});
|
|
9996
10045
|
this.pc.close();
|
|
9997
10046
|
}
|
|
9998
|
-
|
|
10047
|
+
maybeSendSourceIndication(mediaType) {
|
|
10048
|
+
var _a;
|
|
10049
|
+
const transceiver = this.getSendTransceiverOrThrow(mediaType);
|
|
10050
|
+
const numLiveSources = ((_a = transceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.muted) === false ? 1 : 0;
|
|
10051
|
+
if (getMediaFamily(mediaType) === MediaFamily.Video) {
|
|
10052
|
+
const sources = this.getVideoSources(mediaType);
|
|
10053
|
+
if (sources === null) {
|
|
10054
|
+
return;
|
|
10055
|
+
}
|
|
10056
|
+
let webRtcVideoContentHint;
|
|
10057
|
+
if (transceiver.publishedTrack instanceof LocalDisplayTrack) {
|
|
10058
|
+
webRtcVideoContentHint = transceiver.publishedTrack.videoContentHint;
|
|
10059
|
+
}
|
|
10060
|
+
this.sendSourceIndication(mediaType, numLiveSources, sources, webRtcVideoContentHintToJmpVideoContentHint(webRtcVideoContentHint));
|
|
10061
|
+
}
|
|
10062
|
+
else {
|
|
10063
|
+
this.sendSourceIndication(mediaType, numLiveSources);
|
|
10064
|
+
}
|
|
10065
|
+
}
|
|
10066
|
+
sendSourceIndication(mediaType, numLiveSources, sources = [], videoContentHint = undefined) {
|
|
9999
10067
|
var _a;
|
|
10000
10068
|
const task = () => {
|
|
10001
10069
|
var _a;
|
|
10002
|
-
(_a = this.jmpSessions
|
|
10070
|
+
(_a = this.jmpSessions
|
|
10071
|
+
.get(mediaType)) === null || _a === void 0 ? void 0 : _a.updateSourceIndication(1, numLiveSources, sources, videoContentHint);
|
|
10003
10072
|
};
|
|
10004
10073
|
if (((_a = this.dataChannel) === null || _a === void 0 ? void 0 : _a.readyState) === 'open') {
|
|
10005
10074
|
task();
|
|
@@ -10044,24 +10113,9 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10044
10113
|
});
|
|
10045
10114
|
}
|
|
10046
10115
|
addTrackListeners(mediaType, track) {
|
|
10047
|
-
const onTrackResolutionChange = () =>
|
|
10048
|
-
const sources = this.getVideoSources(mediaType);
|
|
10049
|
-
if (sources != null) {
|
|
10050
|
-
this.sendSourceIndication(mediaType, 1, sources);
|
|
10051
|
-
}
|
|
10052
|
-
};
|
|
10116
|
+
const onTrackResolutionChange = () => this.maybeSendSourceIndication(mediaType);
|
|
10053
10117
|
track.on(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
10054
|
-
const onTrackMute = (
|
|
10055
|
-
if (getMediaFamily(mediaType) === MediaFamily.Audio) {
|
|
10056
|
-
this.sendSourceIndication(mediaType, +!event.trackState.muted);
|
|
10057
|
-
}
|
|
10058
|
-
else {
|
|
10059
|
-
const sources = this.getVideoSources(mediaType);
|
|
10060
|
-
if (sources != null) {
|
|
10061
|
-
this.sendSourceIndication(mediaType, +!event.trackState.muted, sources);
|
|
10062
|
-
}
|
|
10063
|
-
}
|
|
10064
|
-
};
|
|
10118
|
+
const onTrackMute = () => this.maybeSendSourceIndication(mediaType);
|
|
10065
10119
|
track.on(LocalTrack.Events.Muted, onTrackMute);
|
|
10066
10120
|
const onTrackPublish = (event) => {
|
|
10067
10121
|
if (!event.isPublished) {
|
|
@@ -10069,14 +10123,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10069
10123
|
track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
10070
10124
|
track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
10071
10125
|
}
|
|
10072
|
-
if (
|
|
10073
|
-
this.
|
|
10074
|
-
}
|
|
10075
|
-
else {
|
|
10076
|
-
const sources = this.getVideoSources(mediaType);
|
|
10077
|
-
if (sources != null) {
|
|
10078
|
-
this.sendSourceIndication(mediaType, +event.isPublished, sources);
|
|
10079
|
-
}
|
|
10126
|
+
if (!track.muted) {
|
|
10127
|
+
this.maybeSendSourceIndication(mediaType);
|
|
10080
10128
|
}
|
|
10081
10129
|
};
|
|
10082
10130
|
track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|