livekit-client 1.2.1 → 1.2.4
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 +974 -109
- 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/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/options.d.ts +5 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/DefaultReconnectPolicy.d.ts +8 -0
- package/dist/src/room/DefaultReconnectPolicy.d.ts.map +1 -0
- package/dist/src/room/PCTransport.d.ts +1 -0
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +6 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/ReconnectPolicy.d.ts +23 -0
- package/dist/src/room/ReconnectPolicy.d.ts.map +1 -0
- package/dist/src/room/Room.d.ts +8 -0
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +2 -2
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/index.ts +2 -0
- package/src/options.ts +6 -0
- package/src/room/DefaultReconnectPolicy.ts +35 -0
- package/src/room/PCTransport.ts +91 -17
- package/src/room/RTCEngine.ts +79 -31
- package/src/room/ReconnectPolicy.ts +25 -0
- package/src/room/Room.ts +55 -30
- package/src/room/events.ts +2 -2
- package/src/room/participant/LocalParticipant.ts +30 -16
- package/src/room/participant/RemoteParticipant.ts +14 -0
- package/src/room/track/LocalVideoTrack.ts +0 -1
@@ -2997,7 +2997,7 @@ LongBits$2.prototype.length = function length() {
|
|
2997
2997
|
};
|
2998
2998
|
})(minimal$1);
|
2999
2999
|
|
3000
|
-
var writer = Writer$1;
|
3000
|
+
var writer$2 = Writer$1;
|
3001
3001
|
var util$4 = minimal$1;
|
3002
3002
|
var BufferWriter$1; // cyclic
|
3003
3003
|
|
@@ -3476,7 +3476,7 @@ Writer$1._configure = function (BufferWriter_) {
|
|
3476
3476
|
|
3477
3477
|
var writer_buffer = BufferWriter; // extends Writer
|
3478
3478
|
|
3479
|
-
var Writer = writer;
|
3479
|
+
var Writer = writer$2;
|
3480
3480
|
(BufferWriter.prototype = Object.create(Writer.prototype)).constructor = BufferWriter;
|
3481
3481
|
var util$3 = minimal$1;
|
3482
3482
|
/**
|
@@ -4193,7 +4193,7 @@ var roots = {};
|
|
4193
4193
|
|
4194
4194
|
protobuf.build = "minimal"; // Serialization
|
4195
4195
|
|
4196
|
-
protobuf.Writer = writer;
|
4196
|
+
protobuf.Writer = writer$2;
|
4197
4197
|
protobuf.BufferWriter = writer_buffer;
|
4198
4198
|
protobuf.Reader = reader;
|
4199
4199
|
protobuf.BufferReader = reader_buffer; // Utility
|
@@ -9997,8 +9997,8 @@ var RoomEvent;
|
|
9997
9997
|
* When we have encountered an error while attempting to create a track.
|
9998
9998
|
* The errors take place in getUserMedia().
|
9999
9999
|
* Use MediaDeviceFailure.getFailure(error) to get the reason of failure.
|
10000
|
-
* [[
|
10001
|
-
* an error while creating the audio or video track respectively.
|
10000
|
+
* [[LocalParticipant.lastCameraError]] and [[LocalParticipant.lastMicrophoneError]]
|
10001
|
+
* will indicate if it had an error while creating the audio or video track respectively.
|
10002
10002
|
*
|
10003
10003
|
* args: (error: Error)
|
10004
10004
|
*/
|
@@ -10265,7 +10265,7 @@ function computeBitrate(currentStats, prevStats) {
|
|
10265
10265
|
return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
|
10266
10266
|
}
|
10267
10267
|
|
10268
|
-
var version$1 = "1.2.
|
10268
|
+
var version$1 = "1.2.4";
|
10269
10269
|
|
10270
10270
|
const version = version$1;
|
10271
10271
|
const protocolVersion = 8;
|
@@ -12016,8 +12016,6 @@ class LocalVideoTrack extends LocalTrack {
|
|
12016
12016
|
}
|
12017
12017
|
|
12018
12018
|
stop() {
|
12019
|
-
this.sender = undefined;
|
12020
|
-
|
12021
12019
|
this._mediaStreamTrack.getConstraints();
|
12022
12020
|
|
12023
12021
|
this.simulcastCodecs.forEach(trackInfo => {
|
@@ -14043,6 +14041,17 @@ class RemoteParticipant extends Participant {
|
|
14043
14041
|
publication = new RemoteTrackPublication(kind, ti.sid, ti.name);
|
14044
14042
|
publication.updateInfo(ti);
|
14045
14043
|
newTracks.set(ti.sid, publication);
|
14044
|
+
const existingTrackOfSource = Array.from(this.tracks.values()).find(publishedTrack => publishedTrack.source === (publication === null || publication === void 0 ? void 0 : publication.source));
|
14045
|
+
|
14046
|
+
if (existingTrackOfSource) {
|
14047
|
+
livekitLogger.warn("received a second track publication for ".concat(this.identity, " with the same source: ").concat(publication.source), {
|
14048
|
+
oldTrack: existingTrackOfSource,
|
14049
|
+
newTrack: publication,
|
14050
|
+
participant: this,
|
14051
|
+
participantInfo: info
|
14052
|
+
});
|
14053
|
+
}
|
14054
|
+
|
14046
14055
|
this.addTrackPublication(publication);
|
14047
14056
|
} else {
|
14048
14057
|
publication.updateInfo(ti);
|
@@ -14618,6 +14627,23 @@ class LocalParticipant extends Participant {
|
|
14618
14627
|
track.source = opts.source;
|
14619
14628
|
}
|
14620
14629
|
|
14630
|
+
const existingTrackOfSource = Array.from(this.tracks.values()).find(publishedTrack => track instanceof LocalTrack && publishedTrack.source === track.source);
|
14631
|
+
|
14632
|
+
if (existingTrackOfSource) {
|
14633
|
+
try {
|
14634
|
+
// throw an Error in order to capture the stack trace
|
14635
|
+
throw Error("publishing a second track with the same source: ".concat(track.source));
|
14636
|
+
} catch (e) {
|
14637
|
+
if (e instanceof Error) {
|
14638
|
+
livekitLogger.warn(e.message, {
|
14639
|
+
oldTrack: existingTrackOfSource,
|
14640
|
+
newTrack: track,
|
14641
|
+
trace: e.stack
|
14642
|
+
});
|
14643
|
+
}
|
14644
|
+
}
|
14645
|
+
}
|
14646
|
+
|
14621
14647
|
if (opts.stopMicTrackOnMute && track instanceof LocalAudioTrack) {
|
14622
14648
|
track.stopOnMute = true;
|
14623
14649
|
}
|
@@ -14849,7 +14875,6 @@ class LocalParticipant extends Participant {
|
|
14849
14875
|
}
|
14850
14876
|
|
14851
14877
|
track = publication.track;
|
14852
|
-
track.sender = undefined;
|
14853
14878
|
track.off(TrackEvent.Muted, this.onTrackMuted);
|
14854
14879
|
track.off(TrackEvent.Unmuted, this.onTrackUnmuted);
|
14855
14880
|
track.off(TrackEvent.Ended, this.handleTrackEnded);
|
@@ -14864,29 +14889,19 @@ class LocalParticipant extends Participant {
|
|
14864
14889
|
track.stop();
|
14865
14890
|
}
|
14866
14891
|
|
14867
|
-
|
14868
|
-
|
14869
|
-
|
14870
|
-
|
14871
|
-
|
14872
|
-
|
14873
|
-
|
14874
|
-
|
14875
|
-
|
14876
|
-
|
14877
|
-
|
14878
|
-
(_a = this.engine.publisher) === null || _a === void 0 ? void 0 : _a.pc.removeTrack(sender);
|
14879
|
-
this.engine.negotiate();
|
14880
|
-
} catch (e) {
|
14881
|
-
livekitLogger.warn('failed to remove track', {
|
14882
|
-
error: e,
|
14883
|
-
method: 'unpublishTrack'
|
14884
|
-
});
|
14885
|
-
}
|
14886
|
-
}
|
14887
|
-
});
|
14888
|
-
} // remove from our maps
|
14892
|
+
if (this.engine.publisher && this.engine.publisher.pc.connectionState !== 'closed' && track.sender) {
|
14893
|
+
try {
|
14894
|
+
this.engine.publisher.pc.removeTrack(track.sender);
|
14895
|
+
this.engine.negotiate();
|
14896
|
+
} catch (e) {
|
14897
|
+
livekitLogger.warn('failed to remove track', {
|
14898
|
+
error: e,
|
14899
|
+
method: 'unpublishTrack'
|
14900
|
+
});
|
14901
|
+
}
|
14902
|
+
}
|
14889
14903
|
|
14904
|
+
track.sender = undefined; // remove from our maps
|
14890
14905
|
|
14891
14906
|
this.tracks.delete(publication.trackSid);
|
14892
14907
|
|
@@ -19050,6 +19065,710 @@ function createConnectionParams(token, info, opts) {
|
|
19050
19065
|
return "?".concat(params.toString());
|
19051
19066
|
}
|
19052
19067
|
|
19068
|
+
const maxRetryDelay = 7000;
|
19069
|
+
const DEFAULT_RETRY_DELAYS_IN_MS = [0, 300, 2 * 2 * 300, 3 * 3 * 300, 4 * 4 * 300, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay];
|
19070
|
+
|
19071
|
+
class DefaultReconnectPolicy {
|
19072
|
+
constructor(retryDelays) {
|
19073
|
+
this._retryDelays = retryDelays !== undefined ? [...retryDelays] : DEFAULT_RETRY_DELAYS_IN_MS;
|
19074
|
+
}
|
19075
|
+
|
19076
|
+
nextRetryDelayInMs(context) {
|
19077
|
+
if (context.retryCount >= this._retryDelays.length) return null;
|
19078
|
+
const retryDelay = this._retryDelays[context.retryCount];
|
19079
|
+
if (context.retryCount <= 1) return retryDelay;
|
19080
|
+
return retryDelay + Math.random() * 1000;
|
19081
|
+
}
|
19082
|
+
|
19083
|
+
}
|
19084
|
+
|
19085
|
+
var parser$1 = {};
|
19086
|
+
|
19087
|
+
var grammar$2 = {exports: {}};
|
19088
|
+
|
19089
|
+
var grammar$1 = grammar$2.exports = {
|
19090
|
+
v: [{
|
19091
|
+
name: 'version',
|
19092
|
+
reg: /^(\d*)$/
|
19093
|
+
}],
|
19094
|
+
o: [{
|
19095
|
+
// o=- 20518 0 IN IP4 203.0.113.1
|
19096
|
+
// NB: sessionId will be a String in most cases because it is huge
|
19097
|
+
name: 'origin',
|
19098
|
+
reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/,
|
19099
|
+
names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'],
|
19100
|
+
format: '%s %s %d %s IP%d %s'
|
19101
|
+
}],
|
19102
|
+
// default parsing of these only (though some of these feel outdated)
|
19103
|
+
s: [{
|
19104
|
+
name: 'name'
|
19105
|
+
}],
|
19106
|
+
i: [{
|
19107
|
+
name: 'description'
|
19108
|
+
}],
|
19109
|
+
u: [{
|
19110
|
+
name: 'uri'
|
19111
|
+
}],
|
19112
|
+
e: [{
|
19113
|
+
name: 'email'
|
19114
|
+
}],
|
19115
|
+
p: [{
|
19116
|
+
name: 'phone'
|
19117
|
+
}],
|
19118
|
+
z: [{
|
19119
|
+
name: 'timezones'
|
19120
|
+
}],
|
19121
|
+
// TODO: this one can actually be parsed properly...
|
19122
|
+
r: [{
|
19123
|
+
name: 'repeats'
|
19124
|
+
}],
|
19125
|
+
// TODO: this one can also be parsed properly
|
19126
|
+
// k: [{}], // outdated thing ignored
|
19127
|
+
t: [{
|
19128
|
+
// t=0 0
|
19129
|
+
name: 'timing',
|
19130
|
+
reg: /^(\d*) (\d*)/,
|
19131
|
+
names: ['start', 'stop'],
|
19132
|
+
format: '%d %d'
|
19133
|
+
}],
|
19134
|
+
c: [{
|
19135
|
+
// c=IN IP4 10.47.197.26
|
19136
|
+
name: 'connection',
|
19137
|
+
reg: /^IN IP(\d) (\S*)/,
|
19138
|
+
names: ['version', 'ip'],
|
19139
|
+
format: 'IN IP%d %s'
|
19140
|
+
}],
|
19141
|
+
b: [{
|
19142
|
+
// b=AS:4000
|
19143
|
+
push: 'bandwidth',
|
19144
|
+
reg: /^(TIAS|AS|CT|RR|RS):(\d*)/,
|
19145
|
+
names: ['type', 'limit'],
|
19146
|
+
format: '%s:%s'
|
19147
|
+
}],
|
19148
|
+
m: [{
|
19149
|
+
// m=video 51744 RTP/AVP 126 97 98 34 31
|
19150
|
+
// NB: special - pushes to session
|
19151
|
+
// TODO: rtp/fmtp should be filtered by the payloads found here?
|
19152
|
+
reg: /^(\w*) (\d*) ([\w/]*)(?: (.*))?/,
|
19153
|
+
names: ['type', 'port', 'protocol', 'payloads'],
|
19154
|
+
format: '%s %d %s %s'
|
19155
|
+
}],
|
19156
|
+
a: [{
|
19157
|
+
// a=rtpmap:110 opus/48000/2
|
19158
|
+
push: 'rtp',
|
19159
|
+
reg: /^rtpmap:(\d*) ([\w\-.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/,
|
19160
|
+
names: ['payload', 'codec', 'rate', 'encoding'],
|
19161
|
+
format: function (o) {
|
19162
|
+
return o.encoding ? 'rtpmap:%d %s/%s/%s' : o.rate ? 'rtpmap:%d %s/%s' : 'rtpmap:%d %s';
|
19163
|
+
}
|
19164
|
+
}, {
|
19165
|
+
// a=fmtp:108 profile-level-id=24;object=23;bitrate=64000
|
19166
|
+
// a=fmtp:111 minptime=10; useinbandfec=1
|
19167
|
+
push: 'fmtp',
|
19168
|
+
reg: /^fmtp:(\d*) ([\S| ]*)/,
|
19169
|
+
names: ['payload', 'config'],
|
19170
|
+
format: 'fmtp:%d %s'
|
19171
|
+
}, {
|
19172
|
+
// a=control:streamid=0
|
19173
|
+
name: 'control',
|
19174
|
+
reg: /^control:(.*)/,
|
19175
|
+
format: 'control:%s'
|
19176
|
+
}, {
|
19177
|
+
// a=rtcp:65179 IN IP4 193.84.77.194
|
19178
|
+
name: 'rtcp',
|
19179
|
+
reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/,
|
19180
|
+
names: ['port', 'netType', 'ipVer', 'address'],
|
19181
|
+
format: function (o) {
|
19182
|
+
return o.address != null ? 'rtcp:%d %s IP%d %s' : 'rtcp:%d';
|
19183
|
+
}
|
19184
|
+
}, {
|
19185
|
+
// a=rtcp-fb:98 trr-int 100
|
19186
|
+
push: 'rtcpFbTrrInt',
|
19187
|
+
reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/,
|
19188
|
+
names: ['payload', 'value'],
|
19189
|
+
format: 'rtcp-fb:%s trr-int %d'
|
19190
|
+
}, {
|
19191
|
+
// a=rtcp-fb:98 nack rpsi
|
19192
|
+
push: 'rtcpFb',
|
19193
|
+
reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/,
|
19194
|
+
names: ['payload', 'type', 'subtype'],
|
19195
|
+
format: function (o) {
|
19196
|
+
return o.subtype != null ? 'rtcp-fb:%s %s %s' : 'rtcp-fb:%s %s';
|
19197
|
+
}
|
19198
|
+
}, {
|
19199
|
+
// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
|
19200
|
+
// a=extmap:1/recvonly URI-gps-string
|
19201
|
+
// a=extmap:3 urn:ietf:params:rtp-hdrext:encrypt urn:ietf:params:rtp-hdrext:smpte-tc 25@600/24
|
19202
|
+
push: 'ext',
|
19203
|
+
reg: /^extmap:(\d+)(?:\/(\w+))?(?: (urn:ietf:params:rtp-hdrext:encrypt))? (\S*)(?: (\S*))?/,
|
19204
|
+
names: ['value', 'direction', 'encrypt-uri', 'uri', 'config'],
|
19205
|
+
format: function (o) {
|
19206
|
+
return 'extmap:%d' + (o.direction ? '/%s' : '%v') + (o['encrypt-uri'] ? ' %s' : '%v') + ' %s' + (o.config ? ' %s' : '');
|
19207
|
+
}
|
19208
|
+
}, {
|
19209
|
+
// a=extmap-allow-mixed
|
19210
|
+
name: 'extmapAllowMixed',
|
19211
|
+
reg: /^(extmap-allow-mixed)/
|
19212
|
+
}, {
|
19213
|
+
// a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32
|
19214
|
+
push: 'crypto',
|
19215
|
+
reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/,
|
19216
|
+
names: ['id', 'suite', 'config', 'sessionConfig'],
|
19217
|
+
format: function (o) {
|
19218
|
+
return o.sessionConfig != null ? 'crypto:%d %s %s %s' : 'crypto:%d %s %s';
|
19219
|
+
}
|
19220
|
+
}, {
|
19221
|
+
// a=setup:actpass
|
19222
|
+
name: 'setup',
|
19223
|
+
reg: /^setup:(\w*)/,
|
19224
|
+
format: 'setup:%s'
|
19225
|
+
}, {
|
19226
|
+
// a=connection:new
|
19227
|
+
name: 'connectionType',
|
19228
|
+
reg: /^connection:(new|existing)/,
|
19229
|
+
format: 'connection:%s'
|
19230
|
+
}, {
|
19231
|
+
// a=mid:1
|
19232
|
+
name: 'mid',
|
19233
|
+
reg: /^mid:([^\s]*)/,
|
19234
|
+
format: 'mid:%s'
|
19235
|
+
}, {
|
19236
|
+
// a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a
|
19237
|
+
name: 'msid',
|
19238
|
+
reg: /^msid:(.*)/,
|
19239
|
+
format: 'msid:%s'
|
19240
|
+
}, {
|
19241
|
+
// a=ptime:20
|
19242
|
+
name: 'ptime',
|
19243
|
+
reg: /^ptime:(\d*(?:\.\d*)*)/,
|
19244
|
+
format: 'ptime:%d'
|
19245
|
+
}, {
|
19246
|
+
// a=maxptime:60
|
19247
|
+
name: 'maxptime',
|
19248
|
+
reg: /^maxptime:(\d*(?:\.\d*)*)/,
|
19249
|
+
format: 'maxptime:%d'
|
19250
|
+
}, {
|
19251
|
+
// a=sendrecv
|
19252
|
+
name: 'direction',
|
19253
|
+
reg: /^(sendrecv|recvonly|sendonly|inactive)/
|
19254
|
+
}, {
|
19255
|
+
// a=ice-lite
|
19256
|
+
name: 'icelite',
|
19257
|
+
reg: /^(ice-lite)/
|
19258
|
+
}, {
|
19259
|
+
// a=ice-ufrag:F7gI
|
19260
|
+
name: 'iceUfrag',
|
19261
|
+
reg: /^ice-ufrag:(\S*)/,
|
19262
|
+
format: 'ice-ufrag:%s'
|
19263
|
+
}, {
|
19264
|
+
// a=ice-pwd:x9cml/YzichV2+XlhiMu8g
|
19265
|
+
name: 'icePwd',
|
19266
|
+
reg: /^ice-pwd:(\S*)/,
|
19267
|
+
format: 'ice-pwd:%s'
|
19268
|
+
}, {
|
19269
|
+
// a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33
|
19270
|
+
name: 'fingerprint',
|
19271
|
+
reg: /^fingerprint:(\S*) (\S*)/,
|
19272
|
+
names: ['type', 'hash'],
|
19273
|
+
format: 'fingerprint:%s %s'
|
19274
|
+
}, {
|
19275
|
+
// a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
|
19276
|
+
// a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 network-id 3 network-cost 10
|
19277
|
+
// a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10
|
19278
|
+
// a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10
|
19279
|
+
// a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10
|
19280
|
+
push: 'candidates',
|
19281
|
+
reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?(?: network-id (\d*))?(?: network-cost (\d*))?/,
|
19282
|
+
names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'],
|
19283
|
+
format: function (o) {
|
19284
|
+
var str = 'candidate:%s %d %s %d %s %d typ %s';
|
19285
|
+
str += o.raddr != null ? ' raddr %s rport %d' : '%v%v'; // NB: candidate has three optional chunks, so %void middles one if it's missing
|
19286
|
+
|
19287
|
+
str += o.tcptype != null ? ' tcptype %s' : '%v';
|
19288
|
+
|
19289
|
+
if (o.generation != null) {
|
19290
|
+
str += ' generation %d';
|
19291
|
+
}
|
19292
|
+
|
19293
|
+
str += o['network-id'] != null ? ' network-id %d' : '%v';
|
19294
|
+
str += o['network-cost'] != null ? ' network-cost %d' : '%v';
|
19295
|
+
return str;
|
19296
|
+
}
|
19297
|
+
}, {
|
19298
|
+
// a=end-of-candidates (keep after the candidates line for readability)
|
19299
|
+
name: 'endOfCandidates',
|
19300
|
+
reg: /^(end-of-candidates)/
|
19301
|
+
}, {
|
19302
|
+
// a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ...
|
19303
|
+
name: 'remoteCandidates',
|
19304
|
+
reg: /^remote-candidates:(.*)/,
|
19305
|
+
format: 'remote-candidates:%s'
|
19306
|
+
}, {
|
19307
|
+
// a=ice-options:google-ice
|
19308
|
+
name: 'iceOptions',
|
19309
|
+
reg: /^ice-options:(\S*)/,
|
19310
|
+
format: 'ice-options:%s'
|
19311
|
+
}, {
|
19312
|
+
// a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1
|
19313
|
+
push: 'ssrcs',
|
19314
|
+
reg: /^ssrc:(\d*) ([\w_-]*)(?::(.*))?/,
|
19315
|
+
names: ['id', 'attribute', 'value'],
|
19316
|
+
format: function (o) {
|
19317
|
+
var str = 'ssrc:%d';
|
19318
|
+
|
19319
|
+
if (o.attribute != null) {
|
19320
|
+
str += ' %s';
|
19321
|
+
|
19322
|
+
if (o.value != null) {
|
19323
|
+
str += ':%s';
|
19324
|
+
}
|
19325
|
+
}
|
19326
|
+
|
19327
|
+
return str;
|
19328
|
+
}
|
19329
|
+
}, {
|
19330
|
+
// a=ssrc-group:FEC 1 2
|
19331
|
+
// a=ssrc-group:FEC-FR 3004364195 1080772241
|
19332
|
+
push: 'ssrcGroups',
|
19333
|
+
// token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E
|
19334
|
+
reg: /^ssrc-group:([\x21\x23\x24\x25\x26\x27\x2A\x2B\x2D\x2E\w]*) (.*)/,
|
19335
|
+
names: ['semantics', 'ssrcs'],
|
19336
|
+
format: 'ssrc-group:%s %s'
|
19337
|
+
}, {
|
19338
|
+
// a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV
|
19339
|
+
name: 'msidSemantic',
|
19340
|
+
reg: /^msid-semantic:\s?(\w*) (\S*)/,
|
19341
|
+
names: ['semantic', 'token'],
|
19342
|
+
format: 'msid-semantic: %s %s' // space after ':' is not accidental
|
19343
|
+
|
19344
|
+
}, {
|
19345
|
+
// a=group:BUNDLE audio video
|
19346
|
+
push: 'groups',
|
19347
|
+
reg: /^group:(\w*) (.*)/,
|
19348
|
+
names: ['type', 'mids'],
|
19349
|
+
format: 'group:%s %s'
|
19350
|
+
}, {
|
19351
|
+
// a=rtcp-mux
|
19352
|
+
name: 'rtcpMux',
|
19353
|
+
reg: /^(rtcp-mux)/
|
19354
|
+
}, {
|
19355
|
+
// a=rtcp-rsize
|
19356
|
+
name: 'rtcpRsize',
|
19357
|
+
reg: /^(rtcp-rsize)/
|
19358
|
+
}, {
|
19359
|
+
// a=sctpmap:5000 webrtc-datachannel 1024
|
19360
|
+
name: 'sctpmap',
|
19361
|
+
reg: /^sctpmap:([\w_/]*) (\S*)(?: (\S*))?/,
|
19362
|
+
names: ['sctpmapNumber', 'app', 'maxMessageSize'],
|
19363
|
+
format: function (o) {
|
19364
|
+
return o.maxMessageSize != null ? 'sctpmap:%s %s %s' : 'sctpmap:%s %s';
|
19365
|
+
}
|
19366
|
+
}, {
|
19367
|
+
// a=x-google-flag:conference
|
19368
|
+
name: 'xGoogleFlag',
|
19369
|
+
reg: /^x-google-flag:([^\s]*)/,
|
19370
|
+
format: 'x-google-flag:%s'
|
19371
|
+
}, {
|
19372
|
+
// a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0
|
19373
|
+
push: 'rids',
|
19374
|
+
reg: /^rid:([\d\w]+) (\w+)(?: ([\S| ]*))?/,
|
19375
|
+
names: ['id', 'direction', 'params'],
|
19376
|
+
format: function (o) {
|
19377
|
+
return o.params ? 'rid:%s %s %s' : 'rid:%s %s';
|
19378
|
+
}
|
19379
|
+
}, {
|
19380
|
+
// a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250]
|
19381
|
+
// a=imageattr:* send [x=800,y=640] recv *
|
19382
|
+
// a=imageattr:100 recv [x=320,y=240]
|
19383
|
+
push: 'imageattrs',
|
19384
|
+
reg: new RegExp( // a=imageattr:97
|
19385
|
+
'^imageattr:(\\d+|\\*)' + // send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320]
|
19386
|
+
'[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' + // recv [x=330,y=250]
|
19387
|
+
'(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?'),
|
19388
|
+
names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'],
|
19389
|
+
format: function (o) {
|
19390
|
+
return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : '');
|
19391
|
+
}
|
19392
|
+
}, {
|
19393
|
+
// a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8
|
19394
|
+
// a=simulcast:recv 1;4,5 send 6;7
|
19395
|
+
name: 'simulcast',
|
19396
|
+
reg: new RegExp( // a=simulcast:
|
19397
|
+
'^simulcast:' + // send 1,2,3;~4,~5
|
19398
|
+
'(send|recv) ([a-zA-Z0-9\\-_~;,]+)' + // space + recv 6;~7,~8
|
19399
|
+
'(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' + // end
|
19400
|
+
'$'),
|
19401
|
+
names: ['dir1', 'list1', 'dir2', 'list2'],
|
19402
|
+
format: function (o) {
|
19403
|
+
return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : '');
|
19404
|
+
}
|
19405
|
+
}, {
|
19406
|
+
// old simulcast draft 03 (implemented by Firefox)
|
19407
|
+
// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-simulcast-03
|
19408
|
+
// a=simulcast: recv pt=97;98 send pt=97
|
19409
|
+
// a=simulcast: send rid=5;6;7 paused=6,7
|
19410
|
+
name: 'simulcast_03',
|
19411
|
+
reg: /^simulcast:[\s\t]+([\S+\s\t]+)$/,
|
19412
|
+
names: ['value'],
|
19413
|
+
format: 'simulcast: %s'
|
19414
|
+
}, {
|
19415
|
+
// a=framerate:25
|
19416
|
+
// a=framerate:29.97
|
19417
|
+
name: 'framerate',
|
19418
|
+
reg: /^framerate:(\d+(?:$|\.\d+))/,
|
19419
|
+
format: 'framerate:%s'
|
19420
|
+
}, {
|
19421
|
+
// RFC4570
|
19422
|
+
// a=source-filter: incl IN IP4 239.5.2.31 10.1.15.5
|
19423
|
+
name: 'sourceFilter',
|
19424
|
+
reg: /^source-filter: *(excl|incl) (\S*) (IP4|IP6|\*) (\S*) (.*)/,
|
19425
|
+
names: ['filterMode', 'netType', 'addressTypes', 'destAddress', 'srcList'],
|
19426
|
+
format: 'source-filter: %s %s %s %s %s'
|
19427
|
+
}, {
|
19428
|
+
// a=bundle-only
|
19429
|
+
name: 'bundleOnly',
|
19430
|
+
reg: /^(bundle-only)/
|
19431
|
+
}, {
|
19432
|
+
// a=label:1
|
19433
|
+
name: 'label',
|
19434
|
+
reg: /^label:(.+)/,
|
19435
|
+
format: 'label:%s'
|
19436
|
+
}, {
|
19437
|
+
// RFC version 26 for SCTP over DTLS
|
19438
|
+
// https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-5
|
19439
|
+
name: 'sctpPort',
|
19440
|
+
reg: /^sctp-port:(\d+)$/,
|
19441
|
+
format: 'sctp-port:%s'
|
19442
|
+
}, {
|
19443
|
+
// RFC version 26 for SCTP over DTLS
|
19444
|
+
// https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6
|
19445
|
+
name: 'maxMessageSize',
|
19446
|
+
reg: /^max-message-size:(\d+)$/,
|
19447
|
+
format: 'max-message-size:%s'
|
19448
|
+
}, {
|
19449
|
+
// RFC7273
|
19450
|
+
// a=ts-refclk:ptp=IEEE1588-2008:39-A7-94-FF-FE-07-CB-D0:37
|
19451
|
+
push: 'tsRefClocks',
|
19452
|
+
reg: /^ts-refclk:([^\s=]*)(?:=(\S*))?/,
|
19453
|
+
names: ['clksrc', 'clksrcExt'],
|
19454
|
+
format: function (o) {
|
19455
|
+
return 'ts-refclk:%s' + (o.clksrcExt != null ? '=%s' : '');
|
19456
|
+
}
|
19457
|
+
}, {
|
19458
|
+
// RFC7273
|
19459
|
+
// a=mediaclk:direct=963214424
|
19460
|
+
name: 'mediaClk',
|
19461
|
+
reg: /^mediaclk:(?:id=(\S*))? *([^\s=]*)(?:=(\S*))?(?: *rate=(\d+)\/(\d+))?/,
|
19462
|
+
names: ['id', 'mediaClockName', 'mediaClockValue', 'rateNumerator', 'rateDenominator'],
|
19463
|
+
format: function (o) {
|
19464
|
+
var str = 'mediaclk:';
|
19465
|
+
str += o.id != null ? 'id=%s %s' : '%v%s';
|
19466
|
+
str += o.mediaClockValue != null ? '=%s' : '';
|
19467
|
+
str += o.rateNumerator != null ? ' rate=%s' : '';
|
19468
|
+
str += o.rateDenominator != null ? '/%s' : '';
|
19469
|
+
return str;
|
19470
|
+
}
|
19471
|
+
}, {
|
19472
|
+
// a=keywds:keywords
|
19473
|
+
name: 'keywords',
|
19474
|
+
reg: /^keywds:(.+)$/,
|
19475
|
+
format: 'keywds:%s'
|
19476
|
+
}, {
|
19477
|
+
// a=content:main
|
19478
|
+
name: 'content',
|
19479
|
+
reg: /^content:(.+)/,
|
19480
|
+
format: 'content:%s'
|
19481
|
+
}, // BFCP https://tools.ietf.org/html/rfc4583
|
19482
|
+
{
|
19483
|
+
// a=floorctrl:c-s
|
19484
|
+
name: 'bfcpFloorCtrl',
|
19485
|
+
reg: /^floorctrl:(c-only|s-only|c-s)/,
|
19486
|
+
format: 'floorctrl:%s'
|
19487
|
+
}, {
|
19488
|
+
// a=confid:1
|
19489
|
+
name: 'bfcpConfId',
|
19490
|
+
reg: /^confid:(\d+)/,
|
19491
|
+
format: 'confid:%s'
|
19492
|
+
}, {
|
19493
|
+
// a=userid:1
|
19494
|
+
name: 'bfcpUserId',
|
19495
|
+
reg: /^userid:(\d+)/,
|
19496
|
+
format: 'userid:%s'
|
19497
|
+
}, {
|
19498
|
+
// a=floorid:1
|
19499
|
+
name: 'bfcpFloorId',
|
19500
|
+
reg: /^floorid:(.+) (?:m-stream|mstrm):(.+)/,
|
19501
|
+
names: ['id', 'mStream'],
|
19502
|
+
format: 'floorid:%s mstrm:%s'
|
19503
|
+
}, {
|
19504
|
+
// any a= that we don't understand is kept verbatim on media.invalid
|
19505
|
+
push: 'invalid',
|
19506
|
+
names: ['value']
|
19507
|
+
}]
|
19508
|
+
}; // set sensible defaults to avoid polluting the grammar with boring details
|
19509
|
+
|
19510
|
+
Object.keys(grammar$1).forEach(function (key) {
|
19511
|
+
var objs = grammar$1[key];
|
19512
|
+
objs.forEach(function (obj) {
|
19513
|
+
if (!obj.reg) {
|
19514
|
+
obj.reg = /(.*)/;
|
19515
|
+
}
|
19516
|
+
|
19517
|
+
if (!obj.format) {
|
19518
|
+
obj.format = '%s';
|
19519
|
+
}
|
19520
|
+
});
|
19521
|
+
});
|
19522
|
+
|
19523
|
+
(function (exports) {
|
19524
|
+
var toIntIfInt = function (v) {
|
19525
|
+
return String(Number(v)) === v ? Number(v) : v;
|
19526
|
+
};
|
19527
|
+
|
19528
|
+
var attachProperties = function (match, location, names, rawName) {
|
19529
|
+
if (rawName && !names) {
|
19530
|
+
location[rawName] = toIntIfInt(match[1]);
|
19531
|
+
} else {
|
19532
|
+
for (var i = 0; i < names.length; i += 1) {
|
19533
|
+
if (match[i + 1] != null) {
|
19534
|
+
location[names[i]] = toIntIfInt(match[i + 1]);
|
19535
|
+
}
|
19536
|
+
}
|
19537
|
+
}
|
19538
|
+
};
|
19539
|
+
|
19540
|
+
var parseReg = function (obj, location, content) {
|
19541
|
+
var needsBlank = obj.name && obj.names;
|
19542
|
+
|
19543
|
+
if (obj.push && !location[obj.push]) {
|
19544
|
+
location[obj.push] = [];
|
19545
|
+
} else if (needsBlank && !location[obj.name]) {
|
19546
|
+
location[obj.name] = {};
|
19547
|
+
}
|
19548
|
+
|
19549
|
+
var keyLocation = obj.push ? {} : // blank object that will be pushed
|
19550
|
+
needsBlank ? location[obj.name] : location; // otherwise, named location or root
|
19551
|
+
|
19552
|
+
attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);
|
19553
|
+
|
19554
|
+
if (obj.push) {
|
19555
|
+
location[obj.push].push(keyLocation);
|
19556
|
+
}
|
19557
|
+
};
|
19558
|
+
|
19559
|
+
var grammar = grammar$2.exports;
|
19560
|
+
var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);
|
19561
|
+
|
19562
|
+
exports.parse = function (sdp) {
|
19563
|
+
var session = {},
|
19564
|
+
media = [],
|
19565
|
+
location = session; // points at where properties go under (one of the above)
|
19566
|
+
// parse lines we understand
|
19567
|
+
|
19568
|
+
sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) {
|
19569
|
+
var type = l[0];
|
19570
|
+
var content = l.slice(2);
|
19571
|
+
|
19572
|
+
if (type === 'm') {
|
19573
|
+
media.push({
|
19574
|
+
rtp: [],
|
19575
|
+
fmtp: []
|
19576
|
+
});
|
19577
|
+
location = media[media.length - 1]; // point at latest media line
|
19578
|
+
}
|
19579
|
+
|
19580
|
+
for (var j = 0; j < (grammar[type] || []).length; j += 1) {
|
19581
|
+
var obj = grammar[type][j];
|
19582
|
+
|
19583
|
+
if (obj.reg.test(content)) {
|
19584
|
+
return parseReg(obj, location, content);
|
19585
|
+
}
|
19586
|
+
}
|
19587
|
+
});
|
19588
|
+
session.media = media; // link it up
|
19589
|
+
|
19590
|
+
return session;
|
19591
|
+
};
|
19592
|
+
|
19593
|
+
var paramReducer = function (acc, expr) {
|
19594
|
+
var s = expr.split(/=(.+)/, 2);
|
19595
|
+
|
19596
|
+
if (s.length === 2) {
|
19597
|
+
acc[s[0]] = toIntIfInt(s[1]);
|
19598
|
+
} else if (s.length === 1 && expr.length > 1) {
|
19599
|
+
acc[s[0]] = undefined;
|
19600
|
+
}
|
19601
|
+
|
19602
|
+
return acc;
|
19603
|
+
};
|
19604
|
+
|
19605
|
+
exports.parseParams = function (str) {
|
19606
|
+
return str.split(/;\s?/).reduce(paramReducer, {});
|
19607
|
+
}; // For backward compatibility - alias will be removed in 3.0.0
|
19608
|
+
|
19609
|
+
|
19610
|
+
exports.parseFmtpConfig = exports.parseParams;
|
19611
|
+
|
19612
|
+
exports.parsePayloads = function (str) {
|
19613
|
+
return str.toString().split(' ').map(Number);
|
19614
|
+
};
|
19615
|
+
|
19616
|
+
exports.parseRemoteCandidates = function (str) {
|
19617
|
+
var candidates = [];
|
19618
|
+
var parts = str.split(' ').map(toIntIfInt);
|
19619
|
+
|
19620
|
+
for (var i = 0; i < parts.length; i += 3) {
|
19621
|
+
candidates.push({
|
19622
|
+
component: parts[i],
|
19623
|
+
ip: parts[i + 1],
|
19624
|
+
port: parts[i + 2]
|
19625
|
+
});
|
19626
|
+
}
|
19627
|
+
|
19628
|
+
return candidates;
|
19629
|
+
};
|
19630
|
+
|
19631
|
+
exports.parseImageAttributes = function (str) {
|
19632
|
+
return str.split(' ').map(function (item) {
|
19633
|
+
return item.substring(1, item.length - 1).split(',').reduce(paramReducer, {});
|
19634
|
+
});
|
19635
|
+
};
|
19636
|
+
|
19637
|
+
exports.parseSimulcastStreamList = function (str) {
|
19638
|
+
return str.split(';').map(function (stream) {
|
19639
|
+
return stream.split(',').map(function (format) {
|
19640
|
+
var scid,
|
19641
|
+
paused = false;
|
19642
|
+
|
19643
|
+
if (format[0] !== '~') {
|
19644
|
+
scid = toIntIfInt(format);
|
19645
|
+
} else {
|
19646
|
+
scid = toIntIfInt(format.substring(1, format.length));
|
19647
|
+
paused = true;
|
19648
|
+
}
|
19649
|
+
|
19650
|
+
return {
|
19651
|
+
scid: scid,
|
19652
|
+
paused: paused
|
19653
|
+
};
|
19654
|
+
});
|
19655
|
+
});
|
19656
|
+
};
|
19657
|
+
})(parser$1);
|
19658
|
+
|
19659
|
+
var grammar = grammar$2.exports; // customized util.format - discards excess arguments and can void middle ones
|
19660
|
+
|
19661
|
+
var formatRegExp = /%[sdv%]/g;
|
19662
|
+
|
19663
|
+
var format = function (formatStr) {
|
19664
|
+
var i = 1;
|
19665
|
+
var args = arguments;
|
19666
|
+
var len = args.length;
|
19667
|
+
return formatStr.replace(formatRegExp, function (x) {
|
19668
|
+
if (i >= len) {
|
19669
|
+
return x; // missing argument
|
19670
|
+
}
|
19671
|
+
|
19672
|
+
var arg = args[i];
|
19673
|
+
i += 1;
|
19674
|
+
|
19675
|
+
switch (x) {
|
19676
|
+
case '%%':
|
19677
|
+
return '%';
|
19678
|
+
|
19679
|
+
case '%s':
|
19680
|
+
return String(arg);
|
19681
|
+
|
19682
|
+
case '%d':
|
19683
|
+
return Number(arg);
|
19684
|
+
|
19685
|
+
case '%v':
|
19686
|
+
return '';
|
19687
|
+
}
|
19688
|
+
}); // NB: we discard excess arguments - they are typically undefined from makeLine
|
19689
|
+
};
|
19690
|
+
|
19691
|
+
var makeLine = function (type, obj, location) {
|
19692
|
+
var str = obj.format instanceof Function ? obj.format(obj.push ? location : location[obj.name]) : obj.format;
|
19693
|
+
var args = [type + '=' + str];
|
19694
|
+
|
19695
|
+
if (obj.names) {
|
19696
|
+
for (var i = 0; i < obj.names.length; i += 1) {
|
19697
|
+
var n = obj.names[i];
|
19698
|
+
|
19699
|
+
if (obj.name) {
|
19700
|
+
args.push(location[obj.name][n]);
|
19701
|
+
} else {
|
19702
|
+
// for mLine and push attributes
|
19703
|
+
args.push(location[obj.names[i]]);
|
19704
|
+
}
|
19705
|
+
}
|
19706
|
+
} else {
|
19707
|
+
args.push(location[obj.name]);
|
19708
|
+
}
|
19709
|
+
|
19710
|
+
return format.apply(null, args);
|
19711
|
+
}; // RFC specified order
|
19712
|
+
// TODO: extend this with all the rest
|
19713
|
+
|
19714
|
+
|
19715
|
+
var defaultOuterOrder = ['v', 'o', 's', 'i', 'u', 'e', 'p', 'c', 'b', 't', 'r', 'z', 'a'];
|
19716
|
+
var defaultInnerOrder = ['i', 'c', 'b', 'a'];
|
19717
|
+
|
19718
|
+
var writer$1 = function (session, opts) {
|
19719
|
+
opts = opts || {}; // ensure certain properties exist
|
19720
|
+
|
19721
|
+
if (session.version == null) {
|
19722
|
+
session.version = 0; // 'v=0' must be there (only defined version atm)
|
19723
|
+
}
|
19724
|
+
|
19725
|
+
if (session.name == null) {
|
19726
|
+
session.name = ' '; // 's= ' must be there if no meaningful name set
|
19727
|
+
}
|
19728
|
+
|
19729
|
+
session.media.forEach(function (mLine) {
|
19730
|
+
if (mLine.payloads == null) {
|
19731
|
+
mLine.payloads = '';
|
19732
|
+
}
|
19733
|
+
});
|
19734
|
+
var outerOrder = opts.outerOrder || defaultOuterOrder;
|
19735
|
+
var innerOrder = opts.innerOrder || defaultInnerOrder;
|
19736
|
+
var sdp = []; // loop through outerOrder for matching properties on session
|
19737
|
+
|
19738
|
+
outerOrder.forEach(function (type) {
|
19739
|
+
grammar[type].forEach(function (obj) {
|
19740
|
+
if (obj.name in session && session[obj.name] != null) {
|
19741
|
+
sdp.push(makeLine(type, obj, session));
|
19742
|
+
} else if (obj.push in session && session[obj.push] != null) {
|
19743
|
+
session[obj.push].forEach(function (el) {
|
19744
|
+
sdp.push(makeLine(type, obj, el));
|
19745
|
+
});
|
19746
|
+
}
|
19747
|
+
});
|
19748
|
+
}); // then for each media line, follow the innerOrder
|
19749
|
+
|
19750
|
+
session.media.forEach(function (mLine) {
|
19751
|
+
sdp.push(makeLine('m', grammar.m[0], mLine));
|
19752
|
+
innerOrder.forEach(function (type) {
|
19753
|
+
grammar[type].forEach(function (obj) {
|
19754
|
+
if (obj.name in mLine && mLine[obj.name] != null) {
|
19755
|
+
sdp.push(makeLine(type, obj, mLine));
|
19756
|
+
} else if (obj.push in mLine && mLine[obj.push] != null) {
|
19757
|
+
mLine[obj.push].forEach(function (el) {
|
19758
|
+
sdp.push(makeLine(type, obj, el));
|
19759
|
+
});
|
19760
|
+
}
|
19761
|
+
});
|
19762
|
+
});
|
19763
|
+
});
|
19764
|
+
return sdp.join('\r\n') + '\r\n';
|
19765
|
+
};
|
19766
|
+
|
19767
|
+
var parser = parser$1;
|
19768
|
+
var writer = writer$1;
|
19769
|
+
var write = writer;
|
19770
|
+
var parse = parser.parse;
|
19771
|
+
|
19053
19772
|
/** @internal */
|
19054
19773
|
|
19055
19774
|
class PCTransport {
|
@@ -19092,6 +19811,8 @@ class PCTransport {
|
|
19092
19811
|
}
|
19093
19812
|
|
19094
19813
|
async createAndSendOffer(options) {
|
19814
|
+
var _a;
|
19815
|
+
|
19095
19816
|
if (this.onOffer === undefined) {
|
19096
19817
|
return;
|
19097
19818
|
}
|
@@ -19121,30 +19842,72 @@ class PCTransport {
|
|
19121
19842
|
|
19122
19843
|
|
19123
19844
|
livekitLogger.debug('starting to negotiate');
|
19124
|
-
const offer = await this.pc.createOffer(options);
|
19845
|
+
const offer = await this.pc.createOffer(options);
|
19846
|
+
const sdpParsed = parse((_a = offer.sdp) !== null && _a !== void 0 ? _a : '');
|
19847
|
+
sdpParsed.media.forEach(media => {
|
19848
|
+
if (media.type === 'audio') {
|
19849
|
+
ensureAudioNack(media);
|
19850
|
+
} else if (media.type === 'video') {
|
19851
|
+
// mung sdp for codec bitrate setting that can't apply by sendEncoding
|
19852
|
+
this.trackBitrates.some(trackbr => {
|
19853
|
+
if (!media.msid || !media.msid.includes(trackbr.sid)) {
|
19854
|
+
return false;
|
19855
|
+
}
|
19125
19856
|
|
19126
|
-
|
19127
|
-
|
19857
|
+
let codecPayload = 0;
|
19858
|
+
media.rtp.some(rtp => {
|
19859
|
+
if (rtp.codec.toUpperCase() === trackbr.codec.toUpperCase()) {
|
19860
|
+
codecPayload = rtp.payload;
|
19861
|
+
return true;
|
19862
|
+
}
|
19128
19863
|
|
19129
|
-
|
19130
|
-
|
19864
|
+
return false;
|
19865
|
+
}); // add x-google-max-bitrate to fmtp line if not exist
|
19131
19866
|
|
19132
|
-
|
19133
|
-
|
19134
|
-
|
19867
|
+
if (codecPayload > 0) {
|
19868
|
+
if (!media.fmtp.some(fmtp => {
|
19869
|
+
if (fmtp.payload === codecPayload) {
|
19870
|
+
if (!fmtp.config.includes('x-google-max-bitrate')) {
|
19871
|
+
fmtp.config += ";x-google-max-bitrate=".concat(trackbr.maxbr);
|
19872
|
+
}
|
19135
19873
|
|
19136
|
-
|
19137
|
-
|
19138
|
-
|
19139
|
-
|
19140
|
-
|
19141
|
-
|
19874
|
+
return true;
|
19875
|
+
}
|
19876
|
+
|
19877
|
+
return false;
|
19878
|
+
})) {
|
19879
|
+
media.fmtp.push({
|
19880
|
+
payload: codecPayload,
|
19881
|
+
config: "x-google-max-bitrate=".concat(trackbr.maxbr)
|
19882
|
+
});
|
19883
|
+
}
|
19884
|
+
}
|
19885
|
+
|
19886
|
+
return true;
|
19887
|
+
});
|
19888
|
+
}
|
19142
19889
|
});
|
19890
|
+
offer.sdp = write(sdpParsed);
|
19143
19891
|
this.trackBitrates = [];
|
19144
19892
|
await this.pc.setLocalDescription(offer);
|
19145
19893
|
this.onOffer(offer);
|
19146
19894
|
}
|
19147
19895
|
|
19896
|
+
async createAndSetAnswer() {
|
19897
|
+
var _a;
|
19898
|
+
|
19899
|
+
const answer = await this.pc.createAnswer();
|
19900
|
+
const sdpParsed = parse((_a = answer.sdp) !== null && _a !== void 0 ? _a : '');
|
19901
|
+
sdpParsed.media.forEach(media => {
|
19902
|
+
if (media.type === 'audio') {
|
19903
|
+
ensureAudioNack(media);
|
19904
|
+
}
|
19905
|
+
});
|
19906
|
+
answer.sdp = write(sdpParsed);
|
19907
|
+
await this.pc.setLocalDescription(answer);
|
19908
|
+
return answer;
|
19909
|
+
}
|
19910
|
+
|
19148
19911
|
setTrackCodecBitrate(sid, codec, maxbr) {
|
19149
19912
|
this.trackBitrates.push({
|
19150
19913
|
sid,
|
@@ -19159,11 +19922,35 @@ class PCTransport {
|
|
19159
19922
|
|
19160
19923
|
}
|
19161
19924
|
|
19925
|
+
function ensureAudioNack(media) {
|
19926
|
+
// found opus codec to add nack fb
|
19927
|
+
let opusPayload = 0;
|
19928
|
+
media.rtp.some(rtp => {
|
19929
|
+
if (rtp.codec === 'opus') {
|
19930
|
+
opusPayload = rtp.payload;
|
19931
|
+
return true;
|
19932
|
+
}
|
19933
|
+
|
19934
|
+
return false;
|
19935
|
+
}); // add nack rtcpfb if not exist
|
19936
|
+
|
19937
|
+
if (opusPayload > 0) {
|
19938
|
+
if (!media.rtcpFb) {
|
19939
|
+
media.rtcpFb = [];
|
19940
|
+
}
|
19941
|
+
|
19942
|
+
if (!media.rtcpFb.some(fb => fb.payload === opusPayload && fb.type === 'nack')) {
|
19943
|
+
media.rtcpFb.push({
|
19944
|
+
payload: opusPayload,
|
19945
|
+
type: 'nack'
|
19946
|
+
});
|
19947
|
+
}
|
19948
|
+
}
|
19949
|
+
}
|
19950
|
+
|
19162
19951
|
const lossyDataChannel = '_lossy';
|
19163
19952
|
const reliableDataChannel = '_reliable';
|
19164
|
-
const maxReconnectRetries = 10;
|
19165
19953
|
const minReconnectWait = 2 * 1000;
|
19166
|
-
const maxReconnectDuration = 60 * 1000;
|
19167
19954
|
const maxICEConnectTimeout = 15 * 1000;
|
19168
19955
|
var PCState;
|
19169
19956
|
|
@@ -19178,8 +19965,14 @@ var PCState;
|
|
19178
19965
|
|
19179
19966
|
|
19180
19967
|
class RTCEngine extends events.exports.EventEmitter {
|
19181
|
-
constructor() {
|
19968
|
+
constructor(options) {
|
19969
|
+
var _this;
|
19970
|
+
|
19971
|
+
var _a;
|
19972
|
+
|
19182
19973
|
super();
|
19974
|
+
_this = this;
|
19975
|
+
this.options = options;
|
19183
19976
|
this.rtcConfig = {};
|
19184
19977
|
this.subscriberPrimary = false;
|
19185
19978
|
this.pcState = PCState.New;
|
@@ -19254,53 +20047,85 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19254
20047
|
// after a number of retries, we'll close and give up permanently
|
19255
20048
|
|
19256
20049
|
|
19257
|
-
this.handleDisconnect = connection
|
19258
|
-
|
20050
|
+
this.handleDisconnect = function (connection) {
|
20051
|
+
let signalEvents = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
20052
|
+
|
20053
|
+
if (_this._isClosed) {
|
19259
20054
|
return;
|
19260
20055
|
}
|
19261
20056
|
|
19262
20057
|
livekitLogger.debug("".concat(connection, " disconnected"));
|
19263
20058
|
|
19264
|
-
if (
|
20059
|
+
if (_this.reconnectAttempts === 0) {
|
19265
20060
|
// only reset start time on the first try
|
19266
|
-
|
20061
|
+
_this.reconnectStart = Date.now();
|
20062
|
+
}
|
20063
|
+
|
20064
|
+
const disconnect = duration => {
|
20065
|
+
livekitLogger.info("could not recover connection after ".concat(_this.reconnectAttempts, " attempts, ").concat(duration, "ms. giving up"));
|
20066
|
+
|
20067
|
+
_this.emit(EngineEvent.Disconnected);
|
20068
|
+
|
20069
|
+
_this.close();
|
20070
|
+
};
|
20071
|
+
|
20072
|
+
const duration = Date.now() - _this.reconnectStart;
|
20073
|
+
|
20074
|
+
const delay = _this.getNextRetryDelay({
|
20075
|
+
elapsedMs: duration,
|
20076
|
+
retryCount: _this.reconnectAttempts
|
20077
|
+
});
|
20078
|
+
|
20079
|
+
if (delay === null) {
|
20080
|
+
disconnect(duration);
|
20081
|
+
return;
|
19267
20082
|
}
|
19268
20083
|
|
19269
|
-
|
19270
|
-
|
20084
|
+
livekitLogger.debug("reconnecting in ".concat(delay, "ms"));
|
20085
|
+
|
20086
|
+
if (_this.reconnectTimeout) {
|
20087
|
+
clearTimeout(_this.reconnectTimeout);
|
20088
|
+
}
|
20089
|
+
|
20090
|
+
_this.reconnectTimeout = setTimeout(async () => {
|
19271
20091
|
var _a, _b, _c;
|
19272
20092
|
|
19273
|
-
if (
|
20093
|
+
if (_this._isClosed) {
|
19274
20094
|
return;
|
19275
20095
|
} // guard for attempting reconnection multiple times while one attempt is still not finished
|
19276
20096
|
|
19277
20097
|
|
19278
|
-
if (
|
20098
|
+
if (_this.attemptingReconnect) {
|
19279
20099
|
return;
|
19280
20100
|
}
|
19281
20101
|
|
19282
20102
|
if (isFireFox() || // TODO remove once clientConfiguration handles firefox case server side
|
19283
|
-
((_a =
|
20103
|
+
((_a = _this.clientConfiguration) === null || _a === void 0 ? void 0 : _a.resumeConnection) === ClientConfigSetting.DISABLED || // signaling state could change to closed due to hardware sleep
|
19284
20104
|
// those connections cannot be resumed
|
19285
|
-
((_c = (_b =
|
19286
|
-
|
20105
|
+
((_c = (_b = _this.primaryPC) === null || _b === void 0 ? void 0 : _b.signalingState) !== null && _c !== void 0 ? _c : 'closed') === 'closed') {
|
20106
|
+
_this.fullReconnectOnNext = true;
|
19287
20107
|
}
|
19288
20108
|
|
19289
20109
|
try {
|
19290
|
-
|
20110
|
+
_this.attemptingReconnect = true;
|
19291
20111
|
|
19292
|
-
if (
|
19293
|
-
await
|
20112
|
+
if (_this.fullReconnectOnNext) {
|
20113
|
+
await _this.restartConnection(signalEvents);
|
19294
20114
|
} else {
|
19295
|
-
await
|
20115
|
+
await _this.resumeConnection(signalEvents);
|
19296
20116
|
}
|
19297
20117
|
|
19298
|
-
|
19299
|
-
|
20118
|
+
_this.reconnectAttempts = 0;
|
20119
|
+
_this.fullReconnectOnNext = false;
|
20120
|
+
|
20121
|
+
if (_this.reconnectTimeout) {
|
20122
|
+
clearTimeout(_this.reconnectTimeout);
|
20123
|
+
}
|
19300
20124
|
} catch (e) {
|
19301
|
-
|
20125
|
+
_this.reconnectAttempts += 1;
|
19302
20126
|
let reconnectRequired = false;
|
19303
20127
|
let recoverable = true;
|
20128
|
+
let requireSignalEvents = false;
|
19304
20129
|
|
19305
20130
|
if (e instanceof UnexpectedConnectionState) {
|
19306
20131
|
livekitLogger.debug('received unrecoverable error', {
|
@@ -19311,35 +20136,29 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19311
20136
|
} else if (!(e instanceof SignalReconnectError)) {
|
19312
20137
|
// cannot resume
|
19313
20138
|
reconnectRequired = true;
|
19314
|
-
} // when we flip from resume to reconnect
|
19315
|
-
//
|
19316
|
-
|
19317
|
-
|
19318
|
-
if (reconnectRequired && !this.fullReconnectOnNext) {
|
19319
|
-
this.fullReconnectOnNext = true;
|
19320
|
-
this.reconnectAttempts = 0;
|
19321
|
-
}
|
20139
|
+
} // when we flip from resume to reconnect
|
20140
|
+
// we need to fire the right reconnecting events
|
19322
20141
|
|
19323
|
-
const duration = Date.now() - this.reconnectStart;
|
19324
20142
|
|
19325
|
-
if (
|
19326
|
-
|
20143
|
+
if (reconnectRequired && !_this.fullReconnectOnNext) {
|
20144
|
+
_this.fullReconnectOnNext = true;
|
20145
|
+
requireSignalEvents = true;
|
19327
20146
|
}
|
19328
20147
|
|
19329
20148
|
if (recoverable) {
|
19330
|
-
|
20149
|
+
_this.handleDisconnect('reconnect', requireSignalEvents);
|
19331
20150
|
} else {
|
19332
|
-
|
19333
|
-
this.emit(EngineEvent.Disconnected);
|
19334
|
-
this.close();
|
20151
|
+
disconnect(Date.now() - _this.reconnectStart);
|
19335
20152
|
}
|
19336
20153
|
} finally {
|
19337
|
-
|
20154
|
+
_this.attemptingReconnect = false;
|
19338
20155
|
}
|
19339
20156
|
}, delay);
|
19340
20157
|
};
|
19341
20158
|
|
19342
20159
|
this.client = new SignalClient();
|
20160
|
+
this.client.signalLatency = this.options.expSignalLatency;
|
20161
|
+
this.reconnectPolicy = (_a = this.options.reconnectPolicy) !== null && _a !== void 0 ? _a : new DefaultReconnectPolicy();
|
19343
20162
|
}
|
19344
20163
|
|
19345
20164
|
get isClosed() {
|
@@ -19403,8 +20222,16 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19403
20222
|
throw new TrackInvalidError('a track with the same ID has already been published');
|
19404
20223
|
}
|
19405
20224
|
|
19406
|
-
return new Promise(resolve => {
|
19407
|
-
|
20225
|
+
return new Promise((resolve, reject) => {
|
20226
|
+
const publicationTimeout = setTimeout(() => {
|
20227
|
+
reject(new ConnectionError('publication of local track timed out, no response from server'));
|
20228
|
+
}, 15000);
|
20229
|
+
|
20230
|
+
this.pendingTrackResolvers[req.cid] = info => {
|
20231
|
+
clearTimeout(publicationTimeout);
|
20232
|
+
resolve(info);
|
20233
|
+
};
|
20234
|
+
|
19408
20235
|
this.client.sendAddTrack(req);
|
19409
20236
|
});
|
19410
20237
|
}
|
@@ -19578,8 +20405,7 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19578
20405
|
});
|
19579
20406
|
await this.subscriber.setRemoteDescription(sd); // answer the offer
|
19580
20407
|
|
19581
|
-
const answer = await this.subscriber.
|
19582
|
-
await this.subscriber.pc.setLocalDescription(answer);
|
20408
|
+
const answer = await this.subscriber.createAndSetAnswer();
|
19583
20409
|
this.client.sendAnswer(answer);
|
19584
20410
|
};
|
19585
20411
|
|
@@ -19652,7 +20478,22 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19652
20478
|
this.reliableDC.onerror = this.handleDataError;
|
19653
20479
|
}
|
19654
20480
|
|
20481
|
+
getNextRetryDelay(context) {
|
20482
|
+
try {
|
20483
|
+
return this.reconnectPolicy.nextRetryDelayInMs(context);
|
20484
|
+
} catch (e) {
|
20485
|
+
livekitLogger.warn('encountered error in reconnect policy', {
|
20486
|
+
error: e
|
20487
|
+
});
|
20488
|
+
} // error in user code with provided reconnect policy, stop reconnecting
|
20489
|
+
|
20490
|
+
|
20491
|
+
return null;
|
20492
|
+
}
|
20493
|
+
|
19655
20494
|
async restartConnection() {
|
20495
|
+
let emitRestarting = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
20496
|
+
|
19656
20497
|
var _a, _b;
|
19657
20498
|
|
19658
20499
|
if (!this.url || !this.token) {
|
@@ -19662,7 +20503,7 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19662
20503
|
|
19663
20504
|
livekitLogger.info("reconnecting, attempt: ".concat(this.reconnectAttempts));
|
19664
20505
|
|
19665
|
-
if (this.reconnectAttempts === 0) {
|
20506
|
+
if (emitRestarting || this.reconnectAttempts === 0) {
|
19666
20507
|
this.emit(EngineEvent.Restarting);
|
19667
20508
|
}
|
19668
20509
|
|
@@ -19691,6 +20532,8 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19691
20532
|
}
|
19692
20533
|
|
19693
20534
|
async resumeConnection() {
|
20535
|
+
let emitResuming = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
20536
|
+
|
19694
20537
|
var _a;
|
19695
20538
|
|
19696
20539
|
if (!this.url || !this.token) {
|
@@ -19705,14 +20548,20 @@ class RTCEngine extends events.exports.EventEmitter {
|
|
19705
20548
|
|
19706
20549
|
livekitLogger.info("resuming signal connection, attempt ".concat(this.reconnectAttempts));
|
19707
20550
|
|
19708
|
-
if (this.reconnectAttempts === 0) {
|
20551
|
+
if (emitResuming || this.reconnectAttempts === 0) {
|
19709
20552
|
this.emit(EngineEvent.Resuming);
|
19710
20553
|
}
|
19711
20554
|
|
19712
20555
|
try {
|
19713
20556
|
await this.client.reconnect(this.url, this.token);
|
19714
20557
|
} catch (e) {
|
19715
|
-
|
20558
|
+
let message = '';
|
20559
|
+
|
20560
|
+
if (e instanceof Error) {
|
20561
|
+
message = e.message;
|
20562
|
+
}
|
20563
|
+
|
20564
|
+
throw new SignalReconnectError(message);
|
19716
20565
|
}
|
19717
20566
|
|
19718
20567
|
this.emit(EngineEvent.SignalResumed);
|
@@ -20020,23 +20869,7 @@ class Room extends events.exports.EventEmitter {
|
|
20020
20869
|
this.localParticipant.identity = pi.identity;
|
20021
20870
|
this.localParticipant.updateInfo(pi); // forward metadata changed for the local participant
|
20022
20871
|
|
20023
|
-
this.localParticipant.on(ParticipantEvent.ParticipantMetadataChanged,
|
20024
|
-
this.emit(RoomEvent.ParticipantMetadataChanged, metadata, this.localParticipant);
|
20025
|
-
}).on(ParticipantEvent.TrackMuted, pub => {
|
20026
|
-
this.emit(RoomEvent.TrackMuted, pub, this.localParticipant);
|
20027
|
-
}).on(ParticipantEvent.TrackUnmuted, pub => {
|
20028
|
-
this.emit(RoomEvent.TrackUnmuted, pub, this.localParticipant);
|
20029
|
-
}).on(ParticipantEvent.LocalTrackPublished, pub => {
|
20030
|
-
this.emit(RoomEvent.LocalTrackPublished, pub, this.localParticipant);
|
20031
|
-
}).on(ParticipantEvent.LocalTrackUnpublished, pub => {
|
20032
|
-
this.emit(RoomEvent.LocalTrackUnpublished, pub, this.localParticipant);
|
20033
|
-
}).on(ParticipantEvent.ConnectionQualityChanged, quality => {
|
20034
|
-
this.emit(RoomEvent.ConnectionQualityChanged, quality, this.localParticipant);
|
20035
|
-
}).on(ParticipantEvent.MediaDevicesError, e => {
|
20036
|
-
this.emit(RoomEvent.MediaDevicesError, e);
|
20037
|
-
}).on(ParticipantEvent.ParticipantPermissionsChanged, prevPermissions => {
|
20038
|
-
this.emit(RoomEvent.ParticipantPermissionsChanged, prevPermissions, this.localParticipant);
|
20039
|
-
}); // populate remote participants, these should not trigger new events
|
20872
|
+
this.localParticipant.on(ParticipantEvent.ParticipantMetadataChanged, this.onLocalParticipantMetadataChanged).on(ParticipantEvent.TrackMuted, this.onLocalTrackMuted).on(ParticipantEvent.TrackUnmuted, this.onLocalTrackUnmuted).on(ParticipantEvent.LocalTrackPublished, this.onLocalTrackPublished).on(ParticipantEvent.LocalTrackUnpublished, this.onLocalTrackUnpublished).on(ParticipantEvent.ConnectionQualityChanged, this.onLocalConnectionQualityChanged).on(ParticipantEvent.MediaDevicesError, this.onMediaDevicesError).on(ParticipantEvent.ParticipantPermissionsChanged, this.onLocalParticipantPermissionsChanged); // populate remote participants, these should not trigger new events
|
20040
20873
|
|
20041
20874
|
joinResponse.otherParticipants.forEach(info => {
|
20042
20875
|
if (info.sid !== this.localParticipant.sid && info.identity !== this.localParticipant.identity) {
|
@@ -20379,6 +21212,38 @@ class Room extends events.exports.EventEmitter {
|
|
20379
21212
|
});
|
20380
21213
|
};
|
20381
21214
|
|
21215
|
+
this.onLocalParticipantMetadataChanged = metadata => {
|
21216
|
+
this.emit(RoomEvent.ParticipantMetadataChanged, metadata, this.localParticipant);
|
21217
|
+
};
|
21218
|
+
|
21219
|
+
this.onLocalTrackMuted = pub => {
|
21220
|
+
this.emit(RoomEvent.TrackMuted, pub, this.localParticipant);
|
21221
|
+
};
|
21222
|
+
|
21223
|
+
this.onLocalTrackUnmuted = pub => {
|
21224
|
+
this.emit(RoomEvent.TrackUnmuted, pub, this.localParticipant);
|
21225
|
+
};
|
21226
|
+
|
21227
|
+
this.onLocalTrackPublished = pub => {
|
21228
|
+
this.emit(RoomEvent.LocalTrackPublished, pub, this.localParticipant);
|
21229
|
+
};
|
21230
|
+
|
21231
|
+
this.onLocalTrackUnpublished = pub => {
|
21232
|
+
this.emit(RoomEvent.LocalTrackUnpublished, pub, this.localParticipant);
|
21233
|
+
};
|
21234
|
+
|
21235
|
+
this.onLocalConnectionQualityChanged = quality => {
|
21236
|
+
this.emit(RoomEvent.ConnectionQualityChanged, quality, this.localParticipant);
|
21237
|
+
};
|
21238
|
+
|
21239
|
+
this.onMediaDevicesError = e => {
|
21240
|
+
this.emit(RoomEvent.MediaDevicesError, e);
|
21241
|
+
};
|
21242
|
+
|
21243
|
+
this.onLocalParticipantPermissionsChanged = prevPermissions => {
|
21244
|
+
this.emit(RoomEvent.ParticipantPermissionsChanged, prevPermissions, this.localParticipant);
|
21245
|
+
};
|
21246
|
+
|
20382
21247
|
this.participants = new Map();
|
20383
21248
|
this.identityToSid = new Map();
|
20384
21249
|
this.options = options || {};
|
@@ -20394,8 +21259,7 @@ class Room extends events.exports.EventEmitter {
|
|
20394
21259
|
return;
|
20395
21260
|
}
|
20396
21261
|
|
20397
|
-
this.engine = new RTCEngine();
|
20398
|
-
this.engine.client.signalLatency = this.options.expSignalLatency;
|
21262
|
+
this.engine = new RTCEngine(this.options);
|
20399
21263
|
this.engine.client.onParticipantUpdate = this.handleParticipantUpdates;
|
20400
21264
|
this.engine.client.onRoomUpdate = this.handleRoomUpdate;
|
20401
21265
|
this.engine.client.onSpeakersChanged = this.handleSpeakersChanged;
|
@@ -20676,6 +21540,7 @@ class Room extends events.exports.EventEmitter {
|
|
20676
21540
|
p.unpublishTrack(pub.trackSid);
|
20677
21541
|
});
|
20678
21542
|
});
|
21543
|
+
this.localParticipant.off(ParticipantEvent.ParticipantMetadataChanged, this.onLocalParticipantMetadataChanged).off(ParticipantEvent.TrackMuted, this.onLocalTrackMuted).off(ParticipantEvent.TrackUnmuted, this.onLocalTrackUnmuted).off(ParticipantEvent.LocalTrackPublished, this.onLocalTrackPublished).off(ParticipantEvent.LocalTrackUnpublished, this.onLocalTrackUnpublished).off(ParticipantEvent.ConnectionQualityChanged, this.onLocalConnectionQualityChanged).off(ParticipantEvent.MediaDevicesError, this.onMediaDevicesError).off(ParticipantEvent.ParticipantPermissionsChanged, this.onLocalParticipantPermissionsChanged);
|
20679
21544
|
this.localParticipant.tracks.forEach(pub => {
|
20680
21545
|
var _a, _b;
|
20681
21546
|
|
@@ -21033,5 +21898,5 @@ async function createLocalScreenTracks(options) {
|
|
21033
21898
|
return localTracks;
|
21034
21899
|
}
|
21035
21900
|
|
21036
|
-
export { AudioPresets, ConnectionError, ConnectionQuality, ConnectionState, DataPacket_Kind, DisconnectReason, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, protocolVersion, setLogExtension, setLogLevel, version };
|
21901
|
+
export { AudioPresets, ConnectionError, ConnectionQuality, ConnectionState, DataPacket_Kind, DefaultReconnectPolicy, DisconnectReason, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, protocolVersion, setLogExtension, setLogLevel, version };
|
21037
21902
|
//# sourceMappingURL=livekit-client.esm.mjs.map
|