@webex/web-client-media-engine 1.40.4 → 1.40.6
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 +113 -63
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +113 -63
- package/dist/esm/index.js.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/package.json +3 -3
package/dist/cjs/index.js
CHANGED
|
@@ -547,12 +547,13 @@ function createMicrophoneTrack(constructor, constraints) {
|
|
|
547
547
|
* Creates a display video track.
|
|
548
548
|
*
|
|
549
549
|
* @param constructor - Constructor for the local display track.
|
|
550
|
+
* @param videoContentHint - An optional parameters to give a hint for the content of the track.
|
|
550
551
|
* @returns A Promise that resolves to a LocalDisplayTrack.
|
|
551
552
|
*/
|
|
552
|
-
function createDisplayTrack(constructor) {
|
|
553
|
+
function createDisplayTrack(constructor, videoContentHint) {
|
|
553
554
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
554
555
|
const stream = yield getDisplayMedia({ video: true });
|
|
555
|
-
return new constructor(stream);
|
|
556
|
+
return new constructor(stream, videoContentHint);
|
|
556
557
|
});
|
|
557
558
|
}
|
|
558
559
|
/**
|
|
@@ -1358,6 +1359,25 @@ class LocalCameraTrack extends LocalTrack {
|
|
|
1358
1359
|
* Represents a local track for a display source.
|
|
1359
1360
|
*/
|
|
1360
1361
|
class LocalDisplayTrack extends LocalTrack {
|
|
1362
|
+
/**
|
|
1363
|
+
* Create a LocalDisplayTrack from the given values.
|
|
1364
|
+
*
|
|
1365
|
+
* @param stream - The MediaStream for this track.
|
|
1366
|
+
* @param videoContentHint - An optional content hint, describing the content of the track.
|
|
1367
|
+
*/
|
|
1368
|
+
constructor(stream, videoContentHint) {
|
|
1369
|
+
super(stream);
|
|
1370
|
+
this._videoContentHint = videoContentHint;
|
|
1371
|
+
this.underlyingTrack.contentHint = videoContentHint || '';
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Get the VideoContentHint for this track.
|
|
1375
|
+
*
|
|
1376
|
+
* @returns The VideoContentHint for this track.
|
|
1377
|
+
*/
|
|
1378
|
+
get videoContentHint() {
|
|
1379
|
+
return this._videoContentHint;
|
|
1380
|
+
}
|
|
1361
1381
|
}
|
|
1362
1382
|
|
|
1363
1383
|
/**
|
|
@@ -5709,11 +5729,12 @@ function compareStreamIds(id1, id2) {
|
|
|
5709
5729
|
}
|
|
5710
5730
|
|
|
5711
5731
|
class SourceIndicationMsg {
|
|
5712
|
-
constructor(seqNum, numTotalSources, numLiveSources, sources) {
|
|
5732
|
+
constructor(seqNum, numTotalSources, numLiveSources, sources, videoContentHint) {
|
|
5713
5733
|
this.seqNum = seqNum;
|
|
5714
5734
|
this.numTotalSources = numTotalSources;
|
|
5715
5735
|
this.numLiveSources = numLiveSources;
|
|
5716
5736
|
this.sources = sources;
|
|
5737
|
+
this.videoContentHint = videoContentHint;
|
|
5717
5738
|
}
|
|
5718
5739
|
sourcesToString() {
|
|
5719
5740
|
return this.sources
|
|
@@ -5809,13 +5830,13 @@ class JmpSession extends events$2.EventEmitter {
|
|
|
5809
5830
|
this.logger.warn(`Retransmits for message expired: ${expiredJmpMsg}`);
|
|
5810
5831
|
});
|
|
5811
5832
|
}
|
|
5812
|
-
updateSourceIndication(numTotalSources, numLiveSources, sources) {
|
|
5833
|
+
updateSourceIndication(numTotalSources, numLiveSources, sources, videoContentHint) {
|
|
5813
5834
|
var _a;
|
|
5814
5835
|
const filteredSources = sources.filter((source) => {
|
|
5815
5836
|
var _a;
|
|
5816
5837
|
return (_a = this.lastReceivedScr) === null || _a === void 0 ? void 0 : _a.requests.some((req) => req.ids.find((streamId) => compareStreamIds(streamId, source.id)));
|
|
5817
5838
|
});
|
|
5818
|
-
const sourceIndicationMsg = new SourceIndicationMsg(this.currSourceIndicationSeqNum++, numTotalSources, numLiveSources, filteredSources);
|
|
5839
|
+
const sourceIndicationMsg = new SourceIndicationMsg(this.currSourceIndicationSeqNum++, numTotalSources, numLiveSources, filteredSources, videoContentHint);
|
|
5819
5840
|
const jmpMsg = new JmpMsg(this.mediaFamily, this.mediaContent, {
|
|
5820
5841
|
msgType: JmpMsgType.SourceIndication,
|
|
5821
5842
|
payload: sourceIndicationMsg,
|
|
@@ -9189,7 +9210,9 @@ class SsrcIngressStreamSignaler {
|
|
|
9189
9210
|
mLine.addLine(new SsrcLine(this.ssrc, 'cname', `${this.ssrc}-cname`));
|
|
9190
9211
|
mLine.addLine(new SsrcLine(this.ssrc, 'msid', '-', '1'));
|
|
9191
9212
|
if (hasCodec('rtx', mLine)) {
|
|
9192
|
-
this.rtxSsrc
|
|
9213
|
+
if (!this.rtxSsrc) {
|
|
9214
|
+
this.rtxSsrc = generateSsrc();
|
|
9215
|
+
}
|
|
9193
9216
|
mLine.addLine(new SsrcLine(this.rtxSsrc, 'cname', `${this.ssrc}-cname`));
|
|
9194
9217
|
mLine.addLine(new SsrcLine(this.rtxSsrc, 'msid', '-', '1'));
|
|
9195
9218
|
mLine.addLine(new SsrcGroupLine('FID', [this.ssrc, this.rtxSsrc]));
|
|
@@ -9201,23 +9224,58 @@ class SsrcEgressStreamSignaler {
|
|
|
9201
9224
|
this.streamIds = [];
|
|
9202
9225
|
}
|
|
9203
9226
|
signalStreams(simulcastEnabled, rtxEnabled, mLine) {
|
|
9227
|
+
var _a;
|
|
9204
9228
|
mLine.rids = [];
|
|
9205
9229
|
mLine.simulcast = undefined;
|
|
9206
|
-
mLine.ssrcs = [];
|
|
9207
|
-
mLine.ssrcGroups = [];
|
|
9208
9230
|
mLine.extMaps = mLine.extMaps.filter((extMapLine) => !/^urn:ietf:params:rtp-hdrext:sdes:(?:mid|rtp-stream-id|repaired-rtp-stream-id)$/.test(extMapLine.uri));
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
const
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9231
|
+
const numStreams = simulcastEnabled ? 3 : 1;
|
|
9232
|
+
if (!this.streamIds.length) {
|
|
9233
|
+
if (mLine.ssrcs.length) {
|
|
9234
|
+
const ssrcs = [...new Set(mLine.ssrcs.map((ssrcLine) => ssrcLine.ssrcId))];
|
|
9235
|
+
mLine.ssrcGroups.forEach((sg) => {
|
|
9236
|
+
if (!sg.ssrcs.every((ssrc) => ssrcs.includes(ssrc))) {
|
|
9237
|
+
throw new Error('SSRC present in SSRC groups is missing from SSRC lines');
|
|
9238
|
+
}
|
|
9239
|
+
});
|
|
9240
|
+
const rtxSsrcGroups = mLine.ssrcGroups.filter((sg) => sg.semantics === 'FID');
|
|
9241
|
+
if (rtxSsrcGroups.length && rtxSsrcGroups.length !== numStreams) {
|
|
9242
|
+
throw new Error(`Expect ${numStreams} RTX SSRC groups, got ${rtxSsrcGroups.length}`);
|
|
9217
9243
|
}
|
|
9218
|
-
|
|
9219
|
-
|
|
9244
|
+
rtxSsrcGroups.forEach((sg) => {
|
|
9245
|
+
this.streamIds.push({
|
|
9246
|
+
ssrc: sg.ssrcs[0],
|
|
9247
|
+
rtxSsrc: sg.ssrcs[1],
|
|
9248
|
+
});
|
|
9249
|
+
});
|
|
9250
|
+
const simulcastSsrcs = (_a = mLine.ssrcGroups.find((sg) => sg.semantics === 'SIM')) === null || _a === void 0 ? void 0 : _a.ssrcs;
|
|
9251
|
+
if (simulcastSsrcs) {
|
|
9252
|
+
if (simulcastSsrcs.length !== numStreams ||
|
|
9253
|
+
!this.streamIds.every((streamId) => simulcastSsrcs.includes(streamId.ssrc))) {
|
|
9254
|
+
throw new Error('SSRCs in simulcast SSRC group do not match primary SSRCs in RTX SSRC groups');
|
|
9255
|
+
}
|
|
9256
|
+
this.streamIds.sort((a, b) => simulcastSsrcs.indexOf(a.ssrc) - simulcastSsrcs.indexOf(b.ssrc));
|
|
9257
|
+
}
|
|
9258
|
+
else if (rtxSsrcGroups.length > 1) {
|
|
9259
|
+
throw new Error('Multiple RTX SSRC groups but no simulcast SSRC group found');
|
|
9260
|
+
}
|
|
9261
|
+
if (!this.streamIds.length) {
|
|
9262
|
+
this.streamIds.push({ ssrc: ssrcs[0] });
|
|
9263
|
+
}
|
|
9264
|
+
}
|
|
9265
|
+
else {
|
|
9266
|
+
[...Array(numStreams).keys()].forEach(() => {
|
|
9267
|
+
const newStreamId = {
|
|
9268
|
+
ssrc: generateSsrc(),
|
|
9269
|
+
};
|
|
9270
|
+
if (rtxEnabled) {
|
|
9271
|
+
newStreamId.rtxSsrc = generateSsrc();
|
|
9272
|
+
}
|
|
9273
|
+
this.streamIds.push(newStreamId);
|
|
9274
|
+
});
|
|
9275
|
+
}
|
|
9220
9276
|
}
|
|
9277
|
+
mLine.ssrcs = [];
|
|
9278
|
+
mLine.ssrcGroups = [];
|
|
9221
9279
|
this.streamIds.forEach((streamId) => {
|
|
9222
9280
|
const rtpSsrc = streamId.ssrc;
|
|
9223
9281
|
mLine.addLine(new SsrcLine(rtpSsrc, 'cname', `${rtpSsrc}-cname`));
|
|
@@ -9685,6 +9743,15 @@ function toMediaStreamTrackKind(mediaType) {
|
|
|
9685
9743
|
? exports.MediaStreamTrackKind.Video
|
|
9686
9744
|
: exports.MediaStreamTrackKind.Audio;
|
|
9687
9745
|
}
|
|
9746
|
+
function webRtcVideoContentHintToJmpVideoContentHint(hint) {
|
|
9747
|
+
if (hint === 'motion') {
|
|
9748
|
+
return 'motion';
|
|
9749
|
+
}
|
|
9750
|
+
if (hint === 'detail') {
|
|
9751
|
+
return 'sharpness';
|
|
9752
|
+
}
|
|
9753
|
+
return undefined;
|
|
9754
|
+
}
|
|
9688
9755
|
function toMediaFamily(kind) {
|
|
9689
9756
|
if (kind === exports.MediaStreamTrackKind.Video) {
|
|
9690
9757
|
return MediaFamily.Video;
|
|
@@ -9933,24 +10000,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9933
10000
|
const dataChannel = this.pc.createDataChannel('datachannel', {});
|
|
9934
10001
|
dataChannel.onopen = (e) => {
|
|
9935
10002
|
logger.info('DataChannel opened: ', e);
|
|
9936
|
-
this.sendTransceivers.forEach((
|
|
9937
|
-
|
|
9938
|
-
if (track) {
|
|
9939
|
-
if (getMediaFamily(mediaType) === MediaFamily.Audio) {
|
|
9940
|
-
this.sendSourceIndication(mediaType, +!track.muted);
|
|
9941
|
-
}
|
|
9942
|
-
else {
|
|
9943
|
-
const signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(transceiver.mid);
|
|
9944
|
-
const state = track.muted ? 'avatar' : 'live';
|
|
9945
|
-
const sources = signaler
|
|
9946
|
-
.getSenderIds()
|
|
9947
|
-
.map((id) => ({ id, state, csi: transceiver.csi }));
|
|
9948
|
-
this.sendSourceIndication(mediaType, +!track.muted, sources);
|
|
9949
|
-
}
|
|
9950
|
-
}
|
|
9951
|
-
else {
|
|
9952
|
-
this.sendSourceIndication(mediaType, 0);
|
|
9953
|
-
}
|
|
10003
|
+
[...this.sendTransceivers.keys()].forEach((mediaType) => {
|
|
10004
|
+
this.maybeSendSourceIndication(mediaType);
|
|
9954
10005
|
});
|
|
9955
10006
|
logger.info(`Flushing pending JMP task queue`);
|
|
9956
10007
|
this.pendingJmpTasks.forEach((t) => t());
|
|
@@ -9999,11 +10050,31 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9999
10050
|
});
|
|
10000
10051
|
this.pc.close();
|
|
10001
10052
|
}
|
|
10002
|
-
|
|
10053
|
+
maybeSendSourceIndication(mediaType) {
|
|
10054
|
+
var _a;
|
|
10055
|
+
const transceiver = this.getSendTransceiverOrThrow(mediaType);
|
|
10056
|
+
const numLiveSources = ((_a = transceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.muted) === false ? 1 : 0;
|
|
10057
|
+
if (getMediaFamily(mediaType) === MediaFamily.Video) {
|
|
10058
|
+
const sources = this.getVideoSources(mediaType);
|
|
10059
|
+
if (sources === null) {
|
|
10060
|
+
return;
|
|
10061
|
+
}
|
|
10062
|
+
let webRtcVideoContentHint;
|
|
10063
|
+
if (transceiver.publishedTrack instanceof LocalDisplayTrack) {
|
|
10064
|
+
webRtcVideoContentHint = transceiver.publishedTrack.videoContentHint;
|
|
10065
|
+
}
|
|
10066
|
+
this.sendSourceIndication(mediaType, numLiveSources, sources, webRtcVideoContentHintToJmpVideoContentHint(webRtcVideoContentHint));
|
|
10067
|
+
}
|
|
10068
|
+
else {
|
|
10069
|
+
this.sendSourceIndication(mediaType, numLiveSources);
|
|
10070
|
+
}
|
|
10071
|
+
}
|
|
10072
|
+
sendSourceIndication(mediaType, numLiveSources, sources = [], videoContentHint = undefined) {
|
|
10003
10073
|
var _a;
|
|
10004
10074
|
const task = () => {
|
|
10005
10075
|
var _a;
|
|
10006
|
-
(_a = this.jmpSessions
|
|
10076
|
+
(_a = this.jmpSessions
|
|
10077
|
+
.get(mediaType)) === null || _a === void 0 ? void 0 : _a.updateSourceIndication(1, numLiveSources, sources, videoContentHint);
|
|
10007
10078
|
};
|
|
10008
10079
|
if (((_a = this.dataChannel) === null || _a === void 0 ? void 0 : _a.readyState) === 'open') {
|
|
10009
10080
|
task();
|
|
@@ -10048,24 +10119,9 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10048
10119
|
});
|
|
10049
10120
|
}
|
|
10050
10121
|
addTrackListeners(mediaType, track) {
|
|
10051
|
-
const onTrackResolutionChange = () =>
|
|
10052
|
-
const sources = this.getVideoSources(mediaType);
|
|
10053
|
-
if (sources != null) {
|
|
10054
|
-
this.sendSourceIndication(mediaType, 1, sources);
|
|
10055
|
-
}
|
|
10056
|
-
};
|
|
10122
|
+
const onTrackResolutionChange = () => this.maybeSendSourceIndication(mediaType);
|
|
10057
10123
|
track.on(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
10058
|
-
const onTrackMute = (
|
|
10059
|
-
if (getMediaFamily(mediaType) === MediaFamily.Audio) {
|
|
10060
|
-
this.sendSourceIndication(mediaType, +!event.trackState.muted);
|
|
10061
|
-
}
|
|
10062
|
-
else {
|
|
10063
|
-
const sources = this.getVideoSources(mediaType);
|
|
10064
|
-
if (sources != null) {
|
|
10065
|
-
this.sendSourceIndication(mediaType, +!event.trackState.muted, sources);
|
|
10066
|
-
}
|
|
10067
|
-
}
|
|
10068
|
-
};
|
|
10124
|
+
const onTrackMute = () => this.maybeSendSourceIndication(mediaType);
|
|
10069
10125
|
track.on(LocalTrack.Events.Muted, onTrackMute);
|
|
10070
10126
|
const onTrackPublish = (event) => {
|
|
10071
10127
|
if (!event.isPublished) {
|
|
@@ -10073,14 +10129,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10073
10129
|
track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
10074
10130
|
track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
10075
10131
|
}
|
|
10076
|
-
if (
|
|
10077
|
-
this.
|
|
10078
|
-
}
|
|
10079
|
-
else {
|
|
10080
|
-
const sources = this.getVideoSources(mediaType);
|
|
10081
|
-
if (sources != null) {
|
|
10082
|
-
this.sendSourceIndication(mediaType, +event.isPublished, sources);
|
|
10083
|
-
}
|
|
10132
|
+
if (!track.muted) {
|
|
10133
|
+
this.maybeSendSourceIndication(mediaType);
|
|
10084
10134
|
}
|
|
10085
10135
|
};
|
|
10086
10136
|
track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|