livekit-client 2.10.0 → 2.11.1
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/livekit-client.esm.mjs +358 -231
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +1 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/StreamWriter.d.ts +1 -1
- package/dist/src/room/StreamWriter.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +2 -1
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +10 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/track/create.d.ts +2 -1
- package/dist/src/room/track/create.d.ts.map +1 -1
- package/dist/ts4.2/src/room/RTCEngine.d.ts +1 -0
- package/dist/ts4.2/src/room/StreamWriter.d.ts +1 -1
- package/dist/ts4.2/src/room/events.d.ts +2 -1
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +10 -1
- package/dist/ts4.2/src/room/track/create.d.ts +2 -1
- package/package.json +1 -1
- package/src/api/utils.test.ts +12 -0
- package/src/api/utils.ts +4 -7
- package/src/room/DeviceManager.ts +1 -1
- package/src/room/RTCEngine.ts +5 -0
- package/src/room/Room.ts +1 -1
- package/src/room/StreamWriter.ts +1 -1
- package/src/room/defaults.ts +2 -2
- package/src/room/events.ts +1 -0
- package/src/room/participant/LocalParticipant.ts +167 -95
- package/src/room/track/create.ts +103 -48
- package/src/room/track/utils.ts +6 -6
@@ -11027,6 +11027,7 @@ var EngineEvent;
|
|
11027
11027
|
EngineEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
|
11028
11028
|
EngineEvent["Offline"] = "offline";
|
11029
11029
|
EngineEvent["SignalRequestResponse"] = "signalRequestResponse";
|
11030
|
+
EngineEvent["SignalConnected"] = "signalConnected";
|
11030
11031
|
})(EngineEvent || (EngineEvent = {}));
|
11031
11032
|
var TrackEvent;
|
11032
11033
|
(function (TrackEvent) {
|
@@ -11185,7 +11186,7 @@ function getOSVersion(ua) {
|
|
11185
11186
|
return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
|
11186
11187
|
}
|
11187
11188
|
|
11188
|
-
var version$1 = "2.
|
11189
|
+
var version$1 = "2.11.1";
|
11189
11190
|
|
11190
11191
|
const version = version$1;
|
11191
11192
|
const protocolVersion = 15;
|
@@ -12201,14 +12202,18 @@ function mergeDefaultOptions(options, audioDefaults, videoDefaults) {
|
|
12201
12202
|
// use defaults
|
12202
12203
|
if (clonedOptions.audio) {
|
12203
12204
|
mergeObjectWithoutOverwriting(clonedOptions.audio, audioDefaults);
|
12204
|
-
(_b = (_d = clonedOptions.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId =
|
12205
|
+
(_b = (_d = clonedOptions.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
|
12206
|
+
ideal: 'default'
|
12207
|
+
};
|
12205
12208
|
if (audioProcessor || defaultAudioProcessor) {
|
12206
12209
|
clonedOptions.audio.processor = audioProcessor !== null && audioProcessor !== void 0 ? audioProcessor : defaultAudioProcessor;
|
12207
12210
|
}
|
12208
12211
|
}
|
12209
12212
|
if (clonedOptions.video) {
|
12210
12213
|
mergeObjectWithoutOverwriting(clonedOptions.video, videoDefaults);
|
12211
|
-
(_c = (_e = clonedOptions.video).deviceId) !== null && _c !== void 0 ? _c : _e.deviceId =
|
12214
|
+
(_c = (_e = clonedOptions.video).deviceId) !== null && _c !== void 0 ? _c : _e.deviceId = {
|
12215
|
+
ideal: 'default'
|
12216
|
+
};
|
12212
12217
|
if (videoProcessor || defaultVideoProcessor) {
|
12213
12218
|
clonedOptions.video.processor = videoProcessor !== null && videoProcessor !== void 0 ? videoProcessor : defaultVideoProcessor;
|
12214
12219
|
}
|
@@ -12242,10 +12247,14 @@ function constraintsForOptions(options) {
|
|
12242
12247
|
}
|
12243
12248
|
});
|
12244
12249
|
constraints.video = videoOptions;
|
12245
|
-
(_a = (_c = constraints.video).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId =
|
12250
|
+
(_a = (_c = constraints.video).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId = {
|
12251
|
+
ideal: 'default'
|
12252
|
+
};
|
12246
12253
|
} else {
|
12247
12254
|
constraints.video = options.video ? {
|
12248
|
-
deviceId:
|
12255
|
+
deviceId: {
|
12256
|
+
ideal: 'default'
|
12257
|
+
}
|
12249
12258
|
} : false;
|
12250
12259
|
}
|
12251
12260
|
} else {
|
@@ -12254,10 +12263,14 @@ function constraintsForOptions(options) {
|
|
12254
12263
|
if (options.audio) {
|
12255
12264
|
if (typeof options.audio === 'object') {
|
12256
12265
|
constraints.audio = options.audio;
|
12257
|
-
(_b = (_d = constraints.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId =
|
12266
|
+
(_b = (_d = constraints.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
|
12267
|
+
ideal: 'default'
|
12268
|
+
};
|
12258
12269
|
} else {
|
12259
12270
|
constraints.audio = {
|
12260
|
-
deviceId:
|
12271
|
+
deviceId: {
|
12272
|
+
ideal: 'default'
|
12273
|
+
}
|
12261
12274
|
};
|
12262
12275
|
}
|
12263
12276
|
} else {
|
@@ -12862,7 +12875,9 @@ class DeviceManager {
|
|
12862
12875
|
const permissionsToAcquire = {
|
12863
12876
|
video: kind !== 'audioinput' && kind !== 'audiooutput',
|
12864
12877
|
audio: kind !== 'videoinput' && {
|
12865
|
-
deviceId:
|
12878
|
+
deviceId: {
|
12879
|
+
ideal: 'default'
|
12880
|
+
}
|
12866
12881
|
}
|
12867
12882
|
};
|
12868
12883
|
const stream = yield navigator.mediaDevices.getUserMedia(permissionsToAcquire);
|
@@ -12961,15 +12976,12 @@ function createValidateUrl(rtcWsUrl) {
|
|
12961
12976
|
const urlObj = new URL(toHttpUrl(rtcWsUrl));
|
12962
12977
|
return appendUrlPath(urlObj, 'validate');
|
12963
12978
|
}
|
12964
|
-
function ensureTrailingSlash(
|
12965
|
-
return
|
12979
|
+
function ensureTrailingSlash(path) {
|
12980
|
+
return path.endsWith('/') ? path : "".concat(path, "/");
|
12966
12981
|
}
|
12967
12982
|
function appendUrlPath(urlObj, path) {
|
12968
|
-
|
12969
|
-
|
12970
|
-
return "".concat(result, "?").concat(urlObj.searchParams.toString());
|
12971
|
-
}
|
12972
|
-
return result;
|
12983
|
+
urlObj.pathname = "".concat(ensureTrailingSlash(urlObj.pathname)).concat(path);
|
12984
|
+
return urlObj.toString();
|
12973
12985
|
}
|
12974
12986
|
|
12975
12987
|
const passThroughQueueSignals = ['syncState', 'trickle', 'offer', 'answer', 'simulate', 'leave'];
|
@@ -14959,14 +14971,18 @@ const publishDefaults = {
|
|
14959
14971
|
backupCodec: true
|
14960
14972
|
};
|
14961
14973
|
const audioDefaults = {
|
14962
|
-
deviceId:
|
14974
|
+
deviceId: {
|
14975
|
+
ideal: 'default'
|
14976
|
+
},
|
14963
14977
|
autoGainControl: true,
|
14964
14978
|
echoCancellation: true,
|
14965
14979
|
noiseSuppression: true,
|
14966
14980
|
voiceIsolation: true
|
14967
14981
|
};
|
14968
14982
|
const videoDefaults = {
|
14969
|
-
deviceId:
|
14983
|
+
deviceId: {
|
14984
|
+
ideal: 'default'
|
14985
|
+
},
|
14970
14986
|
resolution: VideoPresets.h720.resolution
|
14971
14987
|
};
|
14972
14988
|
const roomOptionDefaults = {
|
@@ -17360,6 +17376,10 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17360
17376
|
this.negotiate();
|
17361
17377
|
}
|
17362
17378
|
this.clientConfiguration = joinResponse.clientConfiguration;
|
17379
|
+
// emit signal connected event after a short delay to allow for join response to be processed on room
|
17380
|
+
setTimeout(() => {
|
17381
|
+
this.emit(EngineEvent.SignalConnected);
|
17382
|
+
}, 10);
|
17363
17383
|
return joinResponse;
|
17364
17384
|
} catch (e) {
|
17365
17385
|
if (e instanceof ConnectionError) {
|
@@ -18553,6 +18573,7 @@ class BaseStreamWriter {
|
|
18553
18573
|
}
|
18554
18574
|
}
|
18555
18575
|
class TextStreamWriter extends BaseStreamWriter {}
|
18576
|
+
class ByteStreamWriter extends BaseStreamWriter {}
|
18556
18577
|
|
18557
18578
|
class RemoteTrack extends Track {
|
18558
18579
|
constructor(mediaTrack, sid, kind, receiver, loggerOptions) {
|
@@ -19413,6 +19434,176 @@ class LocalTrackPublication extends TrackPublication {
|
|
19413
19434
|
}
|
19414
19435
|
}
|
19415
19436
|
|
19437
|
+
/**
|
19438
|
+
* Creates a local video and audio track at the same time. When acquiring both
|
19439
|
+
* audio and video tracks together, it'll display a single permission prompt to
|
19440
|
+
* the user instead of two separate ones.
|
19441
|
+
* @param options
|
19442
|
+
*/
|
19443
|
+
function createLocalTracks(options, loggerOptions) {
|
19444
|
+
return __awaiter(this, void 0, void 0, function* () {
|
19445
|
+
// set default options to true
|
19446
|
+
const internalOptions = Object.assign({}, options !== null && options !== void 0 ? options : {});
|
19447
|
+
let attemptExactMatch = false;
|
19448
|
+
let retryAudioOptions = options === null || options === void 0 ? void 0 : options.audio;
|
19449
|
+
let retryVideoOptions = options === null || options === void 0 ? void 0 : options.video;
|
19450
|
+
// if the user passes a device id as a string, we default to exact match
|
19451
|
+
if (internalOptions.audio && typeof internalOptions.audio === 'object' && typeof internalOptions.audio.deviceId === 'string') {
|
19452
|
+
const deviceId = internalOptions.audio.deviceId;
|
19453
|
+
internalOptions.audio.deviceId = {
|
19454
|
+
exact: deviceId
|
19455
|
+
};
|
19456
|
+
attemptExactMatch = true;
|
19457
|
+
retryAudioOptions = Object.assign(Object.assign({}, internalOptions.audio), {
|
19458
|
+
deviceId: {
|
19459
|
+
ideal: deviceId
|
19460
|
+
}
|
19461
|
+
});
|
19462
|
+
}
|
19463
|
+
if (internalOptions.video && typeof internalOptions.video === 'object' && typeof internalOptions.video.deviceId === 'string') {
|
19464
|
+
const deviceId = internalOptions.video.deviceId;
|
19465
|
+
internalOptions.video.deviceId = {
|
19466
|
+
exact: deviceId
|
19467
|
+
};
|
19468
|
+
attemptExactMatch = true;
|
19469
|
+
retryVideoOptions = Object.assign(Object.assign({}, internalOptions.video), {
|
19470
|
+
deviceId: {
|
19471
|
+
ideal: deviceId
|
19472
|
+
}
|
19473
|
+
});
|
19474
|
+
}
|
19475
|
+
// TODO if internal options don't have device Id specified, set it to 'default'
|
19476
|
+
if (internalOptions.audio === true || typeof internalOptions.audio === 'object' && !internalOptions.audio.deviceId) {
|
19477
|
+
internalOptions.audio = {
|
19478
|
+
deviceId: 'default'
|
19479
|
+
};
|
19480
|
+
}
|
19481
|
+
if (internalOptions.video === true || typeof internalOptions.video === 'object' && !internalOptions.video.deviceId) {
|
19482
|
+
internalOptions.video = {
|
19483
|
+
deviceId: 'default'
|
19484
|
+
};
|
19485
|
+
}
|
19486
|
+
const {
|
19487
|
+
audioProcessor,
|
19488
|
+
videoProcessor
|
19489
|
+
} = extractProcessorsFromOptions(internalOptions);
|
19490
|
+
const opts = mergeDefaultOptions(internalOptions, audioDefaults, videoDefaults);
|
19491
|
+
const constraints = constraintsForOptions(opts);
|
19492
|
+
// Keep a reference to the promise on DeviceManager and await it in getLocalDevices()
|
19493
|
+
// works around iOS Safari Bug https://bugs.webkit.org/show_bug.cgi?id=179363
|
19494
|
+
const mediaPromise = navigator.mediaDevices.getUserMedia(constraints);
|
19495
|
+
if (internalOptions.audio) {
|
19496
|
+
DeviceManager.userMediaPromiseMap.set('audioinput', mediaPromise);
|
19497
|
+
mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('audioinput'));
|
19498
|
+
}
|
19499
|
+
if (internalOptions.video) {
|
19500
|
+
DeviceManager.userMediaPromiseMap.set('videoinput', mediaPromise);
|
19501
|
+
mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('videoinput'));
|
19502
|
+
}
|
19503
|
+
try {
|
19504
|
+
const stream = yield mediaPromise;
|
19505
|
+
return yield Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
|
19506
|
+
const isAudio = mediaStreamTrack.kind === 'audio';
|
19507
|
+
let trackOptions = isAudio ? opts.audio : opts.video;
|
19508
|
+
if (typeof trackOptions === 'boolean' || !trackOptions) {
|
19509
|
+
trackOptions = {};
|
19510
|
+
}
|
19511
|
+
let trackConstraints;
|
19512
|
+
const conOrBool = isAudio ? constraints.audio : constraints.video;
|
19513
|
+
if (typeof conOrBool !== 'boolean') {
|
19514
|
+
trackConstraints = conOrBool;
|
19515
|
+
}
|
19516
|
+
// update the constraints with the device id the user gave permissions to in the permission prompt
|
19517
|
+
// otherwise each track restart (e.g. mute - unmute) will try to initialize the device again -> causing additional permission prompts
|
19518
|
+
const newDeviceId = mediaStreamTrack.getSettings().deviceId;
|
19519
|
+
if ((trackConstraints === null || trackConstraints === void 0 ? void 0 : trackConstraints.deviceId) && unwrapConstraint(trackConstraints.deviceId) !== newDeviceId) {
|
19520
|
+
trackConstraints.deviceId = newDeviceId;
|
19521
|
+
} else if (!trackConstraints) {
|
19522
|
+
trackConstraints = {
|
19523
|
+
deviceId: newDeviceId
|
19524
|
+
};
|
19525
|
+
}
|
19526
|
+
const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints, loggerOptions);
|
19527
|
+
if (track.kind === Track.Kind.Video) {
|
19528
|
+
track.source = Track.Source.Camera;
|
19529
|
+
} else if (track.kind === Track.Kind.Audio) {
|
19530
|
+
track.source = Track.Source.Microphone;
|
19531
|
+
}
|
19532
|
+
track.mediaStream = stream;
|
19533
|
+
if (isAudioTrack(track) && audioProcessor) {
|
19534
|
+
yield track.setProcessor(audioProcessor);
|
19535
|
+
} else if (isVideoTrack(track) && videoProcessor) {
|
19536
|
+
yield track.setProcessor(videoProcessor);
|
19537
|
+
}
|
19538
|
+
return track;
|
19539
|
+
})));
|
19540
|
+
} catch (e) {
|
19541
|
+
if (!attemptExactMatch) {
|
19542
|
+
throw e;
|
19543
|
+
}
|
19544
|
+
return createLocalTracks(Object.assign(Object.assign({}, options), {
|
19545
|
+
audio: retryAudioOptions,
|
19546
|
+
video: retryVideoOptions
|
19547
|
+
}), loggerOptions);
|
19548
|
+
}
|
19549
|
+
});
|
19550
|
+
}
|
19551
|
+
/**
|
19552
|
+
* Creates a [[LocalVideoTrack]] with getUserMedia()
|
19553
|
+
* @param options
|
19554
|
+
*/
|
19555
|
+
function createLocalVideoTrack(options) {
|
19556
|
+
return __awaiter(this, void 0, void 0, function* () {
|
19557
|
+
const tracks = yield createLocalTracks({
|
19558
|
+
audio: false,
|
19559
|
+
video: options
|
19560
|
+
});
|
19561
|
+
return tracks[0];
|
19562
|
+
});
|
19563
|
+
}
|
19564
|
+
function createLocalAudioTrack(options) {
|
19565
|
+
return __awaiter(this, void 0, void 0, function* () {
|
19566
|
+
const tracks = yield createLocalTracks({
|
19567
|
+
audio: options,
|
19568
|
+
video: false
|
19569
|
+
});
|
19570
|
+
return tracks[0];
|
19571
|
+
});
|
19572
|
+
}
|
19573
|
+
/**
|
19574
|
+
* Creates a screen capture tracks with getDisplayMedia().
|
19575
|
+
* A LocalVideoTrack is always created and returned.
|
19576
|
+
* If { audio: true }, and the browser supports audio capture, a LocalAudioTrack is also created.
|
19577
|
+
*/
|
19578
|
+
function createLocalScreenTracks(options) {
|
19579
|
+
return __awaiter(this, void 0, void 0, function* () {
|
19580
|
+
if (options === undefined) {
|
19581
|
+
options = {};
|
19582
|
+
}
|
19583
|
+
if (options.resolution === undefined && !isSafari17()) {
|
19584
|
+
options.resolution = ScreenSharePresets.h1080fps30.resolution;
|
19585
|
+
}
|
19586
|
+
if (navigator.mediaDevices.getDisplayMedia === undefined) {
|
19587
|
+
throw new DeviceUnsupportedError('getDisplayMedia not supported');
|
19588
|
+
}
|
19589
|
+
const constraints = screenCaptureToDisplayMediaStreamOptions(options);
|
19590
|
+
const stream = yield navigator.mediaDevices.getDisplayMedia(constraints);
|
19591
|
+
const tracks = stream.getVideoTracks();
|
19592
|
+
if (tracks.length === 0) {
|
19593
|
+
throw new TrackInvalidError('no video track found');
|
19594
|
+
}
|
19595
|
+
const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
|
19596
|
+
screenVideo.source = Track.Source.ScreenShare;
|
19597
|
+
const localTracks = [screenVideo];
|
19598
|
+
if (stream.getAudioTracks().length > 0) {
|
19599
|
+
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
|
19600
|
+
screenAudio.source = Track.Source.ScreenShareAudio;
|
19601
|
+
localTracks.push(screenAudio);
|
19602
|
+
}
|
19603
|
+
return localTracks;
|
19604
|
+
});
|
19605
|
+
}
|
19606
|
+
|
19416
19607
|
var ConnectionQuality;
|
19417
19608
|
(function (ConnectionQuality) {
|
19418
19609
|
ConnectionQuality["Excellent"] = "excellent";
|
@@ -20182,58 +20373,36 @@ class LocalParticipant extends Participant {
|
|
20182
20373
|
var _a, _b;
|
20183
20374
|
options !== null && options !== void 0 ? options : options = {};
|
20184
20375
|
const mergedOptionsWithProcessors = mergeDefaultOptions(options, (_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.audioCaptureDefaults, (_b = this.roomOptions) === null || _b === void 0 ? void 0 : _b.videoCaptureDefaults);
|
20185
|
-
const {
|
20186
|
-
audioProcessor,
|
20187
|
-
videoProcessor,
|
20188
|
-
optionsWithoutProcessor
|
20189
|
-
} = extractProcessorsFromOptions(mergedOptionsWithProcessors);
|
20190
|
-
const constraints = constraintsForOptions(optionsWithoutProcessor);
|
20191
|
-
let stream;
|
20192
20376
|
try {
|
20193
|
-
|
20377
|
+
const tracks = yield createLocalTracks(mergedOptionsWithProcessors, {
|
20378
|
+
loggerName: this.roomOptions.loggerName,
|
20379
|
+
loggerContextCb: () => this.logContext
|
20380
|
+
});
|
20381
|
+
const localTracks = tracks.map(track => {
|
20382
|
+
if (isAudioTrack(track)) {
|
20383
|
+
this.microphoneError = undefined;
|
20384
|
+
track.setAudioContext(this.audioContext);
|
20385
|
+
track.source = Track.Source.Microphone;
|
20386
|
+
this.emit(ParticipantEvent.AudioStreamAcquired);
|
20387
|
+
}
|
20388
|
+
if (isVideoTrack(track)) {
|
20389
|
+
this.cameraError = undefined;
|
20390
|
+
track.source = Track.Source.Camera;
|
20391
|
+
}
|
20392
|
+
return track;
|
20393
|
+
});
|
20394
|
+
return localTracks;
|
20194
20395
|
} catch (err) {
|
20195
20396
|
if (err instanceof Error) {
|
20196
|
-
if (
|
20397
|
+
if (options.audio) {
|
20197
20398
|
this.microphoneError = err;
|
20198
20399
|
}
|
20199
|
-
if (
|
20400
|
+
if (options.video) {
|
20200
20401
|
this.cameraError = err;
|
20201
20402
|
}
|
20202
20403
|
}
|
20203
20404
|
throw err;
|
20204
20405
|
}
|
20205
|
-
if (constraints.audio) {
|
20206
|
-
this.microphoneError = undefined;
|
20207
|
-
this.emit(ParticipantEvent.AudioStreamAcquired);
|
20208
|
-
}
|
20209
|
-
if (constraints.video) {
|
20210
|
-
this.cameraError = undefined;
|
20211
|
-
}
|
20212
|
-
return Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
|
20213
|
-
const isAudio = mediaStreamTrack.kind === 'audio';
|
20214
|
-
let trackConstraints;
|
20215
|
-
const conOrBool = isAudio ? constraints.audio : constraints.video;
|
20216
|
-
if (typeof conOrBool !== 'boolean') {
|
20217
|
-
trackConstraints = conOrBool;
|
20218
|
-
}
|
20219
|
-
const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints, {
|
20220
|
-
loggerName: this.roomOptions.loggerName,
|
20221
|
-
loggerContextCb: () => this.logContext
|
20222
|
-
});
|
20223
|
-
if (track.kind === Track.Kind.Video) {
|
20224
|
-
track.source = Track.Source.Camera;
|
20225
|
-
} else if (track.kind === Track.Kind.Audio) {
|
20226
|
-
track.source = Track.Source.Microphone;
|
20227
|
-
track.setAudioContext(this.audioContext);
|
20228
|
-
}
|
20229
|
-
track.mediaStream = stream;
|
20230
|
-
if (isAudioTrack(track) && audioProcessor) {
|
20231
|
-
yield track.setProcessor(audioProcessor);
|
20232
|
-
} else if (isVideoTrack(track) && videoProcessor) {
|
20233
|
-
yield track.setProcessor(videoProcessor);
|
20234
|
-
}
|
20235
|
-
return track;
|
20236
|
-
})));
|
20237
20406
|
});
|
20238
20407
|
}
|
20239
20408
|
/**
|
@@ -20393,7 +20562,41 @@ class LocalParticipant extends Participant {
|
|
20393
20562
|
if (opts.source) {
|
20394
20563
|
track.source = opts.source;
|
20395
20564
|
}
|
20396
|
-
const publishPromise =
|
20565
|
+
const publishPromise = new Promise((resolve, reject) => __awaiter(_this2, void 0, void 0, function* () {
|
20566
|
+
try {
|
20567
|
+
if (this.engine.client.currentState !== SignalConnectionState.CONNECTED) {
|
20568
|
+
this.log.debug('deferring track publication until signal is connected', Object.assign(Object.assign({}, this.logContext), {
|
20569
|
+
track: getLogContextFromTrack(track)
|
20570
|
+
}));
|
20571
|
+
const onSignalConnected = () => __awaiter(this, void 0, void 0, function* () {
|
20572
|
+
try {
|
20573
|
+
const publication = yield this.publish(track, opts, isStereo);
|
20574
|
+
resolve(publication);
|
20575
|
+
} catch (e) {
|
20576
|
+
reject(e);
|
20577
|
+
}
|
20578
|
+
});
|
20579
|
+
setTimeout(() => {
|
20580
|
+
this.engine.off(EngineEvent.SignalConnected, onSignalConnected);
|
20581
|
+
reject(new PublishTrackError('publishing rejected as engine not connected within timeout', 408));
|
20582
|
+
}, 15000);
|
20583
|
+
this.engine.once(EngineEvent.SignalConnected, onSignalConnected);
|
20584
|
+
this.engine.on(EngineEvent.Closing, () => {
|
20585
|
+
this.engine.off(EngineEvent.SignalConnected, onSignalConnected);
|
20586
|
+
reject(new PublishTrackError('publishing rejected as engine closed', 499));
|
20587
|
+
});
|
20588
|
+
} else {
|
20589
|
+
try {
|
20590
|
+
const publication = yield this.publish(track, opts, isStereo);
|
20591
|
+
resolve(publication);
|
20592
|
+
} catch (e) {
|
20593
|
+
reject(e);
|
20594
|
+
}
|
20595
|
+
}
|
20596
|
+
} catch (e) {
|
20597
|
+
reject(e);
|
20598
|
+
}
|
20599
|
+
}));
|
20397
20600
|
_this2.pendingPublishPromises.set(track, publishPromise);
|
20398
20601
|
try {
|
20399
20602
|
const publication = yield publishPromise;
|
@@ -21090,23 +21293,57 @@ class LocalParticipant extends Participant {
|
|
21090
21293
|
}
|
21091
21294
|
_sendFile(streamId, file, options) {
|
21092
21295
|
return __awaiter(this, void 0, void 0, function* () {
|
21093
|
-
var _a
|
21094
|
-
const
|
21095
|
-
const header = new DataStream_Header({
|
21096
|
-
totalLength: numberToBigInt(totalLength),
|
21097
|
-
mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
|
21296
|
+
var _a;
|
21297
|
+
const writer = yield this.streamBytes({
|
21098
21298
|
streamId,
|
21299
|
+
totalSize: file.size,
|
21300
|
+
name: file.name,
|
21301
|
+
mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
|
21099
21302
|
topic: options === null || options === void 0 ? void 0 : options.topic,
|
21100
|
-
|
21303
|
+
destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities
|
21304
|
+
});
|
21305
|
+
const reader = file.stream().getReader();
|
21306
|
+
while (true) {
|
21307
|
+
const {
|
21308
|
+
done,
|
21309
|
+
value
|
21310
|
+
} = yield reader.read();
|
21311
|
+
if (done) {
|
21312
|
+
break;
|
21313
|
+
}
|
21314
|
+
yield writer.write(value);
|
21315
|
+
}
|
21316
|
+
yield writer.close();
|
21317
|
+
return writer.info;
|
21318
|
+
});
|
21319
|
+
}
|
21320
|
+
streamBytes(options) {
|
21321
|
+
return __awaiter(this, void 0, void 0, function* () {
|
21322
|
+
var _a, _b, _c, _d, _e;
|
21323
|
+
const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
|
21324
|
+
const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
|
21325
|
+
const info = {
|
21326
|
+
id: streamId,
|
21327
|
+
mimeType: (_b = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _b !== void 0 ? _b : 'application/octet-stream',
|
21328
|
+
topic: (_c = options === null || options === void 0 ? void 0 : options.topic) !== null && _c !== void 0 ? _c : '',
|
21329
|
+
timestamp: Date.now(),
|
21330
|
+
attributes: options === null || options === void 0 ? void 0 : options.attributes,
|
21331
|
+
size: options === null || options === void 0 ? void 0 : options.totalSize,
|
21332
|
+
name: (_d = options === null || options === void 0 ? void 0 : options.name) !== null && _d !== void 0 ? _d : 'unknown'
|
21333
|
+
};
|
21334
|
+
const header = new DataStream_Header({
|
21335
|
+
totalLength: numberToBigInt((_e = info.size) !== null && _e !== void 0 ? _e : 0),
|
21336
|
+
mimeType: info.mimeType,
|
21337
|
+
streamId,
|
21338
|
+
topic: info.topic,
|
21101
21339
|
timestamp: numberToBigInt(Date.now()),
|
21102
21340
|
contentHeader: {
|
21103
21341
|
case: 'byteHeader',
|
21104
21342
|
value: new DataStream_ByteHeader({
|
21105
|
-
name:
|
21343
|
+
name: info.name
|
21106
21344
|
})
|
21107
21345
|
}
|
21108
21346
|
});
|
21109
|
-
const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
|
21110
21347
|
const packet = new DataPacket({
|
21111
21348
|
destinationIdentities,
|
21112
21349
|
value: {
|
@@ -21115,45 +21352,60 @@ class LocalParticipant extends Participant {
|
|
21115
21352
|
}
|
21116
21353
|
});
|
21117
21354
|
yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
|
21118
|
-
|
21119
|
-
|
21120
|
-
|
21121
|
-
|
21122
|
-
|
21123
|
-
|
21124
|
-
|
21125
|
-
|
21126
|
-
|
21127
|
-
|
21128
|
-
|
21129
|
-
|
21130
|
-
|
21131
|
-
|
21132
|
-
|
21133
|
-
|
21134
|
-
|
21135
|
-
|
21136
|
-
|
21137
|
-
|
21138
|
-
|
21139
|
-
|
21140
|
-
|
21141
|
-
|
21142
|
-
|
21143
|
-
|
21144
|
-
|
21145
|
-
|
21146
|
-
|
21147
|
-
|
21148
|
-
|
21149
|
-
|
21150
|
-
|
21151
|
-
|
21152
|
-
|
21153
|
-
|
21355
|
+
let chunkId = 0;
|
21356
|
+
const writeMutex = new _();
|
21357
|
+
const engine = this.engine;
|
21358
|
+
const log = this.log;
|
21359
|
+
const writableStream = new WritableStream({
|
21360
|
+
write(chunk) {
|
21361
|
+
return __awaiter(this, void 0, void 0, function* () {
|
21362
|
+
const unlock = yield writeMutex.lock();
|
21363
|
+
let byteOffset = 0;
|
21364
|
+
try {
|
21365
|
+
while (byteOffset < chunk.byteLength) {
|
21366
|
+
const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);
|
21367
|
+
yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
|
21368
|
+
const chunkPacket = new DataPacket({
|
21369
|
+
destinationIdentities,
|
21370
|
+
value: {
|
21371
|
+
case: 'streamChunk',
|
21372
|
+
value: new DataStream_Chunk({
|
21373
|
+
content: subChunk,
|
21374
|
+
streamId,
|
21375
|
+
chunkIndex: numberToBigInt(chunkId)
|
21376
|
+
})
|
21377
|
+
}
|
21378
|
+
});
|
21379
|
+
yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
|
21380
|
+
chunkId += 1;
|
21381
|
+
byteOffset += subChunk.byteLength;
|
21382
|
+
}
|
21383
|
+
} finally {
|
21384
|
+
unlock();
|
21385
|
+
}
|
21386
|
+
});
|
21387
|
+
},
|
21388
|
+
close() {
|
21389
|
+
return __awaiter(this, void 0, void 0, function* () {
|
21390
|
+
const trailer = new DataStream_Trailer({
|
21391
|
+
streamId
|
21392
|
+
});
|
21393
|
+
const trailerPacket = new DataPacket({
|
21394
|
+
destinationIdentities,
|
21395
|
+
value: {
|
21396
|
+
case: 'streamTrailer',
|
21397
|
+
value: trailer
|
21398
|
+
}
|
21399
|
+
});
|
21400
|
+
yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
|
21401
|
+
});
|
21402
|
+
},
|
21403
|
+
abort(err) {
|
21404
|
+
log.error('Sink error:', err);
|
21154
21405
|
}
|
21155
21406
|
});
|
21156
|
-
|
21407
|
+
const byteWriter = new ByteStreamWriter(writableStream, info);
|
21408
|
+
return byteWriter;
|
21157
21409
|
});
|
21158
21410
|
}
|
21159
21411
|
/**
|
@@ -23169,7 +23421,7 @@ class Room extends eventsExports.EventEmitter {
|
|
23169
23421
|
switchActiveDevice(kind_1, deviceId_1) {
|
23170
23422
|
return __awaiter(this, arguments, void 0, function (kind, deviceId) {
|
23171
23423
|
var _this3 = this;
|
23172
|
-
let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] :
|
23424
|
+
let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
23173
23425
|
return function* () {
|
23174
23426
|
var _a, _b, _c, _d, _e, _f, _g;
|
23175
23427
|
var _h;
|
@@ -24162,131 +24414,6 @@ class ConnectionProtocolCheck extends Checker {
|
|
24162
24414
|
}
|
24163
24415
|
}
|
24164
24416
|
|
24165
|
-
/**
|
24166
|
-
* Creates a local video and audio track at the same time. When acquiring both
|
24167
|
-
* audio and video tracks together, it'll display a single permission prompt to
|
24168
|
-
* the user instead of two separate ones.
|
24169
|
-
* @param options
|
24170
|
-
*/
|
24171
|
-
function createLocalTracks(options) {
|
24172
|
-
return __awaiter(this, void 0, void 0, function* () {
|
24173
|
-
var _a, _b;
|
24174
|
-
// set default options to true
|
24175
|
-
options !== null && options !== void 0 ? options : options = {};
|
24176
|
-
(_a = options.audio) !== null && _a !== void 0 ? _a : options.audio = {
|
24177
|
-
deviceId: 'default'
|
24178
|
-
};
|
24179
|
-
(_b = options.video) !== null && _b !== void 0 ? _b : options.video = {
|
24180
|
-
deviceId: 'default'
|
24181
|
-
};
|
24182
|
-
const {
|
24183
|
-
audioProcessor,
|
24184
|
-
videoProcessor
|
24185
|
-
} = extractProcessorsFromOptions(options);
|
24186
|
-
const opts = mergeDefaultOptions(options, audioDefaults, videoDefaults);
|
24187
|
-
const constraints = constraintsForOptions(opts);
|
24188
|
-
// Keep a reference to the promise on DeviceManager and await it in getLocalDevices()
|
24189
|
-
// works around iOS Safari Bug https://bugs.webkit.org/show_bug.cgi?id=179363
|
24190
|
-
const mediaPromise = navigator.mediaDevices.getUserMedia(constraints);
|
24191
|
-
if (options.audio) {
|
24192
|
-
DeviceManager.userMediaPromiseMap.set('audioinput', mediaPromise);
|
24193
|
-
mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('audioinput'));
|
24194
|
-
}
|
24195
|
-
if (options.video) {
|
24196
|
-
DeviceManager.userMediaPromiseMap.set('videoinput', mediaPromise);
|
24197
|
-
mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('videoinput'));
|
24198
|
-
}
|
24199
|
-
const stream = yield mediaPromise;
|
24200
|
-
return Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
|
24201
|
-
const isAudio = mediaStreamTrack.kind === 'audio';
|
24202
|
-
isAudio ? opts.audio : opts.video;
|
24203
|
-
let trackConstraints;
|
24204
|
-
const conOrBool = isAudio ? constraints.audio : constraints.video;
|
24205
|
-
if (typeof conOrBool !== 'boolean') {
|
24206
|
-
trackConstraints = conOrBool;
|
24207
|
-
}
|
24208
|
-
// update the constraints with the device id the user gave permissions to in the permission prompt
|
24209
|
-
// otherwise each track restart (e.g. mute - unmute) will try to initialize the device again -> causing additional permission prompts
|
24210
|
-
const newDeviceId = mediaStreamTrack.getSettings().deviceId;
|
24211
|
-
if ((trackConstraints === null || trackConstraints === void 0 ? void 0 : trackConstraints.deviceId) && unwrapConstraint(trackConstraints.deviceId) !== newDeviceId) {
|
24212
|
-
trackConstraints.deviceId = newDeviceId;
|
24213
|
-
} else if (!trackConstraints) {
|
24214
|
-
trackConstraints = {
|
24215
|
-
deviceId: newDeviceId
|
24216
|
-
};
|
24217
|
-
}
|
24218
|
-
const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints);
|
24219
|
-
if (track.kind === Track.Kind.Video) {
|
24220
|
-
track.source = Track.Source.Camera;
|
24221
|
-
} else if (track.kind === Track.Kind.Audio) {
|
24222
|
-
track.source = Track.Source.Microphone;
|
24223
|
-
}
|
24224
|
-
track.mediaStream = stream;
|
24225
|
-
if (isAudioTrack(track) && audioProcessor) {
|
24226
|
-
yield track.setProcessor(audioProcessor);
|
24227
|
-
} else if (isVideoTrack(track) && videoProcessor) {
|
24228
|
-
yield track.setProcessor(videoProcessor);
|
24229
|
-
}
|
24230
|
-
return track;
|
24231
|
-
})));
|
24232
|
-
});
|
24233
|
-
}
|
24234
|
-
/**
|
24235
|
-
* Creates a [[LocalVideoTrack]] with getUserMedia()
|
24236
|
-
* @param options
|
24237
|
-
*/
|
24238
|
-
function createLocalVideoTrack(options) {
|
24239
|
-
return __awaiter(this, void 0, void 0, function* () {
|
24240
|
-
const tracks = yield createLocalTracks({
|
24241
|
-
audio: false,
|
24242
|
-
video: options
|
24243
|
-
});
|
24244
|
-
return tracks[0];
|
24245
|
-
});
|
24246
|
-
}
|
24247
|
-
function createLocalAudioTrack(options) {
|
24248
|
-
return __awaiter(this, void 0, void 0, function* () {
|
24249
|
-
const tracks = yield createLocalTracks({
|
24250
|
-
audio: options,
|
24251
|
-
video: false
|
24252
|
-
});
|
24253
|
-
return tracks[0];
|
24254
|
-
});
|
24255
|
-
}
|
24256
|
-
/**
|
24257
|
-
* Creates a screen capture tracks with getDisplayMedia().
|
24258
|
-
* A LocalVideoTrack is always created and returned.
|
24259
|
-
* If { audio: true }, and the browser supports audio capture, a LocalAudioTrack is also created.
|
24260
|
-
*/
|
24261
|
-
function createLocalScreenTracks(options) {
|
24262
|
-
return __awaiter(this, void 0, void 0, function* () {
|
24263
|
-
if (options === undefined) {
|
24264
|
-
options = {};
|
24265
|
-
}
|
24266
|
-
if (options.resolution === undefined && !isSafari17()) {
|
24267
|
-
options.resolution = ScreenSharePresets.h1080fps30.resolution;
|
24268
|
-
}
|
24269
|
-
if (navigator.mediaDevices.getDisplayMedia === undefined) {
|
24270
|
-
throw new DeviceUnsupportedError('getDisplayMedia not supported');
|
24271
|
-
}
|
24272
|
-
const constraints = screenCaptureToDisplayMediaStreamOptions(options);
|
24273
|
-
const stream = yield navigator.mediaDevices.getDisplayMedia(constraints);
|
24274
|
-
const tracks = stream.getVideoTracks();
|
24275
|
-
if (tracks.length === 0) {
|
24276
|
-
throw new TrackInvalidError('no video track found');
|
24277
|
-
}
|
24278
|
-
const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
|
24279
|
-
screenVideo.source = Track.Source.ScreenShare;
|
24280
|
-
const localTracks = [screenVideo];
|
24281
|
-
if (stream.getAudioTracks().length > 0) {
|
24282
|
-
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
|
24283
|
-
screenAudio.source = Track.Source.ScreenShareAudio;
|
24284
|
-
localTracks.push(screenAudio);
|
24285
|
-
}
|
24286
|
-
return localTracks;
|
24287
|
-
});
|
24288
|
-
}
|
24289
|
-
|
24290
24417
|
class PublishAudioCheck extends Checker {
|
24291
24418
|
get description() {
|
24292
24419
|
return 'Can publish audio';
|