@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/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,
|
|
@@ -9201,23 +9222,58 @@ class SsrcEgressStreamSignaler {
|
|
|
9201
9222
|
this.streamIds = [];
|
|
9202
9223
|
}
|
|
9203
9224
|
signalStreams(simulcastEnabled, rtxEnabled, mLine) {
|
|
9225
|
+
var _a;
|
|
9204
9226
|
mLine.rids = [];
|
|
9205
9227
|
mLine.simulcast = undefined;
|
|
9206
|
-
mLine.ssrcs = [];
|
|
9207
|
-
mLine.ssrcGroups = [];
|
|
9208
9228
|
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
|
-
|
|
9229
|
+
const numStreams = simulcastEnabled ? 3 : 1;
|
|
9230
|
+
if (!this.streamIds.length) {
|
|
9231
|
+
if (mLine.ssrcs.length) {
|
|
9232
|
+
const ssrcs = [...new Set(mLine.ssrcs.map((ssrcLine) => ssrcLine.ssrcId))];
|
|
9233
|
+
mLine.ssrcGroups.forEach((sg) => {
|
|
9234
|
+
if (!sg.ssrcs.every((ssrc) => ssrcs.includes(ssrc))) {
|
|
9235
|
+
throw new Error('SSRC present in SSRC groups is missing from SSRC lines');
|
|
9236
|
+
}
|
|
9237
|
+
});
|
|
9238
|
+
const rtxSsrcGroups = mLine.ssrcGroups.filter((sg) => sg.semantics === 'FID');
|
|
9239
|
+
if (rtxSsrcGroups.length && rtxSsrcGroups.length !== numStreams) {
|
|
9240
|
+
throw new Error(`Expect ${numStreams} RTX SSRC groups, got ${rtxSsrcGroups.length}`);
|
|
9217
9241
|
}
|
|
9218
|
-
|
|
9219
|
-
|
|
9242
|
+
rtxSsrcGroups.forEach((sg) => {
|
|
9243
|
+
this.streamIds.push({
|
|
9244
|
+
ssrc: sg.ssrcs[0],
|
|
9245
|
+
rtxSsrc: sg.ssrcs[1],
|
|
9246
|
+
});
|
|
9247
|
+
});
|
|
9248
|
+
const simulcastSsrcs = (_a = mLine.ssrcGroups.find((sg) => sg.semantics === 'SIM')) === null || _a === void 0 ? void 0 : _a.ssrcs;
|
|
9249
|
+
if (simulcastSsrcs) {
|
|
9250
|
+
if (simulcastSsrcs.length !== numStreams ||
|
|
9251
|
+
!this.streamIds.every((streamId) => simulcastSsrcs.includes(streamId.ssrc))) {
|
|
9252
|
+
throw new Error('SSRCs in simulcast SSRC group do not match primary SSRCs in RTX SSRC groups');
|
|
9253
|
+
}
|
|
9254
|
+
this.streamIds.sort((a, b) => simulcastSsrcs.indexOf(a.ssrc) - simulcastSsrcs.indexOf(b.ssrc));
|
|
9255
|
+
}
|
|
9256
|
+
else if (rtxSsrcGroups.length > 1) {
|
|
9257
|
+
throw new Error('Multiple RTX SSRC groups but no simulcast SSRC group found');
|
|
9258
|
+
}
|
|
9259
|
+
if (!this.streamIds.length) {
|
|
9260
|
+
this.streamIds.push({ ssrc: ssrcs[0] });
|
|
9261
|
+
}
|
|
9262
|
+
}
|
|
9263
|
+
else {
|
|
9264
|
+
[...Array(numStreams).keys()].forEach(() => {
|
|
9265
|
+
const newStreamId = {
|
|
9266
|
+
ssrc: generateSsrc(),
|
|
9267
|
+
};
|
|
9268
|
+
if (rtxEnabled) {
|
|
9269
|
+
newStreamId.rtxSsrc = generateSsrc();
|
|
9270
|
+
}
|
|
9271
|
+
this.streamIds.push(newStreamId);
|
|
9272
|
+
});
|
|
9273
|
+
}
|
|
9220
9274
|
}
|
|
9275
|
+
mLine.ssrcs = [];
|
|
9276
|
+
mLine.ssrcGroups = [];
|
|
9221
9277
|
this.streamIds.forEach((streamId) => {
|
|
9222
9278
|
const rtpSsrc = streamId.ssrc;
|
|
9223
9279
|
mLine.addLine(new SsrcLine(rtpSsrc, 'cname', `${rtpSsrc}-cname`));
|
|
@@ -9685,6 +9741,15 @@ function toMediaStreamTrackKind(mediaType) {
|
|
|
9685
9741
|
? exports.MediaStreamTrackKind.Video
|
|
9686
9742
|
: exports.MediaStreamTrackKind.Audio;
|
|
9687
9743
|
}
|
|
9744
|
+
function webRtcVideoContentHintToJmpVideoContentHint(hint) {
|
|
9745
|
+
if (hint === 'motion') {
|
|
9746
|
+
return 'motion';
|
|
9747
|
+
}
|
|
9748
|
+
if (hint === 'detail') {
|
|
9749
|
+
return 'sharpness';
|
|
9750
|
+
}
|
|
9751
|
+
return undefined;
|
|
9752
|
+
}
|
|
9688
9753
|
function toMediaFamily(kind) {
|
|
9689
9754
|
if (kind === exports.MediaStreamTrackKind.Video) {
|
|
9690
9755
|
return MediaFamily.Video;
|
|
@@ -9933,24 +9998,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9933
9998
|
const dataChannel = this.pc.createDataChannel('datachannel', {});
|
|
9934
9999
|
dataChannel.onopen = (e) => {
|
|
9935
10000
|
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
|
-
}
|
|
10001
|
+
[...this.sendTransceivers.keys()].forEach((mediaType) => {
|
|
10002
|
+
this.maybeSendSourceIndication(mediaType);
|
|
9954
10003
|
});
|
|
9955
10004
|
logger.info(`Flushing pending JMP task queue`);
|
|
9956
10005
|
this.pendingJmpTasks.forEach((t) => t());
|
|
@@ -9999,11 +10048,31 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9999
10048
|
});
|
|
10000
10049
|
this.pc.close();
|
|
10001
10050
|
}
|
|
10002
|
-
|
|
10051
|
+
maybeSendSourceIndication(mediaType) {
|
|
10052
|
+
var _a;
|
|
10053
|
+
const transceiver = this.getSendTransceiverOrThrow(mediaType);
|
|
10054
|
+
const numLiveSources = ((_a = transceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.muted) === false ? 1 : 0;
|
|
10055
|
+
if (getMediaFamily(mediaType) === MediaFamily.Video) {
|
|
10056
|
+
const sources = this.getVideoSources(mediaType);
|
|
10057
|
+
if (sources === null) {
|
|
10058
|
+
return;
|
|
10059
|
+
}
|
|
10060
|
+
let webRtcVideoContentHint;
|
|
10061
|
+
if (transceiver.publishedTrack instanceof LocalDisplayTrack) {
|
|
10062
|
+
webRtcVideoContentHint = transceiver.publishedTrack.videoContentHint;
|
|
10063
|
+
}
|
|
10064
|
+
this.sendSourceIndication(mediaType, numLiveSources, sources, webRtcVideoContentHintToJmpVideoContentHint(webRtcVideoContentHint));
|
|
10065
|
+
}
|
|
10066
|
+
else {
|
|
10067
|
+
this.sendSourceIndication(mediaType, numLiveSources);
|
|
10068
|
+
}
|
|
10069
|
+
}
|
|
10070
|
+
sendSourceIndication(mediaType, numLiveSources, sources = [], videoContentHint = undefined) {
|
|
10003
10071
|
var _a;
|
|
10004
10072
|
const task = () => {
|
|
10005
10073
|
var _a;
|
|
10006
|
-
(_a = this.jmpSessions
|
|
10074
|
+
(_a = this.jmpSessions
|
|
10075
|
+
.get(mediaType)) === null || _a === void 0 ? void 0 : _a.updateSourceIndication(1, numLiveSources, sources, videoContentHint);
|
|
10007
10076
|
};
|
|
10008
10077
|
if (((_a = this.dataChannel) === null || _a === void 0 ? void 0 : _a.readyState) === 'open') {
|
|
10009
10078
|
task();
|
|
@@ -10048,24 +10117,9 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10048
10117
|
});
|
|
10049
10118
|
}
|
|
10050
10119
|
addTrackListeners(mediaType, track) {
|
|
10051
|
-
const onTrackResolutionChange = () =>
|
|
10052
|
-
const sources = this.getVideoSources(mediaType);
|
|
10053
|
-
if (sources != null) {
|
|
10054
|
-
this.sendSourceIndication(mediaType, 1, sources);
|
|
10055
|
-
}
|
|
10056
|
-
};
|
|
10120
|
+
const onTrackResolutionChange = () => this.maybeSendSourceIndication(mediaType);
|
|
10057
10121
|
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
|
-
};
|
|
10122
|
+
const onTrackMute = () => this.maybeSendSourceIndication(mediaType);
|
|
10069
10123
|
track.on(LocalTrack.Events.Muted, onTrackMute);
|
|
10070
10124
|
const onTrackPublish = (event) => {
|
|
10071
10125
|
if (!event.isPublished) {
|
|
@@ -10073,14 +10127,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10073
10127
|
track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
10074
10128
|
track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
10075
10129
|
}
|
|
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
|
-
}
|
|
10130
|
+
if (!track.muted) {
|
|
10131
|
+
this.maybeSendSourceIndication(mediaType);
|
|
10084
10132
|
}
|
|
10085
10133
|
};
|
|
10086
10134
|
track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|