@fishjam-cloud/webrtc-client 0.26.0 → 0.26.1-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -501,6 +501,8 @@ declare class ConnectionManager {
501
501
  isConnectionUnstable: () => boolean;
502
502
  getConnection: () => RTCPeerConnection;
503
503
  addTransceiversIfNeeded: (serverTracks: MediaEvent_OfferData_TrackTypes) => void;
504
+ private static isLiveRecvTransceiver;
505
+ private stopExcessRecvTransceivers;
504
506
  addTransceiver: (track: MediaStreamTrack, transceiverConfig: RTCRtpTransceiverInit) => void;
505
507
  setOnTrackReady: (onTrackReady: (event: RTCTrackEvent) => void) => void;
506
508
  setRemoteDescription: (data: RTCSessionDescriptionInit) => Promise<void>;
@@ -597,7 +599,9 @@ declare class WebRTCEndpoint extends WebRTCEndpoint_base {
597
599
  * webrtcChannel.on("mediaEvent", (event) => webrtc.receiveMediaEvent(event.data));
598
600
  * ```
599
601
  */
602
+ private mediaEventQueue;
600
603
  receiveMediaEvent: (mediaEvent: SerializedMediaEvent) => Promise<void>;
604
+ private handleConnected;
601
605
  private getEndpointId;
602
606
  private onTrackReady;
603
607
  /**
package/dist/index.mjs CHANGED
@@ -1484,7 +1484,7 @@ var CommandsQueue = class {
1484
1484
  };
1485
1485
 
1486
1486
  // src/ConnectionManager.ts
1487
- var ConnectionManager = class {
1487
+ var ConnectionManager = class _ConnectionManager {
1488
1488
  connection;
1489
1489
  constructor(iceServers) {
1490
1490
  this.connection = new RTCPeerConnection({
@@ -1504,15 +1504,29 @@ var ConnectionManager = class {
1504
1504
  return this.connection;
1505
1505
  };
1506
1506
  addTransceiversIfNeeded = (serverTracks) => {
1507
- const recvTransceivers = this.connection.getTransceivers().filter((elem) => elem.direction === "recvonly");
1507
+ const recvTransceivers = this.connection.getTransceivers().filter(_ConnectionManager.isLiveRecvTransceiver);
1508
1508
  const videoTransceiversAmount = recvTransceivers.filter((elem) => elem.receiver.track.kind === "video").length;
1509
1509
  const audioTransceiversAmount = recvTransceivers.filter((elem) => elem.receiver.track.kind === "audio").length;
1510
- const videoNeededTypes = Array(serverTracks.video - videoTransceiversAmount).fill("video");
1511
- const audioNeededTypes = Array(serverTracks.audio - audioTransceiversAmount).fill("audio");
1510
+ const videoDelta = serverTracks.video - videoTransceiversAmount;
1511
+ const audioDelta = serverTracks.audio - audioTransceiversAmount;
1512
+ this.stopExcessRecvTransceivers("video", -videoDelta);
1513
+ this.stopExcessRecvTransceivers("audio", -audioDelta);
1514
+ const videoNeededTypes = Array(Math.max(0, videoDelta)).fill("video");
1515
+ const audioNeededTypes = Array(Math.max(0, audioDelta)).fill("audio");
1512
1516
  [...videoNeededTypes, ...audioNeededTypes].forEach(
1513
1517
  (kind) => this.connection.addTransceiver(kind, { direction: "recvonly" })
1514
1518
  );
1515
1519
  };
1520
+ static isLiveRecvTransceiver = (t) => t.direction === "recvonly" && t.currentDirection !== "stopped";
1521
+ stopExcessRecvTransceivers = (kind, excess) => {
1522
+ if (excess <= 0) return;
1523
+ const candidates = this.connection.getTransceivers().filter((t) => _ConnectionManager.isLiveRecvTransceiver(t) && t.receiver.track?.kind === kind).sort((a, b) => {
1524
+ const aOrphan = a.mid === null ? 0 : 1;
1525
+ const bOrphan = b.mid === null ? 0 : 1;
1526
+ return aOrphan - bOrphan;
1527
+ });
1528
+ candidates.slice(0, excess).forEach((transceiver) => transceiver.stop());
1529
+ };
1516
1530
  addTransceiver = (track, transceiverConfig) => {
1517
1531
  this.connection.addTransceiver(track, transceiverConfig);
1518
1532
  };
@@ -4835,29 +4849,25 @@ var WebRTCEndpoint = class extends EventEmitter3 {
4835
4849
  * webrtcChannel.on("mediaEvent", (event) => webrtc.receiveMediaEvent(event.data));
4836
4850
  * ```
4837
4851
  */
4838
- receiveMediaEvent = async (mediaEvent) => {
4852
+ mediaEventQueue = Promise.resolve();
4853
+ receiveMediaEvent = (mediaEvent) => {
4839
4854
  const deserializedMediaEvent = deserializeServerMediaEvent(mediaEvent);
4840
- if (deserializedMediaEvent.connected) {
4841
- const connectedEvent = deserializedMediaEvent.connected;
4842
- this.proposedIceServers = connectedEvent.iceServers;
4843
- this.local.setLocalEndpointId(connectedEvent.endpointId);
4844
- const localEndpointMetadataJson = connectedEvent.endpointIdToEndpoint[connectedEvent.endpointId]?.metadataJson;
4845
- if (localEndpointMetadataJson) {
4846
- this.local.setEndpointMetadata(JSON.parse(localEndpointMetadataJson));
4847
- }
4848
- const connectedEndpoint = connectedEvent.endpointIdToEndpoint[connectedEvent.endpointId];
4849
- if (connectedEndpoint?.metadataJson) {
4850
- const parsedMetadata = JSON.parse(connectedEndpoint?.metadataJson);
4851
- this.local.setEndpointMetadata(parsedMetadata);
4852
- }
4853
- Object.entries(connectedEvent.endpointIdToEndpoint).filter(([endpointId]) => endpointId !== this.local.getEndpoint().id).forEach(([endpointId, endpoint]) => {
4854
- this.remote.addRemoteEndpoint(endpointId, endpoint.metadataJson, endpoint.trackIdToTrack);
4855
- });
4856
- const remoteEndpoints = Object.values(this.remote.getRemoteEndpoints());
4857
- this.emit("connected", this.local.getEndpoint().id, remoteEndpoints);
4858
- return;
4859
- }
4860
- if (this.getEndpointId()) await this.handleMediaEvent(deserializedMediaEvent);
4855
+ const next = this.mediaEventQueue.then(() => this.handleMediaEvent(deserializedMediaEvent));
4856
+ this.mediaEventQueue = next.catch(() => void 0);
4857
+ return next;
4858
+ };
4859
+ handleConnected = (connectedEvent) => {
4860
+ this.proposedIceServers = connectedEvent.iceServers;
4861
+ this.local.setLocalEndpointId(connectedEvent.endpointId);
4862
+ const localEndpoint = connectedEvent.endpointIdToEndpoint[connectedEvent.endpointId];
4863
+ if (localEndpoint?.metadataJson) {
4864
+ this.local.setEndpointMetadata(JSON.parse(localEndpoint.metadataJson));
4865
+ }
4866
+ Object.entries(connectedEvent.endpointIdToEndpoint).filter(([endpointId]) => endpointId !== this.local.getEndpoint().id).forEach(([endpointId, endpoint]) => {
4867
+ this.remote.addRemoteEndpoint(endpointId, endpoint.metadataJson, endpoint.trackIdToTrack);
4868
+ });
4869
+ const remoteEndpoints = Object.values(this.remote.getRemoteEndpoints());
4870
+ this.emit("connected", this.local.getEndpoint().id, remoteEndpoints);
4861
4871
  };
4862
4872
  getEndpointId = () => this.local.getEndpoint().id;
4863
4873
  onTrackReady = (event) => {
@@ -4906,6 +4916,11 @@ var WebRTCEndpoint = class extends EventEmitter3 {
4906
4916
  return this.dataChannelManager?.getChannelsReadiness() ?? false;
4907
4917
  }
4908
4918
  handleMediaEvent = async (event) => {
4919
+ if (event.connected) {
4920
+ this.handleConnected(event.connected);
4921
+ return;
4922
+ }
4923
+ if (!this.getEndpointId()) return;
4909
4924
  if (event.offerData) {
4910
4925
  await this.onOfferData(event.offerData);
4911
4926
  } else if (event.tracksAdded) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishjam-cloud/webrtc-client",
3
- "version": "0.26.0",
3
+ "version": "0.26.1-rc.1",
4
4
  "description": "Typescript client library for ExWebRTC/WebRTC endpoint in Membrane RTC Engine",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Fishjam Team",