@vkontakte/media-streaming 1.0.1-dev.7c4e0d2.0

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.
Files changed (2) hide show
  1. package/esnext.cjs +709 -0
  2. package/package.json +27 -0
package/esnext.cjs ADDED
@@ -0,0 +1,709 @@
1
+ /**
2
+ * @vkontakte/media-streaming v1.0.1-dev.7c4e0d2.0
3
+ * Mon, 03 Aug 2026 09:18:14 GMT
4
+ */
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ function __accessProp(key) {
10
+ return this[key];
11
+ }
12
+ var __toCommonJS = (from) => {
13
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
14
+ if (entry)
15
+ return entry;
16
+ entry = __defProp({}, "__esModule", { value: true });
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (var key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(entry, key))
20
+ __defProp(entry, key, {
21
+ get: __accessProp.bind(from, key),
22
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
23
+ });
24
+ }
25
+ __moduleCache.set(from, entry);
26
+ return entry;
27
+ };
28
+ var __moduleCache;
29
+ var __returnValue = (v) => v;
30
+ function __exportSetter(name, newValue) {
31
+ this[name] = __returnValue.bind(null, newValue);
32
+ }
33
+ var __export = (target, all) => {
34
+ for (var name in all)
35
+ __defProp(target, name, {
36
+ get: all[name],
37
+ enumerable: true,
38
+ configurable: true,
39
+ set: __exportSetter.bind(all, name)
40
+ });
41
+ };
42
+ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
43
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
44
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
45
+ r = Reflect.decorate(decorators, target, key, desc);
46
+ else
47
+ for (var i = decorators.length - 1;i >= 0; i--)
48
+ if (d = decorators[i])
49
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
50
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
51
+ };
52
+
53
+ // src/index.ts
54
+ var exports_src = {};
55
+ __export(exports_src, {
56
+ WebRTCStreamer: () => WebRTCStreamer,
57
+ VERSION: () => VERSION,
58
+ StreamerError: () => StreamerError,
59
+ MediaErrorType: () => MediaErrorType
60
+ });
61
+ module.exports = __toCommonJS(exports_src);
62
+
63
+ // src/env.ts
64
+ var VERSION = "1.0.1-dev.7c4e0d2.0";
65
+ // src/constants.ts
66
+ var DEFAULT_STUN_SERVERS = [{ urls: ["stun:videostun.mycdn.me:19302"] }];
67
+ var DEFAULT_WS_SERVER = "wss://ovsu.mycdn.me/publish";
68
+ var WS_CLOSE_CODE = 1000;
69
+ var DEFAULT_FRAME_RATE = 15;
70
+ var SCREEN_SHARE_CONTENT_TEXTHINT = "text";
71
+ var MediaErrorType;
72
+ ((MediaErrorType2) => {
73
+ MediaErrorType2["UNKNOWN"] = "unknown";
74
+ MediaErrorType2["ACCESS"] = "access";
75
+ MediaErrorType2["PERMISSION"] = "permission";
76
+ MediaErrorType2["DEVICES_NOT_FOUND"] = "devices_not_found";
77
+ MediaErrorType2["DEVICES_NOT_SUPPORTED"] = "devices_not_supported";
78
+ })(MediaErrorType ||= {});
79
+ var StreamerError;
80
+ ((StreamerError2) => {
81
+ StreamerError2["SOCKET"] = "socket";
82
+ StreamerError2["CONNECTION"] = "connection";
83
+ StreamerError2["NO_STREAM_DATA"] = "no_stream_data";
84
+ StreamerError2["PEERCONNECTION"] = "peerconnection";
85
+ StreamerError2["CONSTRAINTS"] = "constraints";
86
+ })(StreamerError ||= {});
87
+ // src/WebRTCStreamer.ts
88
+ var import_videoplayer_shared = require("@vkontakte/videoplayer-shared");
89
+
90
+ // src/MediaConstraints.ts
91
+ class MediaConstraints {
92
+ config;
93
+ audio;
94
+ video;
95
+ constructor(config) {
96
+ this.config = config;
97
+ this.audio = false;
98
+ this.video = false;
99
+ const { audio, video } = this.config;
100
+ if (audio) {
101
+ const deviceId = typeof audio === "boolean" ? null : audio.deviceId;
102
+ this.audio = deviceId ? { deviceId: { exact: deviceId } } : true;
103
+ }
104
+ if (video) {
105
+ const videoConfig = typeof video === "boolean" ? {} : video;
106
+ const { minWidth, maxWidth, minHeight, maxHeight, aspectRatio, deviceId, facingMode } = videoConfig;
107
+ this.video = {
108
+ width: { min: minWidth, max: maxWidth || 3840, ideal: 1920 },
109
+ height: { min: minHeight, max: maxHeight || 2160, ideal: 1080 },
110
+ aspectRatio: { ideal: aspectRatio || 16 / 9 }
111
+ };
112
+ if (facingMode) {
113
+ this.video.facingMode = { exact: facingMode };
114
+ } else if (deviceId) {
115
+ this.video.deviceId = { exact: deviceId };
116
+ }
117
+ }
118
+ }
119
+ getNative() {
120
+ return Object.assign({}, { audio: this.audio, video: this.video });
121
+ }
122
+ }
123
+
124
+ // src/MediaError.ts
125
+ class MediaError2 extends Error {
126
+ constructor(name, message) {
127
+ super(message);
128
+ this.name = name;
129
+ }
130
+ }
131
+
132
+ // src/utils.ts
133
+ var getWindow = () => {
134
+ return globalThis;
135
+ };
136
+ var getSafariVersion = (userAgent) => {
137
+ const ua = userAgent ?? (typeof navigator !== "undefined" ? navigator.userAgent : "");
138
+ if (!ua) {
139
+ return;
140
+ }
141
+ const isSafari = /webkit/i.test(ua) && /safari/i.test(ua) && !/chrome|crios|chromium|yabrowser|samsungbrowser|opr\/|edg/i.test(ua);
142
+ if (!isSafari) {
143
+ return;
144
+ }
145
+ const versionMatch = ua.match(/Version\/(\d+)/);
146
+ if (!versionMatch) {
147
+ return;
148
+ }
149
+ const version = parseInt(versionMatch[1], 10);
150
+ return isNaN(version) ? undefined : version;
151
+ };
152
+ var enumerateDevices = async () => await getWindow().navigator.mediaDevices.enumerateDevices();
153
+ var getUserMedia = (constraints) => getWindow().navigator.mediaDevices.getUserMedia(constraints).catch((e) => {
154
+ if (e instanceof Error) {
155
+ switch (e.name) {
156
+ case "PermissionDismissedError":
157
+ case "PermissionDeniedError":
158
+ case "SecurityError":
159
+ case "NotAllowedError":
160
+ case "DOMException":
161
+ throw new MediaError2(e.name, "permission" /* PERMISSION */);
162
+ case "OverconstrainedError":
163
+ case "NotFoundError":
164
+ case "TypeError":
165
+ throw new MediaError2(e.name, "unknown" /* UNKNOWN */);
166
+ case "AbortError":
167
+ case "NotReadableError":
168
+ throw new MediaError2(e.name, "access" /* ACCESS */);
169
+ default:
170
+ throw new MediaError2(e.name, "unknown" /* UNKNOWN */);
171
+ }
172
+ }
173
+ throw new Error("unknown");
174
+ });
175
+ var getDisplayMedia = (constraints) => getWindow().navigator.mediaDevices.getDisplayMedia(constraints.getNative()).catch((e) => {
176
+ if (e instanceof Error) {
177
+ switch (e.name) {
178
+ case "PermissionDeniedError":
179
+ case "SecurityError":
180
+ case "NotAllowedError":
181
+ throw new Error("permission");
182
+ default:
183
+ throw new Error("access");
184
+ }
185
+ }
186
+ throw new Error("unknown");
187
+ });
188
+ var omitKeys = (data, keys) => {
189
+ return Object.fromEntries(Object.entries(data).filter(([k]) => !keys.includes(k)));
190
+ };
191
+ var serializeTrack = (track) => {
192
+ return {
193
+ on: track.enabled,
194
+ k: track.kind,
195
+ ...track.contentHint && { h: track.contentHint }
196
+ };
197
+ };
198
+ var serializeStream = (stream) => {
199
+ return {
200
+ t: stream.getTracks().map(serializeTrack)
201
+ };
202
+ };
203
+ var serializeConfig = (cfg) => {
204
+ return {
205
+ key: cfg.streamKey,
206
+ ...cfg.audioOnly && { audioOnly: true },
207
+ ...cfg.lockOrientation && { lockOrientation: true },
208
+ ...cfg.mediaConstraints && { mediaConstraints: omitKeys(cfg.mediaConstraints, ["getNative"]) },
209
+ ...cfg.screenShare && { screenShare: omitKeys(cfg.screenShare, ["onEnded"]) }
210
+ };
211
+ };
212
+ var serializeMediaDevices = (devices) => {
213
+ return devices.map((d) => ({
214
+ id: d.deviceId.slice(0, 8),
215
+ kind: d.kind,
216
+ label: d.label
217
+ }));
218
+ };
219
+
220
+ // src/ScreenConstraints.ts
221
+ class ScreenConstraints extends MediaConstraints {
222
+ constructor({ width, height, frameRate = DEFAULT_FRAME_RATE }) {
223
+ super({
224
+ video: true,
225
+ audio: false
226
+ });
227
+ if (typeof this.video === "object") {
228
+ delete this.video.deviceId;
229
+ delete this.video.aspectRatio;
230
+ delete this.video.frameRate;
231
+ delete this.video.facingMode;
232
+ } else {
233
+ this.video = {};
234
+ }
235
+ this.video.cursor = "motion";
236
+ this.video.width = width;
237
+ this.video.height = height;
238
+ this.video.frameRate = frameRate;
239
+ if (getSafariVersion() === 16) {
240
+ this.video.width = { max: width };
241
+ this.video.height = { max: height };
242
+ }
243
+ }
244
+ }
245
+
246
+ // src/WebRTCStreamer.ts
247
+ class WebRTCStreamer {
248
+ config;
249
+ messagesQueue = [];
250
+ ws;
251
+ peerConnection;
252
+ stream;
253
+ screenShareTrack = null;
254
+ connected = false;
255
+ destroying = false;
256
+ cameraId;
257
+ microphoneId;
258
+ muted = false;
259
+ static notDestroying(_target, _propertyKey, descriptor) {
260
+ const original = descriptor.value;
261
+ descriptor.value = function(...args) {
262
+ if (this.destroying) {
263
+ return;
264
+ }
265
+ return original.apply(this, args);
266
+ };
267
+ return descriptor;
268
+ }
269
+ constructor(config) {
270
+ this.config = config;
271
+ }
272
+ callback(name, ...args) {
273
+ const fn = this.config.callbacks[name];
274
+ if (fn && !this.destroying) {
275
+ fn?.(...args);
276
+ }
277
+ }
278
+ async init() {
279
+ this.tracerLog("init", {
280
+ cfg: serializeConfig(this.config),
281
+ d: serializeMediaDevices(await enumerateDevices())
282
+ });
283
+ let permissionName = "user_media" /* USER_MEDIA */;
284
+ const { audioOnly, mediaConstraints, screenShare } = this.config;
285
+ try {
286
+ const constraints = mediaConstraints || new MediaConstraints({
287
+ audio: true,
288
+ video: !screenShare && !audioOnly
289
+ });
290
+ this.stream = await getUserMedia(constraints.getNative());
291
+ if (!audioOnly && screenShare) {
292
+ permissionName = "display_media" /* DISPLAY_MEDIA */;
293
+ const screenShareTrack = await this.createScreenShareStream(screenShare);
294
+ if (screenShareTrack) {
295
+ const { frameRate = DEFAULT_FRAME_RATE } = screenShare;
296
+ try {
297
+ await screenShareTrack.applyConstraints({
298
+ frameRate: { exact: frameRate }
299
+ });
300
+ } catch (e) {
301
+ this.tracerLog("error", { type: "constraints" /* CONSTRAINTS */ });
302
+ this.callback("onError", "constraints" /* CONSTRAINTS */);
303
+ }
304
+ this.stream.addTrack(screenShareTrack);
305
+ }
306
+ this.screenShareTrack = screenShareTrack;
307
+ }
308
+ this.tracerLog("streamChanged", serializeStream(this.stream));
309
+ this.callback("onStreamChanged", this.stream);
310
+ } catch (err) {
311
+ if (err instanceof MediaError) {
312
+ this.tracerLog("permissionFailed", { name: permissionName, msg: err.message, code: err.code });
313
+ this.callback("onPermissionFailed", permissionName, err);
314
+ } else {
315
+ this.tracerLog("permissionFailed", { name: permissionName });
316
+ this.callback("onPermissionFailed", permissionName);
317
+ }
318
+ }
319
+ }
320
+ async connect() {
321
+ this.tracerLog("connect");
322
+ this.openSocket();
323
+ if (!this.peerConnection) {
324
+ await this.createPeerConnection();
325
+ }
326
+ }
327
+ async switchCamera(deviceId) {
328
+ const { audioOnly } = this.config;
329
+ this.tracerLog("switchCamera", { id: deviceId, audioOnly });
330
+ if (audioOnly) {
331
+ return;
332
+ }
333
+ this.cameraId = deviceId;
334
+ const constraints = new MediaConstraints({
335
+ audio: this.microphoneId ? {
336
+ deviceId: this.microphoneId
337
+ } : true,
338
+ video: {
339
+ deviceId: this.cameraId
340
+ }
341
+ });
342
+ const newStream = await getUserMedia(constraints.getNative());
343
+ this.replaceStream(newStream);
344
+ if (this.muted) {
345
+ this.setMicMuted(true);
346
+ }
347
+ }
348
+ async switchMicrophone(deviceId) {
349
+ this.tracerLog("switchMicrophone", { id: deviceId });
350
+ this.microphoneId = deviceId;
351
+ const constraints = new MediaConstraints({
352
+ audio: {
353
+ deviceId: this.microphoneId
354
+ },
355
+ video: this.screenShareTrack ? false : this.cameraId ? {
356
+ deviceId: this.cameraId
357
+ } : true
358
+ });
359
+ const newStream = await getUserMedia(constraints.getNative());
360
+ if (this.screenShareTrack) {
361
+ newStream.addTrack(this.screenShareTrack);
362
+ }
363
+ this.replaceStream(newStream, true);
364
+ if (this.muted) {
365
+ this.setMicMuted(true);
366
+ }
367
+ }
368
+ async enableScreenShare(config) {
369
+ this.tracerLog("enableScreenShare", omitKeys(config, ["onEnded"]));
370
+ const constraints = new MediaConstraints({
371
+ audio: this.microphoneId ? { deviceId: this.microphoneId } : true,
372
+ video: false
373
+ });
374
+ const newStream = await getUserMedia(constraints.getNative());
375
+ const screenShareTrack = await this.createScreenShareStream(config);
376
+ if (screenShareTrack) {
377
+ const { frameRate = DEFAULT_FRAME_RATE } = config;
378
+ await screenShareTrack.applyConstraints({
379
+ frameRate: { exact: frameRate }
380
+ });
381
+ newStream.addTrack(screenShareTrack);
382
+ }
383
+ this.screenShareTrack = screenShareTrack;
384
+ this.replaceStream(newStream);
385
+ if (this.muted) {
386
+ this.setMicMuted(true);
387
+ }
388
+ }
389
+ async disableScreenShare(cameraDeviceId) {
390
+ this.tracerLog("disableScreenShare", cameraDeviceId ? { cid: cameraDeviceId } : undefined);
391
+ if (cameraDeviceId) {
392
+ await this.switchCamera(cameraDeviceId);
393
+ } else {
394
+ const devices = await enumerateDevices();
395
+ const defaultCamera = devices.find((d) => d.kind === "videoinput");
396
+ if (defaultCamera) {
397
+ await this.switchCamera(defaultCamera.deviceId);
398
+ }
399
+ }
400
+ }
401
+ setMicMuted(muted) {
402
+ this.tracerLog("setMicMuted", { m: muted });
403
+ this.muted = muted;
404
+ this.stream?.getAudioTracks().forEach((track) => {
405
+ track.enabled = !muted;
406
+ });
407
+ }
408
+ setCameraEnabled(enabled) {
409
+ this.tracerLog("setCameraEnabled", { on: enabled });
410
+ this.stream?.getVideoTracks().forEach((track) => {
411
+ track.enabled = enabled;
412
+ });
413
+ }
414
+ destroy() {
415
+ this.destroying = true;
416
+ this.tracerLog("destroy");
417
+ this.disconnect();
418
+ this.cameraId = undefined;
419
+ this.microphoneId = undefined;
420
+ this.muted = false;
421
+ if (this.stream) {
422
+ this.stream.getTracks().forEach((track) => track.stop());
423
+ this.stream = undefined;
424
+ this.screenShareTrack = null;
425
+ }
426
+ }
427
+ disconnect() {
428
+ this.tracerLog("disconnect");
429
+ this.closePeerConnection();
430
+ if (this.socketOpened) {
431
+ this.send({ type: "BYE" });
432
+ this.closeWSConnection();
433
+ }
434
+ }
435
+ replaceStream(stream, keepScreenShare = false) {
436
+ this.stream?.getTracks().forEach((track) => {
437
+ const isScreenShare = track.contentHint === SCREEN_SHARE_CONTENT_TEXTHINT;
438
+ if (!isScreenShare || !keepScreenShare) {
439
+ track.stop();
440
+ if (isScreenShare) {
441
+ this.screenShareTrack = null;
442
+ }
443
+ }
444
+ this.stream?.removeTrack(track);
445
+ });
446
+ this.stream = stream;
447
+ this.tracerLog("streamChanged", serializeStream(stream));
448
+ this.callback("onStreamChanged", this.stream);
449
+ this.replaceTracksInPeerConnection(this.stream);
450
+ }
451
+ replaceTracksInPeerConnection(stream, keepScreenShare = false) {
452
+ if (!this.peerConnection) {
453
+ return;
454
+ }
455
+ this.peerConnection.getTransceivers().forEach(({ sender }) => {
456
+ const { track } = sender;
457
+ if (track && (track.contentHint !== SCREEN_SHARE_CONTENT_TEXTHINT || !keepScreenShare)) {
458
+ track.stop();
459
+ }
460
+ stream.getTracks().forEach((newTrack) => {
461
+ if (track?.kind === newTrack.kind) {
462
+ sender.replaceTrack(newTrack).then(() => {}, () => {});
463
+ }
464
+ });
465
+ });
466
+ }
467
+ get socketOpened() {
468
+ return this.ws?.readyState === WebSocket.OPEN;
469
+ }
470
+ async createScreenShareStream(screenShare) {
471
+ const { width, height, onEnded = null } = screenShare;
472
+ const displayStream = await getDisplayMedia(new ScreenConstraints({ width, height }));
473
+ const screenShareTrack = displayStream ? displayStream.getVideoTracks()[0] : null;
474
+ if (screenShareTrack) {
475
+ screenShareTrack.contentHint = SCREEN_SHARE_CONTENT_TEXTHINT;
476
+ screenShareTrack.onended = () => {
477
+ this.screenShareTrack = null;
478
+ onEnded?.();
479
+ };
480
+ }
481
+ return screenShareTrack;
482
+ }
483
+ openSocket() {
484
+ if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
485
+ this.ws = new WebSocket(this.config.serverUrl ?? DEFAULT_WS_SERVER);
486
+ this.ws.onopen = this.handleWSOpen;
487
+ this.ws.onmessage = this.handleWSMessage;
488
+ this.ws.onclose = this.handleWSClose;
489
+ }
490
+ }
491
+ handleWSOpen = () => {
492
+ this.sendMessageFromQueue();
493
+ };
494
+ handleWSMessage = (event) => {
495
+ if (this.destroying || !this.ws || this.ws.readyState >= WebSocket.CLOSING) {
496
+ return;
497
+ }
498
+ const message = this.parseMessage(event.data);
499
+ switch (message.type) {
500
+ case "INVITE":
501
+ this.handleInviteMessage(message);
502
+ break;
503
+ case "ERROR":
504
+ this.handleError("socket" /* SOCKET */, message);
505
+ break;
506
+ case "STATUS":
507
+ this.handleStatusMessage(message);
508
+ break;
509
+ }
510
+ };
511
+ handleWSClose = (event) => {
512
+ this.closePeerConnection();
513
+ if (!this.ws) {
514
+ return;
515
+ }
516
+ this.messagesQueue = [];
517
+ this.connected = false;
518
+ this.ws = undefined;
519
+ this.tracerLog("disconnected", { code: event.code });
520
+ this.callback("onDisconnected", event);
521
+ };
522
+ send(message) {
523
+ this.messagesQueue.push(message);
524
+ if (this.socketOpened) {
525
+ this.sendMessageFromQueue();
526
+ }
527
+ }
528
+ sendMessageFromQueue() {
529
+ while (this.messagesQueue.length > 0) {
530
+ if (this.socketOpened) {
531
+ const message = this.messagesQueue.shift();
532
+ this.ws?.send(JSON.stringify(message));
533
+ }
534
+ }
535
+ }
536
+ handleStatusMessage(msg) {
537
+ const { status, message } = msg;
538
+ if (status === "INFO" && message === "no_stream_data") {
539
+ this.handleError("no_stream_data" /* NO_STREAM_DATA */, msg);
540
+ }
541
+ }
542
+ handleInviteMessage(message) {
543
+ switch (message.inviteType) {
544
+ case "ANSWER":
545
+ this.handleAnswer(message.sdp);
546
+ break;
547
+ case "CANDIDATE":
548
+ if (message.candidate) {
549
+ this.tracerLog("gotRTCCandidate", { v: message.candidate });
550
+ this.handleCandidate(message.candidate);
551
+ }
552
+ break;
553
+ default:
554
+ break;
555
+ }
556
+ }
557
+ handleAnswer(sdp) {
558
+ this.peerConnection?.setRemoteDescription(new RTCSessionDescription({ type: "answer", sdp }));
559
+ }
560
+ handleCandidate(candidate) {
561
+ this.peerConnection?.addIceCandidate(new RTCIceCandidate(candidate));
562
+ }
563
+ handleError(err, message) {
564
+ if (["no_stream_data" /* NO_STREAM_DATA */, "peerconnection" /* PEERCONNECTION */].includes(err)) {
565
+ this.closePeerConnection();
566
+ this.closeWSConnection();
567
+ }
568
+ const reason = message ? typeof message === "string" ? message : message.text ?? message.message : undefined;
569
+ this.tracerLog("error", { type: err, ...reason && { r: reason } });
570
+ this.callback("onError", err, reason);
571
+ }
572
+ async createPeerConnection() {
573
+ this.peerConnection = new RTCPeerConnection({
574
+ iceServers: this.config.stunServers ?? DEFAULT_STUN_SERVERS,
575
+ rtcpMuxPolicy: "require",
576
+ bundlePolicy: "max-compat"
577
+ });
578
+ this.peerConnection.onicecandidate = this.handleRTCIceCandidate;
579
+ this.peerConnection.onsignalingstatechange = this.handleRTCSignalingStateChange;
580
+ this.peerConnection.oniceconnectionstatechange = this.handleRTCIceConnectionStateChange;
581
+ this.stream?.getTracks().forEach((track) => {
582
+ if (track.kind === "video") {
583
+ track.contentHint = "text";
584
+ }
585
+ this.stream && this.peerConnection?.addTrack(track, this.stream);
586
+ });
587
+ try {
588
+ const offer = await this.peerConnection.createOffer();
589
+ if (this.config.lockOrientation) {
590
+ offer.sdp = offer.sdp?.replace(/a=extmap:[0-9]+ urn:3gpp:video-orientation[\r\n]+/g, "");
591
+ }
592
+ await this.setDescription(offer);
593
+ } catch (e) {
594
+ this.handleError("peerconnection" /* PEERCONNECTION */, "set offer description failed");
595
+ }
596
+ }
597
+ handleRTCIceCandidate = ({ candidate }) => {
598
+ if (candidate) {
599
+ this.tracerLog("sendRTCCandidate", { v: candidate.candidate });
600
+ this.send({
601
+ type: "INVITE",
602
+ promoCall: false,
603
+ inviteType: "CANDIDATE",
604
+ candidate
605
+ });
606
+ } else {
607
+ this.send({ type: "INVITE", promoCall: false, inviteType: "CANDIDATE" });
608
+ }
609
+ };
610
+ handleRTCSignalingStateChange = () => {
611
+ if (!this.peerConnection) {
612
+ return;
613
+ }
614
+ switch (this.peerConnection.signalingState) {
615
+ case "have-local-offer":
616
+ const sdp = this.peerConnection.localDescription?.sdp;
617
+ this.send({
618
+ type: "INVITE",
619
+ inviteType: "OFFER",
620
+ promoCall: false,
621
+ streamKey: this.config.streamKey,
622
+ sdp
623
+ });
624
+ break;
625
+ case "closed":
626
+ this.handleError("peerconnection" /* PEERCONNECTION */, "signalling closed");
627
+ break;
628
+ }
629
+ };
630
+ handleRTCIceConnectionStateChange = () => {
631
+ if (!this.peerConnection) {
632
+ return;
633
+ }
634
+ switch (this.peerConnection.iceConnectionState) {
635
+ case "failed":
636
+ this.handleError("peerconnection" /* PEERCONNECTION */, "ice connection failed");
637
+ break;
638
+ case "disconnected":
639
+ this.disconnect();
640
+ break;
641
+ case "connected":
642
+ this.connected = true;
643
+ this.tracerLog("connected");
644
+ this.callback("onConnected");
645
+ break;
646
+ }
647
+ };
648
+ async setDescription(description) {
649
+ try {
650
+ await this.peerConnection?.setLocalDescription(description);
651
+ } catch (e) {
652
+ this.handleError("peerconnection" /* PEERCONNECTION */, "set local description failed");
653
+ }
654
+ }
655
+ closePeerConnection() {
656
+ if (this.peerConnection) {
657
+ if (this.peerConnection.signalingState !== "closed") {
658
+ this.peerConnection.close();
659
+ }
660
+ this.peerConnection = undefined;
661
+ }
662
+ }
663
+ closeWSConnection() {
664
+ if (this.ws && this.ws.readyState < WebSocket.CLOSING) {
665
+ this.ws.close(WS_CLOSE_CODE);
666
+ }
667
+ }
668
+ parseMessage(data) {
669
+ try {
670
+ return JSON.parse(data);
671
+ } catch (e) {
672
+ return { type: "EMPTY" };
673
+ }
674
+ }
675
+ tracerLog(event, data) {
676
+ return this.config.tracer?.log(event, import_videoplayer_shared.flattenObject(data));
677
+ }
678
+ }
679
+ __legacyDecorateClassTS([
680
+ WebRTCStreamer.notDestroying
681
+ ], WebRTCStreamer.prototype, "init", null);
682
+ __legacyDecorateClassTS([
683
+ WebRTCStreamer.notDestroying
684
+ ], WebRTCStreamer.prototype, "connect", null);
685
+ __legacyDecorateClassTS([
686
+ WebRTCStreamer.notDestroying
687
+ ], WebRTCStreamer.prototype, "switchCamera", null);
688
+ __legacyDecorateClassTS([
689
+ WebRTCStreamer.notDestroying
690
+ ], WebRTCStreamer.prototype, "switchMicrophone", null);
691
+ __legacyDecorateClassTS([
692
+ WebRTCStreamer.notDestroying
693
+ ], WebRTCStreamer.prototype, "enableScreenShare", null);
694
+ __legacyDecorateClassTS([
695
+ WebRTCStreamer.notDestroying
696
+ ], WebRTCStreamer.prototype, "disableScreenShare", null);
697
+ __legacyDecorateClassTS([
698
+ WebRTCStreamer.notDestroying
699
+ ], WebRTCStreamer.prototype, "setMicMuted", null);
700
+ __legacyDecorateClassTS([
701
+ WebRTCStreamer.notDestroying
702
+ ], WebRTCStreamer.prototype, "setCameraEnabled", null);
703
+ __legacyDecorateClassTS([
704
+ WebRTCStreamer.notDestroying
705
+ ], WebRTCStreamer.prototype, "destroy", null);
706
+
707
+ //# debugId=F692A4354B910EA964756E2164756E21
708
+
709
+ //# sourceMappingURL=esnext.cjs.map
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@vkontakte/media-streaming",
3
+ "version": "1.0.1-dev.7c4e0d2.0",
4
+ "author": "vk.com",
5
+ "description": "VK WebRTC media streaming module",
6
+ "homepage": "https://vk.com",
7
+ "license": "GPL-3.0",
8
+ "main": "esnext.cjs",
9
+ "module": "esnext.esm.js",
10
+ "types": "types/index.d.ts",
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./out/types/index.d.ts",
15
+ "import": "./out/esnext.esm.js",
16
+ "require": "./out/esnext.cjs"
17
+ }
18
+ },
19
+ "files": [
20
+ "out/esnext.esm.js",
21
+ "out/esnext.cjs",
22
+ "out/types/**/*.d.ts"
23
+ ],
24
+ "dependencies": {
25
+ "@vkontakte/videoplayer-shared": "^1.0.97"
26
+ }
27
+ }