@vkontakte/media-streaming 1.0.1-dev.e965d10.0 → 1.0.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.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @vkontakte/media-streaming v1.0.1-dev.e965d10.0
3
- * Mon, 03 Aug 2026 10:45:14 GMT
2
+ * @vkontakte/media-streaming v1.0.1
3
+ * Mon, 28 Sep 2026 08:29:49 GMT
4
4
  */
5
5
  var __legacyDecorateClassTS = function(decorators, target, key, desc) {
6
6
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -13,14 +13,25 @@ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
13
13
  return c > 3 && r && Object.defineProperty(target, key, r), r;
14
14
  };
15
15
 
16
- // src/env.ts
17
- var VERSION = "1.0.1-dev.e965d10.0";
16
+ // src/MediaError.ts
17
+ class StreamerMediaError extends Error {
18
+ constructor(name, message) {
19
+ super(message);
20
+ this.name = name;
21
+ }
22
+ }
23
+
18
24
  // src/constants.ts
19
25
  var DEFAULT_STUN_SERVERS = [{ urls: ["stun:videostun.mycdn.me:19302"] }];
20
26
  var DEFAULT_WS_SERVER = "wss://ovsu.mycdn.me/publish";
21
27
  var WS_CLOSE_CODE = 1000;
22
28
  var DEFAULT_FRAME_RATE = 15;
23
29
  var SCREEN_SHARE_CONTENT_TEXTHINT = "text";
30
+ var PermissionName;
31
+ ((PermissionName2) => {
32
+ PermissionName2["DISPLAY_MEDIA"] = "display_media";
33
+ PermissionName2["USER_MEDIA"] = "user_media";
34
+ })(PermissionName ||= {});
24
35
  var MediaErrorType;
25
36
  ((MediaErrorType2) => {
26
37
  MediaErrorType2["UNKNOWN"] = "unknown";
@@ -37,8 +48,6 @@ var StreamerError;
37
48
  StreamerError2["PEERCONNECTION"] = "peerconnection";
38
49
  StreamerError2["CONSTRAINTS"] = "constraints";
39
50
  })(StreamerError ||= {});
40
- // src/WebRTCStreamer.ts
41
- import { flattenObject } from "@vkontakte/videoplayer-shared";
42
51
 
43
52
  // src/MediaConstraints.ts
44
53
  class MediaConstraints {
@@ -74,14 +83,6 @@ class MediaConstraints {
74
83
  }
75
84
  }
76
85
 
77
- // src/MediaError.ts
78
- class MediaError2 extends Error {
79
- constructor(name, message) {
80
- super(message);
81
- this.name = name;
82
- }
83
- }
84
-
85
86
  // src/utils.ts
86
87
  var getWindow = () => {
87
88
  return globalThis;
@@ -102,29 +103,38 @@ var getSafariVersion = (userAgent) => {
102
103
  const version = parseInt(versionMatch[1], 10);
103
104
  return isNaN(version) ? undefined : version;
104
105
  };
105
- var enumerateDevices = async () => await getWindow().navigator.mediaDevices.enumerateDevices();
106
- var getUserMedia = (constraints) => getWindow().navigator.mediaDevices.getUserMedia(constraints).catch((e) => {
107
- if (e instanceof Error) {
108
- switch (e.name) {
109
- case "PermissionDismissedError":
110
- case "PermissionDeniedError":
111
- case "SecurityError":
112
- case "NotAllowedError":
113
- case "DOMException":
114
- throw new MediaError2(e.name, "permission" /* PERMISSION */);
115
- case "OverconstrainedError":
116
- case "NotFoundError":
117
- case "TypeError":
118
- throw new MediaError2(e.name, "unknown" /* UNKNOWN */);
119
- case "AbortError":
120
- case "NotReadableError":
121
- throw new MediaError2(e.name, "access" /* ACCESS */);
122
- default:
123
- throw new MediaError2(e.name, "unknown" /* UNKNOWN */);
106
+ var enumerateDevices = async () => {
107
+ const devices = await getWindow().navigator.mediaDevices.enumerateDevices();
108
+ return {
109
+ cameras: devices.filter((d) => d.kind === "videoinput"),
110
+ microphones: devices.filter((d) => d.kind === "audioinput")
111
+ };
112
+ };
113
+ var getUserStream = (config) => {
114
+ const constraints = new MediaConstraints(config).getNative();
115
+ return getWindow().navigator.mediaDevices.getUserMedia(constraints).catch((e) => {
116
+ if (e instanceof Error) {
117
+ switch (e.name) {
118
+ case "PermissionDismissedError":
119
+ case "PermissionDeniedError":
120
+ case "SecurityError":
121
+ case "NotAllowedError":
122
+ case "DOMException":
123
+ throw new StreamerMediaError(e.name, "permission" /* PERMISSION */);
124
+ case "OverconstrainedError":
125
+ case "NotFoundError":
126
+ case "TypeError":
127
+ throw new StreamerMediaError(e.name, "unknown" /* UNKNOWN */);
128
+ case "AbortError":
129
+ case "NotReadableError":
130
+ throw new StreamerMediaError(e.name, "access" /* ACCESS */);
131
+ default:
132
+ throw new StreamerMediaError(e.name, "unknown" /* UNKNOWN */);
133
+ }
124
134
  }
125
- }
126
- throw new Error("unknown");
127
- });
135
+ throw new Error("unknown");
136
+ });
137
+ };
128
138
  var getDisplayMedia = (constraints) => getWindow().navigator.mediaDevices.getDisplayMedia(constraints.getNative()).catch((e) => {
129
139
  if (e instanceof Error) {
130
140
  switch (e.name) {
@@ -158,7 +168,7 @@ var serializeConfig = (cfg) => {
158
168
  key: cfg.streamKey,
159
169
  ...cfg.audioOnly && { audioOnly: true },
160
170
  ...cfg.lockOrientation && { lockOrientation: true },
161
- ...cfg.mediaConstraints && { mediaConstraints: omitKeys(cfg.mediaConstraints, ["getNative"]) },
171
+ ...cfg.mediaConfig && { mediaConfig: cfg.mediaConfig },
162
172
  ...cfg.screenShare && { screenShare: omitKeys(cfg.screenShare, ["onEnded"]) }
163
173
  };
164
174
  };
@@ -170,6 +180,11 @@ var serializeMediaDevices = (devices) => {
170
180
  }));
171
181
  };
172
182
 
183
+ // src/env.ts
184
+ var VERSION = "1.0.1";
185
+ // src/WebRTCStreamer.ts
186
+ import { flattenObject } from "@vkontakte/videoplayer-shared";
187
+
173
188
  // src/ScreenConstraints.ts
174
189
  class ScreenConstraints extends MediaConstraints {
175
190
  constructor({ width, height, frameRate = DEFAULT_FRAME_RATE }) {
@@ -199,20 +214,20 @@ class ScreenConstraints extends MediaConstraints {
199
214
  // src/WebRTCStreamer.ts
200
215
  class WebRTCStreamer {
201
216
  config;
202
- messagesQueue = [];
203
- ws;
204
- peerConnection;
205
- stream;
206
- screenShareTrack = null;
207
- connected = false;
208
- destroying = false;
209
- cameraId;
210
- microphoneId;
211
- muted = false;
217
+ #messagesQueue = [];
218
+ #ws;
219
+ #peerConnection;
220
+ #stream;
221
+ #screenShareTrack = null;
222
+ #connected = false;
223
+ #destroying = false;
224
+ #cameraId;
225
+ #microphoneId;
226
+ #muted = false;
212
227
  static notDestroying(_target, _propertyKey, descriptor) {
213
228
  const original = descriptor.value;
214
229
  descriptor.value = function(...args) {
215
- if (this.destroying) {
230
+ if (this.#destroying) {
216
231
  return;
217
232
  }
218
233
  return original.apply(this, args);
@@ -224,23 +239,26 @@ class WebRTCStreamer {
224
239
  }
225
240
  callback(name, ...args) {
226
241
  const fn = this.config.callbacks[name];
227
- if (fn && !this.destroying) {
242
+ if (fn && !this.#destroying) {
228
243
  fn?.(...args);
229
244
  }
230
245
  }
246
+ get connected() {
247
+ return this.#connected;
248
+ }
231
249
  async init() {
250
+ const { cameras, microphones } = await enumerateDevices();
232
251
  this.tracerLog("init", {
233
252
  cfg: serializeConfig(this.config),
234
- d: serializeMediaDevices(await enumerateDevices())
253
+ d: serializeMediaDevices([...cameras, ...microphones])
235
254
  });
236
255
  let permissionName = "user_media" /* USER_MEDIA */;
237
- const { audioOnly, mediaConstraints, screenShare } = this.config;
256
+ const { audioOnly, mediaConfig, screenShare } = this.config;
238
257
  try {
239
- const constraints = mediaConstraints || new MediaConstraints({
258
+ this.#stream = await getUserStream(mediaConfig ?? {
240
259
  audio: true,
241
260
  video: !screenShare && !audioOnly
242
261
  });
243
- this.stream = await getUserMedia(constraints.getNative());
244
262
  if (!audioOnly && screenShare) {
245
263
  permissionName = "display_media" /* DISPLAY_MEDIA */;
246
264
  const screenShareTrack = await this.createScreenShareStream(screenShare);
@@ -251,18 +269,17 @@ class WebRTCStreamer {
251
269
  frameRate: { exact: frameRate }
252
270
  });
253
271
  } catch (e) {
254
- this.tracerLog("error", { type: "constraints" /* CONSTRAINTS */ });
255
- this.callback("onError", "constraints" /* CONSTRAINTS */);
272
+ this.handleScreenShareConstraintsError(frameRate);
256
273
  }
257
- this.stream.addTrack(screenShareTrack);
274
+ this.#stream.addTrack(screenShareTrack);
258
275
  }
259
- this.screenShareTrack = screenShareTrack;
276
+ this.#screenShareTrack = screenShareTrack;
260
277
  }
261
- this.tracerLog("streamChanged", serializeStream(this.stream));
262
- this.callback("onStreamChanged", this.stream);
278
+ this.tracerLog("streamChanged", serializeStream(this.#stream));
279
+ this.callback("onStreamChanged", this.#stream);
263
280
  } catch (err) {
264
- if (err instanceof MediaError) {
265
- this.tracerLog("permissionFailed", { name: permissionName, msg: err.message, code: err.code });
281
+ if (err instanceof StreamerMediaError) {
282
+ this.tracerLog("permissionFailed", { name: permissionName, msg: err.message, code: err.name });
266
283
  this.callback("onPermissionFailed", permissionName, err);
267
284
  } else {
268
285
  this.tracerLog("permissionFailed", { name: permissionName });
@@ -272,8 +289,9 @@ class WebRTCStreamer {
272
289
  }
273
290
  async connect() {
274
291
  this.tracerLog("connect");
292
+ this.callback("onConnecting");
275
293
  this.openSocket();
276
- if (!this.peerConnection) {
294
+ if (!this.#peerConnection) {
277
295
  await this.createPeerConnection();
278
296
  }
279
297
  }
@@ -283,59 +301,60 @@ class WebRTCStreamer {
283
301
  if (audioOnly) {
284
302
  return;
285
303
  }
286
- this.cameraId = deviceId;
287
- const constraints = new MediaConstraints({
288
- audio: this.microphoneId ? {
289
- deviceId: this.microphoneId
304
+ this.#cameraId = deviceId;
305
+ const newStream = await getUserStream({
306
+ audio: this.#microphoneId ? {
307
+ deviceId: this.#microphoneId
290
308
  } : true,
291
309
  video: {
292
- deviceId: this.cameraId
310
+ deviceId: this.#cameraId
293
311
  }
294
312
  });
295
- const newStream = await getUserMedia(constraints.getNative());
296
313
  this.replaceStream(newStream);
297
- if (this.muted) {
314
+ if (this.#muted) {
298
315
  this.setMicMuted(true);
299
316
  }
300
317
  }
301
318
  async switchMicrophone(deviceId) {
302
319
  this.tracerLog("switchMicrophone", { id: deviceId });
303
- this.microphoneId = deviceId;
304
- const constraints = new MediaConstraints({
320
+ this.#microphoneId = deviceId;
321
+ const newStream = await getUserStream({
305
322
  audio: {
306
- deviceId: this.microphoneId
323
+ deviceId: this.#microphoneId
307
324
  },
308
- video: this.screenShareTrack ? false : this.cameraId ? {
309
- deviceId: this.cameraId
325
+ video: this.#screenShareTrack ? false : this.#cameraId ? {
326
+ deviceId: this.#cameraId
310
327
  } : true
311
328
  });
312
- const newStream = await getUserMedia(constraints.getNative());
313
- if (this.screenShareTrack) {
314
- newStream.addTrack(this.screenShareTrack);
329
+ if (this.#screenShareTrack) {
330
+ newStream.addTrack(this.#screenShareTrack);
315
331
  }
316
332
  this.replaceStream(newStream, true);
317
- if (this.muted) {
333
+ if (this.#muted) {
318
334
  this.setMicMuted(true);
319
335
  }
320
336
  }
321
337
  async enableScreenShare(config) {
322
338
  this.tracerLog("enableScreenShare", omitKeys(config, ["onEnded"]));
323
- const constraints = new MediaConstraints({
324
- audio: this.microphoneId ? { deviceId: this.microphoneId } : true,
339
+ const newStream = await getUserStream({
340
+ audio: this.#microphoneId ? { deviceId: this.#microphoneId } : true,
325
341
  video: false
326
342
  });
327
- const newStream = await getUserMedia(constraints.getNative());
328
343
  const screenShareTrack = await this.createScreenShareStream(config);
329
344
  if (screenShareTrack) {
330
345
  const { frameRate = DEFAULT_FRAME_RATE } = config;
331
- await screenShareTrack.applyConstraints({
332
- frameRate: { exact: frameRate }
333
- });
346
+ try {
347
+ await screenShareTrack.applyConstraints({
348
+ frameRate: { exact: frameRate }
349
+ });
350
+ } catch (e) {
351
+ this.handleScreenShareConstraintsError(frameRate);
352
+ }
334
353
  newStream.addTrack(screenShareTrack);
335
354
  }
336
- this.screenShareTrack = screenShareTrack;
355
+ this.#screenShareTrack = screenShareTrack;
337
356
  this.replaceStream(newStream);
338
- if (this.muted) {
357
+ if (this.#muted) {
339
358
  this.setMicMuted(true);
340
359
  }
341
360
  }
@@ -344,37 +363,90 @@ class WebRTCStreamer {
344
363
  if (cameraDeviceId) {
345
364
  await this.switchCamera(cameraDeviceId);
346
365
  } else {
347
- const devices = await enumerateDevices();
348
- const defaultCamera = devices.find((d) => d.kind === "videoinput");
366
+ const { cameras } = await enumerateDevices();
367
+ const defaultCamera = cameras[0];
349
368
  if (defaultCamera) {
350
369
  await this.switchCamera(defaultCamera.deviceId);
351
370
  }
352
371
  }
353
372
  }
373
+ async switchMediaDevices({
374
+ cameraId,
375
+ microphoneId,
376
+ screenShare
377
+ }) {
378
+ if (cameraId === undefined && microphoneId === undefined && screenShare === undefined) {
379
+ return;
380
+ }
381
+ this.tracerLog("switchMediaDevices", {
382
+ ...cameraId !== undefined && { cam: cameraId },
383
+ ...microphoneId !== undefined && { mic: microphoneId },
384
+ ...screenShare !== undefined && { ss: screenShare === false ? false : omitKeys(screenShare, ["onEnded"]) }
385
+ });
386
+ const { audioOnly } = this.config;
387
+ const changingScreenShare = screenShare !== undefined;
388
+ const keepScreenShare = !changingScreenShare && Boolean(this.#screenShareTrack);
389
+ let audio = this.#microphoneId ? { deviceId: this.#microphoneId } : true;
390
+ let video = this.#cameraId ? { deviceId: this.#cameraId } : true;
391
+ if (microphoneId) {
392
+ this.#microphoneId = microphoneId;
393
+ audio = { deviceId: microphoneId };
394
+ } else if (microphoneId === false) {
395
+ audio = false;
396
+ }
397
+ if (audioOnly || cameraId === false) {
398
+ video = false;
399
+ } else if (cameraId) {
400
+ this.#cameraId = cameraId;
401
+ video = screenShare || keepScreenShare ? false : { deviceId: cameraId };
402
+ }
403
+ const newStream = await getUserStream({ audio, video });
404
+ if (screenShare) {
405
+ const screenShareTrack = await this.createScreenShareStream(screenShare);
406
+ if (screenShareTrack) {
407
+ const { frameRate = DEFAULT_FRAME_RATE } = screenShare;
408
+ try {
409
+ await screenShareTrack.applyConstraints({
410
+ frameRate: { exact: frameRate }
411
+ });
412
+ } catch (e) {
413
+ this.handleScreenShareConstraintsError(frameRate);
414
+ }
415
+ newStream.addTrack(screenShareTrack);
416
+ }
417
+ this.#screenShareTrack = screenShareTrack;
418
+ } else if (keepScreenShare && this.#screenShareTrack) {
419
+ newStream.addTrack(this.#screenShareTrack);
420
+ }
421
+ this.replaceStream(newStream, keepScreenShare);
422
+ if (this.#muted) {
423
+ this.setMicMuted(true);
424
+ }
425
+ }
354
426
  setMicMuted(muted) {
355
427
  this.tracerLog("setMicMuted", { m: muted });
356
- this.muted = muted;
357
- this.stream?.getAudioTracks().forEach((track) => {
428
+ this.#muted = muted;
429
+ this.#stream?.getAudioTracks().forEach((track) => {
358
430
  track.enabled = !muted;
359
431
  });
360
432
  }
361
433
  setCameraEnabled(enabled) {
362
434
  this.tracerLog("setCameraEnabled", { on: enabled });
363
- this.stream?.getVideoTracks().forEach((track) => {
435
+ this.#stream?.getVideoTracks().forEach((track) => {
364
436
  track.enabled = enabled;
365
437
  });
366
438
  }
367
439
  destroy() {
368
- this.destroying = true;
440
+ this.#destroying = true;
369
441
  this.tracerLog("destroy");
370
442
  this.disconnect();
371
- this.cameraId = undefined;
372
- this.microphoneId = undefined;
373
- this.muted = false;
374
- if (this.stream) {
375
- this.stream.getTracks().forEach((track) => track.stop());
376
- this.stream = undefined;
377
- this.screenShareTrack = null;
443
+ this.#cameraId = undefined;
444
+ this.#microphoneId = undefined;
445
+ this.#muted = false;
446
+ if (this.#stream) {
447
+ this.#stream.getTracks().forEach((track) => track.stop());
448
+ this.#stream = undefined;
449
+ this.#screenShareTrack = null;
378
450
  }
379
451
  }
380
452
  disconnect() {
@@ -386,26 +458,26 @@ class WebRTCStreamer {
386
458
  }
387
459
  }
388
460
  replaceStream(stream, keepScreenShare = false) {
389
- this.stream?.getTracks().forEach((track) => {
461
+ this.#stream?.getTracks().forEach((track) => {
390
462
  const isScreenShare = track.contentHint === SCREEN_SHARE_CONTENT_TEXTHINT;
391
463
  if (!isScreenShare || !keepScreenShare) {
392
464
  track.stop();
393
465
  if (isScreenShare) {
394
- this.screenShareTrack = null;
466
+ this.#screenShareTrack = null;
395
467
  }
396
468
  }
397
- this.stream?.removeTrack(track);
469
+ this.#stream?.removeTrack(track);
398
470
  });
399
- this.stream = stream;
471
+ this.#stream = stream;
400
472
  this.tracerLog("streamChanged", serializeStream(stream));
401
- this.callback("onStreamChanged", this.stream);
402
- this.replaceTracksInPeerConnection(this.stream);
473
+ this.callback("onStreamChanged", this.#stream);
474
+ this.replaceTracksInPeerConnection(this.#stream);
403
475
  }
404
476
  replaceTracksInPeerConnection(stream, keepScreenShare = false) {
405
- if (!this.peerConnection) {
477
+ if (!this.#peerConnection) {
406
478
  return;
407
479
  }
408
- this.peerConnection.getTransceivers().forEach(({ sender }) => {
480
+ this.#peerConnection.getTransceivers().forEach(({ sender }) => {
409
481
  const { track } = sender;
410
482
  if (track && (track.contentHint !== SCREEN_SHARE_CONTENT_TEXTHINT || !keepScreenShare)) {
411
483
  track.stop();
@@ -418,7 +490,7 @@ class WebRTCStreamer {
418
490
  });
419
491
  }
420
492
  get socketOpened() {
421
- return this.ws?.readyState === WebSocket.OPEN;
493
+ return this.#ws?.readyState === WebSocket.OPEN;
422
494
  }
423
495
  async createScreenShareStream(screenShare) {
424
496
  const { width, height, onEnded = null } = screenShare;
@@ -427,25 +499,25 @@ class WebRTCStreamer {
427
499
  if (screenShareTrack) {
428
500
  screenShareTrack.contentHint = SCREEN_SHARE_CONTENT_TEXTHINT;
429
501
  screenShareTrack.onended = () => {
430
- this.screenShareTrack = null;
502
+ this.#screenShareTrack = null;
431
503
  onEnded?.();
432
504
  };
433
505
  }
434
506
  return screenShareTrack;
435
507
  }
436
508
  openSocket() {
437
- if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
438
- this.ws = new WebSocket(this.config.serverUrl ?? DEFAULT_WS_SERVER);
439
- this.ws.onopen = this.handleWSOpen;
440
- this.ws.onmessage = this.handleWSMessage;
441
- this.ws.onclose = this.handleWSClose;
509
+ if (!this.#ws || this.#ws.readyState === WebSocket.CLOSED) {
510
+ this.#ws = new WebSocket(this.config.serverUrl ?? DEFAULT_WS_SERVER);
511
+ this.#ws.onopen = this.handleWSOpen;
512
+ this.#ws.onmessage = this.handleWSMessage;
513
+ this.#ws.onclose = this.handleWSClose;
442
514
  }
443
515
  }
444
516
  handleWSOpen = () => {
445
517
  this.sendMessageFromQueue();
446
518
  };
447
519
  handleWSMessage = (event) => {
448
- if (this.destroying || !this.ws || this.ws.readyState >= WebSocket.CLOSING) {
520
+ if (this.#destroying || !this.#ws || this.#ws.readyState >= WebSocket.CLOSING) {
449
521
  return;
450
522
  }
451
523
  const message = this.parseMessage(event.data);
@@ -463,26 +535,27 @@ class WebRTCStreamer {
463
535
  };
464
536
  handleWSClose = (event) => {
465
537
  this.closePeerConnection();
466
- if (!this.ws) {
538
+ if (!this.#ws) {
467
539
  return;
468
540
  }
469
- this.messagesQueue = [];
470
- this.connected = false;
471
- this.ws = undefined;
541
+ const isAbnormalClose = event.code > 1000;
542
+ this.#messagesQueue = [];
543
+ this.#connected = false;
544
+ this.#ws = undefined;
472
545
  this.tracerLog("disconnected", { code: event.code });
473
- this.callback("onDisconnected", event);
546
+ this.callback("onDisconnected", isAbnormalClose ? "connection" /* CONNECTION */ : undefined);
474
547
  };
475
548
  send(message) {
476
- this.messagesQueue.push(message);
549
+ this.#messagesQueue.push(message);
477
550
  if (this.socketOpened) {
478
551
  this.sendMessageFromQueue();
479
552
  }
480
553
  }
481
554
  sendMessageFromQueue() {
482
- while (this.messagesQueue.length > 0) {
555
+ while (this.#messagesQueue.length > 0) {
483
556
  if (this.socketOpened) {
484
- const message = this.messagesQueue.shift();
485
- this.ws?.send(JSON.stringify(message));
557
+ const message = this.#messagesQueue.shift();
558
+ this.#ws?.send(JSON.stringify(message));
486
559
  }
487
560
  }
488
561
  }
@@ -508,10 +581,14 @@ class WebRTCStreamer {
508
581
  }
509
582
  }
510
583
  handleAnswer(sdp) {
511
- this.peerConnection?.setRemoteDescription(new RTCSessionDescription({ type: "answer", sdp }));
584
+ this.#peerConnection?.setRemoteDescription(new RTCSessionDescription({ type: "answer", sdp }));
512
585
  }
513
586
  handleCandidate(candidate) {
514
- this.peerConnection?.addIceCandidate(new RTCIceCandidate(candidate));
587
+ this.#peerConnection?.addIceCandidate(new RTCIceCandidate(candidate));
588
+ }
589
+ handleScreenShareConstraintsError(frameRate) {
590
+ this.tracerLog("error", { type: "constraints" /* CONSTRAINTS */, frameRate });
591
+ this.callback("onError", "constraints" /* CONSTRAINTS */);
515
592
  }
516
593
  handleError(err, message) {
517
594
  if (["no_stream_data" /* NO_STREAM_DATA */, "peerconnection" /* PEERCONNECTION */].includes(err)) {
@@ -523,22 +600,27 @@ class WebRTCStreamer {
523
600
  this.callback("onError", err, reason);
524
601
  }
525
602
  async createPeerConnection() {
526
- this.peerConnection = new RTCPeerConnection({
527
- iceServers: this.config.stunServers ?? DEFAULT_STUN_SERVERS,
528
- rtcpMuxPolicy: "require",
529
- bundlePolicy: "max-compat"
530
- });
531
- this.peerConnection.onicecandidate = this.handleRTCIceCandidate;
532
- this.peerConnection.onsignalingstatechange = this.handleRTCSignalingStateChange;
533
- this.peerConnection.oniceconnectionstatechange = this.handleRTCIceConnectionStateChange;
534
- this.stream?.getTracks().forEach((track) => {
535
- if (track.kind === "video") {
536
- track.contentHint = "text";
537
- }
538
- this.stream && this.peerConnection?.addTrack(track, this.stream);
539
- });
540
603
  try {
541
- const offer = await this.peerConnection.createOffer();
604
+ this.#peerConnection = new RTCPeerConnection({
605
+ iceServers: this.config.stunServers ?? DEFAULT_STUN_SERVERS,
606
+ rtcpMuxPolicy: "require",
607
+ bundlePolicy: "max-compat"
608
+ });
609
+ this.#peerConnection.onicecandidate = this.handleRTCIceCandidate;
610
+ this.#peerConnection.onsignalingstatechange = this.handleRTCSignalingStateChange;
611
+ this.#peerConnection.oniceconnectionstatechange = this.handleRTCIceConnectionStateChange;
612
+ this.#stream?.getTracks().forEach((track) => {
613
+ if (track.kind === "video") {
614
+ track.contentHint = "text";
615
+ }
616
+ this.#stream && this.#peerConnection?.addTrack(track, this.#stream);
617
+ });
618
+ } catch (e) {
619
+ this.handleError("peerconnection" /* PEERCONNECTION */, "create peer connection failed");
620
+ return;
621
+ }
622
+ try {
623
+ const offer = await this.#peerConnection.createOffer();
542
624
  if (this.config.lockOrientation) {
543
625
  offer.sdp = offer.sdp?.replace(/a=extmap:[0-9]+ urn:3gpp:video-orientation[\r\n]+/g, "");
544
626
  }
@@ -561,12 +643,12 @@ class WebRTCStreamer {
561
643
  }
562
644
  };
563
645
  handleRTCSignalingStateChange = () => {
564
- if (!this.peerConnection) {
646
+ if (!this.#peerConnection) {
565
647
  return;
566
648
  }
567
- switch (this.peerConnection.signalingState) {
649
+ switch (this.#peerConnection.signalingState) {
568
650
  case "have-local-offer":
569
- const sdp = this.peerConnection.localDescription?.sdp;
651
+ const sdp = this.#peerConnection.localDescription?.sdp;
570
652
  this.send({
571
653
  type: "INVITE",
572
654
  inviteType: "OFFER",
@@ -581,10 +663,10 @@ class WebRTCStreamer {
581
663
  }
582
664
  };
583
665
  handleRTCIceConnectionStateChange = () => {
584
- if (!this.peerConnection) {
666
+ if (!this.#peerConnection) {
585
667
  return;
586
668
  }
587
- switch (this.peerConnection.iceConnectionState) {
669
+ switch (this.#peerConnection.iceConnectionState) {
588
670
  case "failed":
589
671
  this.handleError("peerconnection" /* PEERCONNECTION */, "ice connection failed");
590
672
  break;
@@ -592,7 +674,7 @@ class WebRTCStreamer {
592
674
  this.disconnect();
593
675
  break;
594
676
  case "connected":
595
- this.connected = true;
677
+ this.#connected = true;
596
678
  this.tracerLog("connected");
597
679
  this.callback("onConnected");
598
680
  break;
@@ -600,22 +682,22 @@ class WebRTCStreamer {
600
682
  };
601
683
  async setDescription(description) {
602
684
  try {
603
- await this.peerConnection?.setLocalDescription(description);
685
+ await this.#peerConnection?.setLocalDescription(description);
604
686
  } catch (e) {
605
687
  this.handleError("peerconnection" /* PEERCONNECTION */, "set local description failed");
606
688
  }
607
689
  }
608
690
  closePeerConnection() {
609
- if (this.peerConnection) {
610
- if (this.peerConnection.signalingState !== "closed") {
611
- this.peerConnection.close();
691
+ if (this.#peerConnection) {
692
+ if (this.#peerConnection.signalingState !== "closed") {
693
+ this.#peerConnection.close();
612
694
  }
613
- this.peerConnection = undefined;
695
+ this.#peerConnection = undefined;
614
696
  }
615
697
  }
616
698
  closeWSConnection() {
617
- if (this.ws && this.ws.readyState < WebSocket.CLOSING) {
618
- this.ws.close(WS_CLOSE_CODE);
699
+ if (this.#ws && this.#ws.readyState < WebSocket.CLOSING) {
700
+ this.#ws.close(WS_CLOSE_CODE);
619
701
  }
620
702
  }
621
703
  parseMessage(data) {
@@ -628,6 +710,9 @@ class WebRTCStreamer {
628
710
  tracerLog(event, data) {
629
711
  return this.config.tracer?.log(event, flattenObject(data));
630
712
  }
713
+ logStat(event, data) {
714
+ this.config.statisticsLogger?.log(event, data);
715
+ }
631
716
  }
632
717
  __legacyDecorateClassTS([
633
718
  WebRTCStreamer.notDestroying
@@ -647,6 +732,9 @@ __legacyDecorateClassTS([
647
732
  __legacyDecorateClassTS([
648
733
  WebRTCStreamer.notDestroying
649
734
  ], WebRTCStreamer.prototype, "disableScreenShare", null);
735
+ __legacyDecorateClassTS([
736
+ WebRTCStreamer.notDestroying
737
+ ], WebRTCStreamer.prototype, "switchMediaDevices", null);
650
738
  __legacyDecorateClassTS([
651
739
  WebRTCStreamer.notDestroying
652
740
  ], WebRTCStreamer.prototype, "setMicMuted", null);
@@ -656,13 +744,18 @@ __legacyDecorateClassTS([
656
744
  __legacyDecorateClassTS([
657
745
  WebRTCStreamer.notDestroying
658
746
  ], WebRTCStreamer.prototype, "destroy", null);
747
+
748
+ // src/index.ts
749
+ var MediaUtils = { enumerateDevices, getUserStream };
659
750
  export {
660
751
  WebRTCStreamer,
661
752
  VERSION,
662
753
  StreamerError,
754
+ PermissionName,
755
+ MediaUtils,
663
756
  MediaErrorType
664
757
  };
665
758
 
666
- //# debugId=281C5760B351F83D64756E2164756E21
759
+ //# debugId=1BADA26CFC6F2DA564756E2164756E21
667
760
 
668
761
  //# sourceMappingURL=media-streaming.esm.js.map