werift 0.24.4 → 0.25.0-alpha.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 (166) hide show
  1. package/README.md +116 -113
  2. package/lib/common/src/transport.d.ts +22 -2
  3. package/lib/common/src/transport.js +84 -26
  4. package/lib/common/src/transport.js.map +1 -1
  5. package/lib/ice/src/exceptions.d.ts +9 -0
  6. package/lib/ice/src/exceptions.js +23 -1
  7. package/lib/ice/src/exceptions.js.map +1 -1
  8. package/lib/ice/src/ice.d.ts +40 -0
  9. package/lib/ice/src/ice.js +194 -28
  10. package/lib/ice/src/ice.js.map +1 -1
  11. package/lib/ice/src/iceBase.d.ts +26 -0
  12. package/lib/ice/src/iceBase.js.map +1 -1
  13. package/lib/ice/src/stun/const.d.ts +7 -0
  14. package/lib/ice/src/stun/const.js +8 -0
  15. package/lib/ice/src/stun/const.js.map +1 -1
  16. package/lib/ice/src/stun/protocol.js +1 -4
  17. package/lib/ice/src/stun/protocol.js.map +1 -1
  18. package/lib/ice/src/stun/tcpProtocol.d.ts +7 -1
  19. package/lib/ice/src/stun/tcpProtocol.js +65 -14
  20. package/lib/ice/src/stun/tcpProtocol.js.map +1 -1
  21. package/lib/ice/src/stun/transaction.d.ts +12 -1
  22. package/lib/ice/src/stun/transaction.js +37 -4
  23. package/lib/ice/src/stun/transaction.js.map +1 -1
  24. package/lib/ice/src/turn/protocol.d.ts +40 -15
  25. package/lib/ice/src/turn/protocol.js +141 -32
  26. package/lib/ice/src/turn/protocol.js.map +1 -1
  27. package/lib/ice/src/types/model.d.ts +8 -0
  28. package/lib/ice/src/types/model.js.map +1 -1
  29. package/lib/index.mjs +6175 -4073
  30. package/lib/nonstandard/index.mjs +286 -1003
  31. package/lib/polyfill/dom.mjs +23794 -0
  32. package/lib/polyfill/index.mjs +23794 -0
  33. package/lib/rtp/src/extra/container/mp4/container.js +12 -4
  34. package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
  35. package/lib/rtp/src/extra/processor/mp4.js +8 -3
  36. package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
  37. package/lib/rtp/src/extra/processor/mp4Callback.js +3 -1
  38. package/lib/rtp/src/extra/processor/mp4Callback.js.map +1 -1
  39. package/lib/sctp/src/chunk.d.ts +5 -0
  40. package/lib/sctp/src/chunk.js +16 -11
  41. package/lib/sctp/src/chunk.js.map +1 -1
  42. package/lib/sctp/src/index.d.ts +3 -1
  43. package/lib/sctp/src/index.js +10 -1
  44. package/lib/sctp/src/index.js.map +1 -1
  45. package/lib/sctp/src/sctp.d.ts +12 -3
  46. package/lib/sctp/src/sctp.js +51 -18
  47. package/lib/sctp/src/sctp.js.map +1 -1
  48. package/lib/webrtc/src/const.js +2 -0
  49. package/lib/webrtc/src/const.js.map +1 -1
  50. package/lib/webrtc/src/errors.d.ts +9 -1
  51. package/lib/webrtc/src/errors.js +19 -0
  52. package/lib/webrtc/src/errors.js.map +1 -1
  53. package/lib/webrtc/src/media/codec.d.ts +5 -0
  54. package/lib/webrtc/src/media/codec.js +21 -0
  55. package/lib/webrtc/src/media/codec.js.map +1 -1
  56. package/lib/webrtc/src/media/codecCompatibility.d.ts +23 -0
  57. package/lib/webrtc/src/media/codecCompatibility.js +138 -0
  58. package/lib/webrtc/src/media/codecCompatibility.js.map +1 -0
  59. package/lib/webrtc/src/media/index.d.ts +1 -0
  60. package/lib/webrtc/src/media/index.js +1 -0
  61. package/lib/webrtc/src/media/index.js.map +1 -1
  62. package/lib/webrtc/src/media/router.d.ts +2 -0
  63. package/lib/webrtc/src/media/router.js +23 -3
  64. package/lib/webrtc/src/media/router.js.map +1 -1
  65. package/lib/webrtc/src/media/rtpReceiver.d.ts +12 -0
  66. package/lib/webrtc/src/media/rtpReceiver.js +35 -0
  67. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  68. package/lib/webrtc/src/media/rtpSender.d.ts +65 -4
  69. package/lib/webrtc/src/media/rtpSender.js +264 -35
  70. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  71. package/lib/webrtc/src/media/rtpTransceiver.d.ts +42 -0
  72. package/lib/webrtc/src/media/rtpTransceiver.js +157 -4
  73. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  74. package/lib/webrtc/src/media/track.d.ts +29 -1
  75. package/lib/webrtc/src/media/track.js +164 -5
  76. package/lib/webrtc/src/media/track.js.map +1 -1
  77. package/lib/webrtc/src/nonstandard/index.d.ts +0 -1
  78. package/lib/webrtc/src/nonstandard/index.js +0 -1
  79. package/lib/webrtc/src/nonstandard/index.js.map +1 -1
  80. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +2 -1
  81. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
  82. package/lib/webrtc/src/nonstandard/userMedia.d.ts +1 -2
  83. package/lib/webrtc/src/nonstandard/userMedia.js +30 -14
  84. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  85. package/lib/webrtc/src/peerConnection.d.ts +126 -5
  86. package/lib/webrtc/src/peerConnection.js +609 -136
  87. package/lib/webrtc/src/peerConnection.js.map +1 -1
  88. package/lib/webrtc/src/polyfill/api.d.ts +14 -0
  89. package/lib/webrtc/src/polyfill/api.js +23 -0
  90. package/lib/webrtc/src/polyfill/api.js.map +1 -0
  91. package/lib/webrtc/src/polyfill/browserIdentity.d.ts +11 -0
  92. package/lib/webrtc/src/polyfill/browserIdentity.js +59 -0
  93. package/lib/webrtc/src/polyfill/browserIdentity.js.map +1 -0
  94. package/lib/webrtc/src/polyfill/dom.d.ts +11 -0
  95. package/lib/webrtc/src/polyfill/dom.js +18 -0
  96. package/lib/webrtc/src/polyfill/dom.js.map +1 -0
  97. package/lib/webrtc/src/polyfill/existingMediaDevices.d.ts +2 -0
  98. package/lib/webrtc/src/polyfill/existingMediaDevices.js +22 -0
  99. package/lib/webrtc/src/polyfill/existingMediaDevices.js.map +1 -0
  100. package/lib/webrtc/src/polyfill/globals.d.ts +28 -0
  101. package/lib/webrtc/src/polyfill/globals.js +3 -0
  102. package/lib/webrtc/src/polyfill/globals.js.map +1 -0
  103. package/lib/webrtc/src/polyfill/index.d.ts +2 -0
  104. package/lib/webrtc/src/polyfill/index.js +19 -0
  105. package/lib/webrtc/src/polyfill/index.js.map +1 -0
  106. package/lib/webrtc/src/polyfill/install.d.ts +13 -0
  107. package/lib/webrtc/src/polyfill/install.js +266 -0
  108. package/lib/webrtc/src/polyfill/install.js.map +1 -0
  109. package/lib/webrtc/src/polyfill/mediaDevices.d.ts +38 -0
  110. package/lib/webrtc/src/polyfill/mediaDevices.js +228 -0
  111. package/lib/webrtc/src/polyfill/mediaDevices.js.map +1 -0
  112. package/lib/webrtc/src/polyfill/mediaRegister.d.ts +51 -0
  113. package/lib/webrtc/src/polyfill/mediaRegister.js +14 -0
  114. package/lib/webrtc/src/polyfill/mediaRegister.js.map +1 -0
  115. package/lib/webrtc/src/polyfill/peerConnectionConfig.d.ts +3 -0
  116. package/lib/webrtc/src/polyfill/peerConnectionConfig.js +52 -0
  117. package/lib/webrtc/src/polyfill/peerConnectionConfig.js.map +1 -0
  118. package/lib/webrtc/src/polyfill/registers/callback.d.ts +16 -0
  119. package/lib/webrtc/src/polyfill/registers/callback.js +57 -0
  120. package/lib/webrtc/src/polyfill/registers/callback.js.map +1 -0
  121. package/lib/webrtc/src/polyfill/registers/empty.d.ts +2 -0
  122. package/lib/webrtc/src/polyfill/registers/empty.js +28 -0
  123. package/lib/webrtc/src/polyfill/registers/empty.js.map +1 -0
  124. package/lib/webrtc/src/polyfill/registers/mp4Webm.d.ts +36 -0
  125. package/lib/webrtc/src/polyfill/registers/mp4Webm.js +242 -0
  126. package/lib/webrtc/src/polyfill/registers/mp4Webm.js.map +1 -0
  127. package/lib/webrtc/src/polyfill/registers/rtpRtcp.d.ts +17 -0
  128. package/lib/webrtc/src/polyfill/registers/rtpRtcp.js +143 -0
  129. package/lib/webrtc/src/polyfill/registers/rtpRtcp.js.map +1 -0
  130. package/lib/webrtc/src/polyfill/rtcSessionDescription.d.ts +18 -0
  131. package/lib/webrtc/src/polyfill/rtcSessionDescription.js +36 -0
  132. package/lib/webrtc/src/polyfill/rtcSessionDescription.js.map +1 -0
  133. package/lib/webrtc/src/polyfill/rtpCodec.d.ts +17 -0
  134. package/lib/webrtc/src/polyfill/rtpCodec.js +93 -0
  135. package/lib/webrtc/src/polyfill/rtpCodec.js.map +1 -0
  136. package/lib/webrtc/src/polyfill/selectSettings.d.ts +31 -0
  137. package/lib/webrtc/src/polyfill/selectSettings.js +156 -0
  138. package/lib/webrtc/src/polyfill/selectSettings.js.map +1 -0
  139. package/lib/webrtc/src/polyfill/sourceIo.d.ts +21 -0
  140. package/lib/webrtc/src/polyfill/sourceIo.js +298 -0
  141. package/lib/webrtc/src/polyfill/sourceIo.js.map +1 -0
  142. package/lib/webrtc/src/polyfill/trackStop.d.ts +4 -0
  143. package/lib/webrtc/src/polyfill/trackStop.js +16 -0
  144. package/lib/webrtc/src/polyfill/trackStop.js.map +1 -0
  145. package/lib/webrtc/src/sctpManager.d.ts +2 -1
  146. package/lib/webrtc/src/sctpManager.js +5 -2
  147. package/lib/webrtc/src/sctpManager.js.map +1 -1
  148. package/lib/webrtc/src/sdp.d.ts +1 -1
  149. package/lib/webrtc/src/sdp.js +5 -6
  150. package/lib/webrtc/src/sdp.js.map +1 -1
  151. package/lib/webrtc/src/sdpManager.d.ts +38 -1
  152. package/lib/webrtc/src/sdpManager.js +236 -30
  153. package/lib/webrtc/src/sdpManager.js.map +1 -1
  154. package/lib/webrtc/src/secureTransportManager.d.ts +43 -12
  155. package/lib/webrtc/src/secureTransportManager.js +123 -47
  156. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  157. package/lib/webrtc/src/transceiverManager.d.ts +91 -6
  158. package/lib/webrtc/src/transceiverManager.js +477 -62
  159. package/lib/webrtc/src/transceiverManager.js.map +1 -1
  160. package/lib/webrtc/src/transport/ice.d.ts +8 -0
  161. package/lib/webrtc/src/transport/ice.js +17 -1
  162. package/lib/webrtc/src/transport/ice.js.map +1 -1
  163. package/lib/webrtc/src/transport/sctp.d.ts +3 -2
  164. package/lib/webrtc/src/transport/sctp.js +8 -2
  165. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  166. package/package.json +13 -3
@@ -579,7 +579,7 @@ var Event2 = class {
579
579
  error
580
580
  );
581
581
  };
582
- watch = (cb, timeLimit) => new Promise((resolve2, reject) => {
582
+ watch = (cb, timeLimit) => new Promise((resolve, reject) => {
583
583
  const timeout = timeLimit && setTimeout(() => {
584
584
  reject("Event watch timeout");
585
585
  }, timeLimit);
@@ -588,22 +588,22 @@ var Event2 = class {
588
588
  if (done) {
589
589
  if (timeout) clearTimeout(timeout);
590
590
  unSubscribe();
591
- resolve2(args);
591
+ resolve(args);
592
592
  }
593
593
  });
594
594
  });
595
- asPromise = (timeLimit) => new Promise((resolve2, reject) => {
595
+ asPromise = (timeLimit) => new Promise((resolve, reject) => {
596
596
  const timeout = timeLimit && setTimeout(() => {
597
597
  reject("Event asPromise timeout");
598
598
  }, timeLimit);
599
599
  this.once(
600
600
  (...args) => {
601
601
  if (timeout) clearTimeout(timeout);
602
- resolve2(args);
602
+ resolve(args);
603
603
  },
604
604
  () => {
605
605
  if (timeout) clearTimeout(timeout);
606
- resolve2([]);
606
+ resolve([]);
607
607
  },
608
608
  (err5) => {
609
609
  if (timeout) clearTimeout(timeout);
@@ -642,6 +642,7 @@ import * as net from "node:net";
642
642
  import * as tls from "node:tls";
643
643
  import { connect as connect2 } from "node:net";
644
644
  var log = debug("werift-ice:packages/ice/src/transport.ts");
645
+ var DEFAULT_CONNECT_TIMEOUT_MS = 8e3;
645
646
  var UdpTransport = class _UdpTransport {
646
647
  constructor(socketType, options = {}) {
647
648
  this.socketType = socketType;
@@ -710,6 +711,10 @@ var UdpTransport = class _UdpTransport {
710
711
  get address() {
711
712
  return this.socket.address();
712
713
  }
714
+ /** IP family of the bound socket: 4 for udp4, 6 for udp6. */
715
+ get addressFamily() {
716
+ return this.socketType === "udp6" ? 6 : 4;
717
+ }
713
718
  get host() {
714
719
  return this.socket.address().address;
715
720
  }
@@ -729,16 +734,23 @@ var UdpTransport = class _UdpTransport {
729
734
  var TcpTransport = class _TcpTransport {
730
735
  type = "tcp";
731
736
  stream;
732
- constructor(addr) {
737
+ constructor(addr, options = {}) {
733
738
  this.stream = new StreamTransport(
734
739
  "tcp",
735
- () => connect2({ port: addr[1], host: addr[0] })
740
+ () => connect2({ port: addr[1], host: addr[0] }),
741
+ void 0,
742
+ options.connectTimeoutMs
736
743
  );
737
744
  }
738
- static async init(addr) {
739
- const transport = new _TcpTransport(addr);
740
- await transport.init();
741
- return transport;
745
+ static async init(addr, options = {}) {
746
+ const transport = new _TcpTransport(addr, options);
747
+ try {
748
+ await transport.init();
749
+ return transport;
750
+ } catch (error) {
751
+ await transport.close();
752
+ throw error;
753
+ }
742
754
  }
743
755
  async init() {
744
756
  await this.stream.waitForConnect();
@@ -746,6 +758,9 @@ var TcpTransport = class _TcpTransport {
746
758
  get address() {
747
759
  return this.stream.address;
748
760
  }
761
+ get remoteAddress() {
762
+ return this.stream.remoteAddress;
763
+ }
749
764
  get closed() {
750
765
  return this.stream.closed;
751
766
  }
@@ -765,20 +780,27 @@ var TcpTransport = class _TcpTransport {
765
780
  var TlsTransport = class _TlsTransport {
766
781
  type = "tls";
767
782
  stream;
768
- constructor(addr, options = {}) {
783
+ constructor(addr, options = {}, streamOptions = {}) {
769
784
  this.stream = new StreamTransport(
770
785
  "tls",
771
786
  () => tls.connect({
772
787
  ...options,
773
788
  host: addr[0],
774
789
  port: addr[1]
775
- })
790
+ }),
791
+ void 0,
792
+ streamOptions.connectTimeoutMs
776
793
  );
777
794
  }
778
- static async init(addr, options = {}) {
779
- const transport = new _TlsTransport(addr, options);
780
- await transport.init();
781
- return transport;
795
+ static async init(addr, options = {}, streamOptions = {}) {
796
+ const transport = new _TlsTransport(addr, options, streamOptions);
797
+ try {
798
+ await transport.init();
799
+ return transport;
800
+ } catch (error) {
801
+ await transport.close();
802
+ throw error;
803
+ }
782
804
  }
783
805
  async init() {
784
806
  await this.stream.waitForConnect();
@@ -786,6 +808,9 @@ var TlsTransport = class _TlsTransport {
786
808
  get address() {
787
809
  return this.stream.address;
788
810
  }
811
+ get remoteAddress() {
812
+ return this.stream.remoteAddress;
813
+ }
789
814
  get closed() {
790
815
  return this.stream.closed;
791
816
  }
@@ -803,9 +828,10 @@ var TlsTransport = class _TlsTransport {
803
828
  };
804
829
  };
805
830
  var StreamTransport = class {
806
- constructor(type, createClient, connectEvent = type === "tls" ? "secureConnect" : "connect") {
831
+ constructor(type, createClient, connectEvent = type === "tls" ? "secureConnect" : "connect", connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MS) {
807
832
  this.createClient = createClient;
808
833
  this.connectEvent = connectEvent;
834
+ this.connectTimeoutMs = connectTimeoutMs;
809
835
  this.type = type;
810
836
  this.connect();
811
837
  }
@@ -815,6 +841,7 @@ var StreamTransport = class {
815
841
  onData = () => {
816
842
  };
817
843
  closed = false;
844
+ rejectConnecting;
818
845
  connect() {
819
846
  if (this.closed) {
820
847
  return;
@@ -824,27 +851,40 @@ var StreamTransport = class {
824
851
  }
825
852
  const client = this.createClient();
826
853
  this.client = client;
827
- this.connecting = new Promise((r, f) => {
828
- const onConnect = () => {
854
+ this.connecting = new Promise((resolve, reject) => {
855
+ let settled = false;
856
+ const settle = (error) => {
857
+ if (settled) return;
858
+ settled = true;
859
+ clearTimeout(timer2);
860
+ client.off(this.connectEvent, onConnect);
829
861
  client.off("error", onConnectError);
830
- r();
862
+ this.rejectConnecting = void 0;
863
+ error ? reject(error) : resolve();
864
+ };
865
+ const onConnect = () => {
866
+ settle();
831
867
  };
832
868
  const onConnectError = (error) => {
833
- client.off(this.connectEvent, onConnect);
834
- f(error);
869
+ this.closed = true;
870
+ settle(error);
871
+ client.destroy();
835
872
  };
873
+ const timer2 = setTimeout(() => {
874
+ this.closed = true;
875
+ settle(
876
+ new Error(
877
+ `${this.type} connect timed out after ${this.connectTimeoutMs}ms`
878
+ )
879
+ );
880
+ client.destroy();
881
+ }, this.connectTimeoutMs);
882
+ this.rejectConnecting = (error) => settle(error);
836
883
  client.once(this.connectEvent, onConnect);
837
884
  client.once("error", onConnectError);
838
885
  });
839
886
  client.on("data", (data) => {
840
- const addr = [
841
- this.client.remoteAddress,
842
- this.client.remotePort
843
- ];
844
- this.onData(data, addr);
845
- });
846
- client.on("end", () => {
847
- this.connect();
887
+ this.onData(data, this.remoteAddress);
848
888
  });
849
889
  client.on("error", (error) => {
850
890
  log(`${this.type} transport error`, error);
@@ -856,24 +896,36 @@ var StreamTransport = class {
856
896
  get address() {
857
897
  return {};
858
898
  }
899
+ /** The peer the stream is connected to, once connected. */
900
+ get remoteAddress() {
901
+ const { remoteAddress, remotePort } = this.client;
902
+ if (!remoteAddress || !remotePort) {
903
+ return void 0;
904
+ }
905
+ return [stripZoneId(remoteAddress), remotePort];
906
+ }
859
907
  send = async (data, addr) => {
860
908
  void addr;
861
909
  await this.connecting;
862
- await new Promise((resolve2, reject) => {
910
+ await new Promise((resolve, reject) => {
863
911
  this.client.write(data, (err5) => {
864
912
  if (err5) {
865
913
  reject(err5);
866
914
  return;
867
915
  }
868
- resolve2();
916
+ resolve();
869
917
  });
870
918
  });
871
919
  };
872
920
  close = async () => {
873
921
  this.closed = true;
922
+ this.rejectConnecting?.(new Error(`${this.type} transport closed`));
874
923
  this.client?.destroy();
875
924
  };
876
925
  };
926
+ function stripZoneId(address) {
927
+ return address.split("%")[0];
928
+ }
877
929
 
878
930
  // ../rtp/src/extra/container/mp4/container.ts
879
931
  var Mp4Container = class {
@@ -897,6 +949,8 @@ var Mp4Container = class {
897
949
  #startPromise;
898
950
  #stopPromise;
899
951
  #stopped = false;
952
+ // EncodedChunk timestamps may be negative; EncodedPacket requires >= 0.
953
+ #timestampOrigin = {};
900
954
  #videoFrame;
901
955
  #videoMeta;
902
956
  #videoSource;
@@ -1131,10 +1185,17 @@ var Mp4Container = class {
1131
1185
  async #writePacket(frame, duration) {
1132
1186
  const data = new Uint8Array(frame.byteLength);
1133
1187
  frame.copyTo(data.buffer);
1188
+ if (this.#timestampOrigin[frame.track] == void 0) {
1189
+ this.#timestampOrigin[frame.track] = Math.min(0, frame.timestamp);
1190
+ }
1191
+ const timestamp = Math.max(
1192
+ 0,
1193
+ frame.timestamp - this.#timestampOrigin[frame.track]
1194
+ );
1134
1195
  const packet = new EncodedPacket(
1135
1196
  data,
1136
1197
  frame.type,
1137
- frame.timestamp / 1e6,
1198
+ timestamp / 1e6,
1138
1199
  duration / 1e6
1139
1200
  );
1140
1201
  if (frame.track === "audio") {
@@ -1148,12 +1209,7 @@ var Mp4Container = class {
1148
1209
  }
1149
1210
  await this.#videoSource.add(packet, this.#videoMeta);
1150
1211
  }
1151
- this.#rememberFragmentPacket(
1152
- frame.track,
1153
- frame.type,
1154
- frame.timestamp,
1155
- duration
1156
- );
1212
+ this.#rememberFragmentPacket(frame.track, frame.type, timestamp, duration);
1157
1213
  }
1158
1214
  #rememberFragmentPacket(kind, type, timestamp, duration) {
1159
1215
  const end = timestamp + duration;
@@ -5809,17 +5865,17 @@ var JitterBufferBase = class {
5809
5865
  this.rtpBuffer[rtp.header.sequenceNumber] = rtp;
5810
5866
  }
5811
5867
  resolveBuffer(seqNumFrom) {
5812
- const resolve2 = [];
5868
+ const resolve = [];
5813
5869
  for (let index = seqNumFrom; ; index = uint16Add(index, 1)) {
5814
5870
  const rtp = this.rtpBuffer[index];
5815
5871
  if (rtp) {
5816
- resolve2.push(rtp);
5872
+ resolve.push(rtp);
5817
5873
  delete this.rtpBuffer[index];
5818
5874
  } else {
5819
5875
  break;
5820
5876
  }
5821
5877
  }
5822
- return resolve2;
5878
+ return resolve;
5823
5879
  }
5824
5880
  sortAndClearBuffer(rtpBuffer) {
5825
5881
  const buffer2 = [];
@@ -6141,7 +6197,7 @@ var MP4Base = class {
6141
6197
  if (eol) {
6142
6198
  this.videoStopped = true;
6143
6199
  if (!this.tracks.some((track2) => track2.kind === "audio") || this.audioStopped) {
6144
- void this.stop();
6200
+ void this.stop().catch(() => void 0);
6145
6201
  }
6146
6202
  }
6147
6203
  return;
@@ -6198,7 +6254,7 @@ var MP4Base = class {
6198
6254
  if (eol) {
6199
6255
  this.audioStopped = true;
6200
6256
  if (!this.tracks.some((track2) => track2.kind === "video") || this.videoStopped) {
6201
- void this.stop();
6257
+ void this.stop().catch(() => void 0);
6202
6258
  }
6203
6259
  }
6204
6260
  return;
@@ -6233,7 +6289,10 @@ var MP4Base = class {
6233
6289
  return;
6234
6290
  }
6235
6291
  this.stopped = true;
6236
- await this.container.stop();
6292
+ try {
6293
+ await this.container.stop();
6294
+ } catch {
6295
+ }
6237
6296
  await this.output({ eol: true });
6238
6297
  await this.onStopped.execute();
6239
6298
  }
@@ -6294,7 +6353,7 @@ var MP4Callback = class extends MP4Base {
6294
6353
  this.processVideoInput(input);
6295
6354
  };
6296
6355
  destroy = () => {
6297
- void this.stop().finally(() => {
6356
+ void this.stop().catch(() => void 0).finally(() => {
6298
6357
  this.cb = void 0;
6299
6358
  this.queue.cancel();
6300
6359
  });
@@ -9242,10 +9301,6 @@ var log25 = debug("werift-ice : packages/ice/src/ice.ts : log");
9242
9301
 
9243
9302
  // src/helper.ts
9244
9303
  import { EventEmitter } from "node:events";
9245
- function divide(from, split) {
9246
- const arr = from.split(split);
9247
- return [arr[0], arr.slice(1).join(split)];
9248
- }
9249
9304
  var EventTarget2 = class extends EventEmitter {
9250
9305
  emit(type, ...args) {
9251
9306
  if (typeof type !== "string") {
@@ -9357,6 +9412,12 @@ var usePCMU = (props = {}) => new RTCRtpCodecParameters({
9357
9412
  payloadType: 0,
9358
9413
  ...props
9359
9414
  });
9415
+ function defaultCodecs() {
9416
+ return {
9417
+ audio: [useOPUS(), usePCMU()],
9418
+ video: [useVP8()]
9419
+ };
9420
+ }
9360
9421
  var supportedCodecs = [
9361
9422
  useAV1X(),
9362
9423
  useVP9(),
@@ -9385,23 +9446,83 @@ var DTLS_SETUP_ROLE = Object.keys(
9385
9446
  acc[key] = cur;
9386
9447
  return acc;
9387
9448
  }, {});
9388
- var FMTP_INT_PARAMETERS = [
9389
- "apt",
9390
- "max-fr",
9391
- "max-fs",
9392
- "maxplaybackrate",
9393
- "minptime",
9394
- "stereo",
9395
- "useinbandfec"
9396
- ];
9397
9449
  var SRTP_PROFILE = {
9398
9450
  SRTP_AES128_CM_HMAC_SHA1_80: ProtectionProfileAes128CmHmacSha1_80,
9399
9451
  SRTP_AEAD_AES_128_GCM: ProtectionProfileAeadAes128Gcm
9400
9452
  };
9401
9453
 
9454
+ // src/transport/dtls.ts
9455
+ import { Certificate as Certificate3, PrivateKey as PrivateKey2 } from "@fidm/x509";
9456
+
9402
9457
  // src/media/track.ts
9403
9458
  import { randomUUID as randomUUID5 } from "crypto";
9404
- var MediaStreamTrack = class extends EventTarget2 {
9459
+ var sourceCodecsByTrack = /* @__PURE__ */ new WeakMap();
9460
+ var sourceCodecsCapturedByTrack = /* @__PURE__ */ new WeakSet();
9461
+ function setTrackSourceCodecs(track, codecs) {
9462
+ sourceCodecsCapturedByTrack.add(track);
9463
+ if (codecs == void 0) sourceCodecsByTrack.delete(track);
9464
+ else sourceCodecsByTrack.set(track, codecs);
9465
+ }
9466
+ function getTrackSourceCodecs(track) {
9467
+ return track == void 0 ? void 0 : sourceCodecsByTrack.get(track);
9468
+ }
9469
+ function captureTrackSourceCodecs(track) {
9470
+ if (sourceCodecsCapturedByTrack.has(track)) return;
9471
+ sourceCodecsCapturedByTrack.add(track);
9472
+ if (track.codec != void 0) {
9473
+ sourceCodecsByTrack.set(track, [track.codec]);
9474
+ }
9475
+ }
9476
+ var TrackBroadcastSource = class {
9477
+ tracks = /* @__PURE__ */ new Set();
9478
+ upstreamStops = /* @__PURE__ */ new Set();
9479
+ attach(track) {
9480
+ this.tracks.add(track);
9481
+ }
9482
+ detach(track) {
9483
+ this.tracks.delete(track);
9484
+ if (this.tracks.size > 0) {
9485
+ return;
9486
+ }
9487
+ for (const stop of [...this.upstreamStops]) {
9488
+ stop();
9489
+ }
9490
+ this.upstreamStops.clear();
9491
+ }
9492
+ addUpstreamStop(stop) {
9493
+ const once = () => {
9494
+ this.upstreamStops.delete(once);
9495
+ stop();
9496
+ };
9497
+ this.upstreamStops.add(once);
9498
+ }
9499
+ deliverRtp(packet, extensions) {
9500
+ const live = [...this.tracks].filter((track) => !track.stopped);
9501
+ for (const track of live) {
9502
+ track.applyIncomingRtp(packet.clone(), extensions);
9503
+ }
9504
+ }
9505
+ deliverRtcp(packet) {
9506
+ for (const track of this.tracks) {
9507
+ if (!track.stopped) {
9508
+ track.onReceiveRtcp.execute(packet);
9509
+ }
9510
+ }
9511
+ }
9512
+ deliverSourceChanged(header) {
9513
+ for (const track of this.tracks) {
9514
+ if (!track.stopped) {
9515
+ track.onSourceChanged.execute(header);
9516
+ }
9517
+ }
9518
+ }
9519
+ stopAllTracks() {
9520
+ for (const track of [...this.tracks]) {
9521
+ track.stop();
9522
+ }
9523
+ }
9524
+ };
9525
+ var MediaStreamTrack = class _MediaStreamTrack extends EventTarget2 {
9405
9526
  uuid = randomUUID5().toString();
9406
9527
  /**MediaStream ID*/
9407
9528
  streamId;
@@ -9421,34 +9542,83 @@ var MediaStreamTrack = class extends EventTarget2 {
9421
9542
  onSourceChanged = new Event2();
9422
9543
  stopped = false;
9423
9544
  muted = true;
9545
+ broadcastSource;
9424
9546
  constructor(props) {
9425
9547
  super();
9548
+ const sharedSource = props.broadcastSource;
9426
9549
  Object.assign(this, props);
9550
+ this.id ??= this.uuid;
9551
+ this.broadcastSource = sharedSource ?? new TrackBroadcastSource();
9552
+ if (!this.stopped) {
9553
+ this.broadcastSource.attach(this);
9554
+ }
9427
9555
  this.onReceiveRtp.subscribe((rtp) => {
9428
9556
  this.muted = false;
9429
9557
  this.header = rtp.header;
9430
9558
  });
9431
9559
  this.label = `${this.remote ? "remote" : "local"} ${this.kind}`;
9432
9560
  }
9561
+ get readyState() {
9562
+ return this.stopped ? "ended" : "live";
9563
+ }
9433
9564
  stop = () => {
9565
+ if (this.stopped) {
9566
+ return;
9567
+ }
9434
9568
  this.stopped = true;
9435
9569
  this.muted = true;
9436
9570
  this.onReceiveRtp.complete();
9437
9571
  this.emit("ended");
9572
+ this.broadcastSource.detach(this);
9438
9573
  };
9439
9574
  writeRtp = (rtp) => {
9440
9575
  if (this.remote) {
9441
9576
  throw new Error("this is remoteTrack");
9442
9577
  }
9578
+ const packet = Buffer.isBuffer(rtp) ? RtpPacket.deSerialize(rtp) : rtp.clone();
9579
+ packet.header.payloadType = this.codec?.payloadType ?? packet.header.payloadType;
9580
+ this.broadcastSource.deliverRtp(packet);
9581
+ };
9582
+ writeRtcp = (rtcp) => {
9583
+ this.broadcastSource.deliverRtcp(rtcp);
9584
+ };
9585
+ notifySourceChanged(header) {
9586
+ this.broadcastSource.deliverSourceChanged(header);
9587
+ }
9588
+ applyIncomingRtp(packet, extensions) {
9443
9589
  if (this.stopped) {
9444
9590
  return;
9445
9591
  }
9446
- const packet = Buffer.isBuffer(rtp) ? RtpPacket.deSerialize(rtp) : rtp;
9447
- packet.header.payloadType = this.codec?.payloadType ?? packet.header.payloadType;
9448
- this.onReceiveRtp.execute(packet);
9449
- };
9592
+ this.onReceiveRtp.execute(packet, extensions);
9593
+ }
9594
+ bindUpstreamStop(stop) {
9595
+ this.broadcastSource.addUpstreamStop(stop);
9596
+ }
9597
+ stopMediaSource() {
9598
+ this.broadcastSource.stopAllTracks();
9599
+ }
9600
+ clone() {
9601
+ const cloned = new _MediaStreamTrack({
9602
+ kind: this.kind,
9603
+ remote: this.remote,
9604
+ enabled: this.enabled,
9605
+ muted: this.muted,
9606
+ stopped: this.stopped,
9607
+ codec: this.codec,
9608
+ ssrc: this.ssrc,
9609
+ rid: this.rid,
9610
+ header: this.header,
9611
+ broadcastSource: this.broadcastSource
9612
+ });
9613
+ if (sourceCodecsCapturedByTrack.has(this)) {
9614
+ setTrackSourceCodecs(cloned, getTrackSourceCodecs(this));
9615
+ } else {
9616
+ captureTrackSourceCodecs(cloned);
9617
+ }
9618
+ return cloned;
9619
+ }
9450
9620
  };
9451
- var MediaStream = class {
9621
+ var MediaStream = class _MediaStream {
9452
9622
  id;
9453
9623
  tracks = [];
9454
9624
  constructor(props = {}) {
@@ -9478,6 +9648,19 @@ var MediaStream = class {
9478
9648
  getVideoTracks() {
9479
9649
  return this.tracks.filter((track) => track.kind === "video");
9480
9650
  }
9651
+ getTrackById(id) {
9652
+ return this.tracks.find((track) => track.id === id);
9653
+ }
9654
+ get active() {
9655
+ return this.tracks.some((track) => !track.stopped);
9656
+ }
9657
+ clone() {
9658
+ const cloned = new _MediaStream();
9659
+ for (const track of this.tracks) {
9660
+ cloned.addTrack(track.clone());
9661
+ }
9662
+ return cloned;
9663
+ }
9481
9664
  };
9482
9665
 
9483
9666
  // src/utils.ts
@@ -9486,21 +9669,17 @@ var milliTime = Date.now;
9486
9669
  var startupTimestampInMicroseconds = BigInt(Date.now()) * 1000n - process.hrtime.bigint() / 1000n;
9487
9670
  var createSelfSignedCertificate = CipherContext.createSelfSignedCertificateWithKey;
9488
9671
 
9489
- // src/media/receiver/nack.ts
9490
- var log28 = debug("werift:packages/webrtc/src/media/receiver/nack.ts");
9491
- var LOST_SIZE2 = 30 * 5;
9492
-
9493
- // src/media/receiver/receiverTwcc.ts
9494
- var log29 = debug("werift:packages/webrtc/media/receiver/receiverTwcc");
9495
-
9496
9672
  // src/transport/dtls.ts
9497
- import { Certificate as Certificate3, PrivateKey as PrivateKey2 } from "@fidm/x509";
9498
- var log30 = debug("werift:packages/webrtc/src/transport/dtls.ts");
9673
+ var log28 = debug("werift:packages/webrtc/src/transport/dtls.ts");
9499
9674
 
9500
9675
  // src/transport/ice.ts
9501
- var log31 = debug("werift:packages/webrtc/src/transport/ice.ts");
9676
+ var log29 = debug("werift:packages/webrtc/src/transport/ice.ts");
9502
9677
 
9503
9678
  // ../sctp/src/chunk.ts
9679
+ var SCTP_PADDING_MULTIPLE = 4;
9680
+ var SCTP_CHUNK_HEADER_SIZE = 4;
9681
+ var SCTP_DATA_FIXED_HEADER_SIZE = 12;
9682
+ var SCTP_DATA_CHUNK_HEADER_SIZE = SCTP_CHUNK_HEADER_SIZE + SCTP_DATA_FIXED_HEADER_SIZE;
9504
9683
  var Chunk = class _Chunk {
9505
9684
  constructor(flags = 0, _body = Buffer.from("")) {
9506
9685
  this.flags = flags;
@@ -9518,10 +9697,10 @@ var Chunk = class _Chunk {
9518
9697
  }
9519
9698
  get bytes() {
9520
9699
  if (!this.body) throw new Error();
9521
- const header = Buffer.alloc(4);
9700
+ const header = Buffer.alloc(SCTP_CHUNK_HEADER_SIZE);
9522
9701
  header.writeUInt8(this.type, 0);
9523
9702
  header.writeUInt8(this.flags, 1);
9524
- header.writeUInt16BE(this.body.length + 4, 2);
9703
+ header.writeUInt16BE(this.body.length + SCTP_CHUNK_HEADER_SIZE, 2);
9525
9704
  const data = Buffer.concat([
9526
9705
  header,
9527
9706
  this.body,
@@ -9646,8 +9825,8 @@ var DataChunk = class _DataChunk extends Chunk {
9646
9825
  maxRetransmits;
9647
9826
  sentTime;
9648
9827
  get bytes() {
9649
- const length = 16 + this.userData.length;
9650
- const header = Buffer.alloc(16);
9828
+ const length = SCTP_DATA_CHUNK_HEADER_SIZE + this.userData.length;
9829
+ const header = Buffer.alloc(SCTP_DATA_CHUNK_HEADER_SIZE);
9651
9830
  header.writeUInt8(this.type, 0);
9652
9831
  header.writeUInt8(this.flags, 1);
9653
9832
  header.writeUInt16BE(length, 2);
@@ -9857,8 +10036,8 @@ var CHUNK_BY_TYPE = CHUNK_CLASSES.reduce(
9857
10036
  {}
9858
10037
  );
9859
10038
  function padL(l) {
9860
- const m = l % 4;
9861
- return m ? 4 - m : 0;
10039
+ const m = l % SCTP_PADDING_MULTIPLE;
10040
+ return m ? SCTP_PADDING_MULTIPLE - m : 0;
9862
10041
  }
9863
10042
  function encodeParams(params) {
9864
10043
  let body = Buffer.from("");
@@ -9888,35 +10067,22 @@ function decodeParams(body) {
9888
10067
  }
9889
10068
 
9890
10069
  // ../sctp/src/sctp.ts
9891
- var log32 = debug("werift/sctp/sctp");
10070
+ var log30 = debug("werift/sctp/sctp");
10071
+ var DEFAULT_SCTP_MTU = 1191;
9892
10072
  var SCTP_RTO_ALPHA = 1 / 8;
9893
10073
  var SCTP_RTO_BETA = 1 / 4;
9894
10074
  var SCTP_TSN_MODULO = 2 ** 32;
9895
10075
 
9896
10076
  // src/transport/sctp.ts
9897
- var log33 = debug("werift:packages/webrtc/src/transport/sctp.ts");
10077
+ var log31 = debug("werift:packages/webrtc/src/transport/sctp.ts");
9898
10078
  var DEFAULT_MAX_MESSAGE_SIZE = 65536;
9899
10079
 
9900
- // src/sdp.ts
9901
- function codecParametersFromString(str) {
9902
- const parameters = {};
9903
- str.split(";").forEach((param) => {
9904
- if (param.includes("=")) {
9905
- const [k, v] = divide(param, "=");
9906
- if (FMTP_INT_PARAMETERS.includes(k)) {
9907
- parameters[k] = Number(v);
9908
- } else {
9909
- parameters[k] = v;
9910
- }
9911
- } else if (param.includes(":")) {
9912
- const [k, v] = param.split(":");
9913
- parameters[k] = Number.isNaN(Number(v)) ? v : Number(v);
9914
- } else {
9915
- parameters[param] = void 0;
9916
- }
9917
- });
9918
- return parameters;
9919
- }
10080
+ // src/media/receiver/nack.ts
10081
+ var log32 = debug("werift:packages/webrtc/src/media/receiver/nack.ts");
10082
+ var LOST_SIZE2 = 30 * 5;
10083
+
10084
+ // src/media/receiver/receiverTwcc.ts
10085
+ var log33 = debug("werift:packages/webrtc/media/receiver/receiverTwcc");
9920
10086
 
9921
10087
  // src/media/rtpReceiver.ts
9922
10088
  var log34 = debug("werift:packages/webrtc/src/media/rtpReceiver.ts");
@@ -9927,11 +10093,14 @@ var log35 = debug("werift:packages/webrtc/src/media/router.ts");
9927
10093
  // src/media/rtpSender.ts
9928
10094
  var log36 = debug("werift:packages/webrtc/src/media/rtpSender.ts");
9929
10095
 
10096
+ // src/transceiverManager.ts
10097
+ var log37 = debug("werift:packages/webrtc/src/media/rtpTransceiverManager.ts");
10098
+
9930
10099
  // src/sctpManager.ts
9931
- var log37 = debug("werift:packages/webrtc/src/transport/sctpManager.ts");
10100
+ var log38 = debug("werift:packages/webrtc/src/transport/sctpManager.ts");
9932
10101
 
9933
10102
  // src/secureTransportManager.ts
9934
- var log38 = debug(
10103
+ var log39 = debug(
9935
10104
  "werift:packages/webrtc/src/transport/secureTransportManager.ts"
9936
10105
  );
9937
10106
  var srtpProfiles = [
@@ -9941,13 +10110,10 @@ var srtpProfiles = [
9941
10110
  ];
9942
10111
 
9943
10112
  // src/peerConnection.ts
9944
- var log39 = debug("werift:packages/webrtc/src/peerConnection.ts");
10113
+ var log40 = debug("werift:packages/webrtc/src/peerConnection.ts");
9945
10114
  function generateDefaultPeerConfig() {
9946
10115
  return {
9947
- codecs: {
9948
- audio: [useOPUS(), usePCMU()],
9949
- video: [useVP8()]
9950
- },
10116
+ codecs: defaultCodecs(),
9951
10117
  headerExtensions: {
9952
10118
  audio: [],
9953
10119
  video: []
@@ -9961,8 +10127,12 @@ function generateDefaultPeerConfig() {
9961
10127
  iceUseIpv4: true,
9962
10128
  iceUseIpv6: true,
9963
10129
  iceUseTcp: false,
10130
+ iceTcpPassive: true,
10131
+ iceStunGatherTimeout: void 0,
10132
+ iceTurnConnectTimeout: void 0,
9964
10133
  turnTransport: void 0,
9965
10134
  turnTlsOptions: void 0,
10135
+ turnUdpFamily: void 0,
9966
10136
  iceFilterStunResponse: void 0,
9967
10137
  iceFilterCandidatePair: void 0,
9968
10138
  icePasswordPrefix: void 0,
@@ -9975,14 +10145,14 @@ function generateDefaultPeerConfig() {
9975
10145
  debug: {},
9976
10146
  midSuffix: false,
9977
10147
  forceTurnTCP: false,
9978
- maxMessageSize: DEFAULT_MAX_MESSAGE_SIZE
10148
+ maxMessageSize: DEFAULT_MAX_MESSAGE_SIZE,
10149
+ sctp: { mtu: DEFAULT_SCTP_MTU },
10150
+ pendingRtp: false,
10151
+ mLineReuse: "compatible"
9979
10152
  };
9980
10153
  }
9981
10154
  var defaultPeerConfig = generateDefaultPeerConfig();
9982
10155
 
9983
- // src/transceiverManager.ts
9984
- var log40 = debug("werift:packages/webrtc/src/media/rtpTransceiverManager.ts");
9985
-
9986
10156
  // src/nonstandard/dummyMedia.ts
9987
10157
  var AUDIO_PACKET_MS = 20;
9988
10158
  var AUDIO_TIMESTAMP_STEP = 960;
@@ -10268,6 +10438,7 @@ var WebmFactory = class extends MediaWriter {
10268
10438
  return "VP9";
10269
10439
  case "h264":
10270
10440
  return "MPEG4/ISO/AVC";
10441
+ case "av1":
10271
10442
  case "av1x":
10272
10443
  return "AV1";
10273
10444
  default:
@@ -10425,893 +10596,6 @@ var MediaRecorder = class {
10425
10596
  await this.writer.stop();
10426
10597
  }
10427
10598
  };
10428
-
10429
- // src/nonstandard/userMedia.ts
10430
- import { randomUUID as randomUUID6 } from "crypto";
10431
- import { homedir } from "os";
10432
- import { isAbsolute, resolve } from "path";
10433
- import { Readable } from "stream";
10434
- import { readFile } from "fs/promises";
10435
- import {
10436
- setImmediate as onNextTurn,
10437
- setTimeout as wait
10438
- } from "timers/promises";
10439
- import {
10440
- BufferSource,
10441
- EncodedPacketSink,
10442
- Input,
10443
- MP4,
10444
- WEBM
10445
- } from "mediabunny";
10446
-
10447
- // src/nonstandard/userMedia/packetizer.ts
10448
- var DEFAULT_MAX_RTP_PAYLOAD_SIZE = 1200;
10449
- var supportedSourceCodecs = [
10450
- "avc",
10451
- "vp8",
10452
- "vp9",
10453
- "av1",
10454
- "opus"
10455
- ];
10456
- function toSupportedMimeType(codec) {
10457
- switch (codec) {
10458
- case "avc":
10459
- return "video/h264";
10460
- case "vp8":
10461
- return "video/vp8";
10462
- case "vp9":
10463
- return "video/vp9";
10464
- case "av1":
10465
- return "video/av1x";
10466
- case "opus":
10467
- return "audio/opus";
10468
- }
10469
- }
10470
- function createPacketizer({
10471
- codec,
10472
- sourceCodec,
10473
- decoderDescription
10474
- }) {
10475
- switch (sourceCodec) {
10476
- case "avc":
10477
- return new H264Packetizer(codec, decoderDescription ?? null);
10478
- case "vp8":
10479
- return new Vp8Packetizer(codec);
10480
- case "vp9":
10481
- return new Vp9Packetizer(codec);
10482
- case "av1":
10483
- return new Av1Packetizer(codec);
10484
- case "opus":
10485
- return new OpusPacketizer(codec);
10486
- }
10487
- }
10488
- var BasePacketizer = class {
10489
- constructor(codec, maxPayloadSize = DEFAULT_MAX_RTP_PAYLOAD_SIZE) {
10490
- this.codec = codec;
10491
- this.maxPayloadSize = maxPayloadSize;
10492
- }
10493
- sequenceNumber = random16();
10494
- buildPacket(payload, timestamp, marker) {
10495
- const packet = new RtpPacket(
10496
- new RtpHeader({
10497
- payloadType: this.codec.payloadType ?? 96,
10498
- sequenceNumber: this.sequenceNumber,
10499
- timestamp,
10500
- marker
10501
- }),
10502
- payload
10503
- );
10504
- this.sequenceNumber = this.sequenceNumber + 1 & 65535;
10505
- return packet;
10506
- }
10507
- };
10508
- var OpusPacketizer = class extends BasePacketizer {
10509
- packetize(packet, rtpTimestamp) {
10510
- return [this.buildPacket(toBuffer(packet.data), rtpTimestamp, true)];
10511
- }
10512
- };
10513
- var Vp8Packetizer = class extends BasePacketizer {
10514
- packetize(packet, rtpTimestamp) {
10515
- const frame = toBuffer(packet.data);
10516
- const chunkSize = this.maxPayloadSize - 1;
10517
- if (chunkSize <= 0) {
10518
- throw new Error("invalid VP8 RTP payload size");
10519
- }
10520
- const packets = [];
10521
- for (let offset = 0; offset < frame.length; offset += chunkSize) {
10522
- const chunk = frame.subarray(
10523
- offset,
10524
- Math.min(frame.length, offset + chunkSize)
10525
- );
10526
- const descriptor = Buffer.from([offset === 0 ? 16 : 0]);
10527
- packets.push(
10528
- this.buildPacket(
10529
- Buffer.concat([descriptor, chunk]),
10530
- rtpTimestamp,
10531
- offset + chunk.length >= frame.length
10532
- )
10533
- );
10534
- }
10535
- return packets;
10536
- }
10537
- };
10538
- var Vp9Packetizer = class extends BasePacketizer {
10539
- packetize(packet, rtpTimestamp) {
10540
- const frame = toBuffer(packet.data);
10541
- const chunkSize = this.maxPayloadSize - 1;
10542
- if (chunkSize <= 0) {
10543
- throw new Error("invalid VP9 RTP payload size");
10544
- }
10545
- const packets = [];
10546
- for (let offset = 0; offset < frame.length; offset += chunkSize) {
10547
- const chunk = frame.subarray(
10548
- offset,
10549
- Math.min(frame.length, offset + chunkSize)
10550
- );
10551
- const descriptor = new BitWriter(8).set(1, 0, 0).set(1, 1, packet.type === "delta" ? 1 : 0).set(1, 2, 0).set(1, 3, 0).set(1, 4, offset === 0 ? 1 : 0).set(1, 5, offset + chunk.length >= frame.length ? 1 : 0).set(1, 6, 0).set(1, 7, 0).buffer;
10552
- packets.push(
10553
- this.buildPacket(
10554
- Buffer.concat([descriptor, chunk]),
10555
- rtpTimestamp,
10556
- offset + chunk.length >= frame.length
10557
- )
10558
- );
10559
- }
10560
- return packets;
10561
- }
10562
- };
10563
- var Av1Packetizer = class extends BasePacketizer {
10564
- packetize(packet, rtpTimestamp) {
10565
- const obus = splitAv1Obus(toBuffer(packet.data));
10566
- const packets = [];
10567
- const fragmentSize = this.maxPayloadSize - 1;
10568
- if (fragmentSize <= 0) {
10569
- throw new Error("invalid AV1 RTP payload size");
10570
- }
10571
- let firstPacketInFrame = true;
10572
- const startsNewCodedVideoSequence = packet.type === "key";
10573
- for (const obu of obus) {
10574
- if (obu.length <= fragmentSize) {
10575
- const aggregationHeader = createAv1AggregationHeader({
10576
- startsWithFragment: false,
10577
- endsWithFragment: false,
10578
- startsNewCodedVideoSequence: firstPacketInFrame && startsNewCodedVideoSequence
10579
- });
10580
- packets.push(
10581
- this.buildPacket(
10582
- Buffer.concat([aggregationHeader, obu]),
10583
- rtpTimestamp,
10584
- false
10585
- )
10586
- );
10587
- firstPacketInFrame = false;
10588
- continue;
10589
- }
10590
- for (let offset = 0; offset < obu.length; offset += fragmentSize) {
10591
- const chunk = obu.subarray(
10592
- offset,
10593
- Math.min(obu.length, offset + fragmentSize)
10594
- );
10595
- const aggregationHeader = createAv1AggregationHeader({
10596
- startsWithFragment: offset > 0,
10597
- endsWithFragment: offset + chunk.length < obu.length,
10598
- startsNewCodedVideoSequence: firstPacketInFrame && startsNewCodedVideoSequence
10599
- });
10600
- packets.push(
10601
- this.buildPacket(
10602
- Buffer.concat([aggregationHeader, chunk]),
10603
- rtpTimestamp,
10604
- false
10605
- )
10606
- );
10607
- firstPacketInFrame = false;
10608
- }
10609
- }
10610
- if (packets.length === 0) {
10611
- throw new Error("AV1 sample did not contain any OBU data");
10612
- }
10613
- packets.at(-1).header.marker = true;
10614
- return packets;
10615
- }
10616
- };
10617
- var H264Packetizer = class extends BasePacketizer {
10618
- naluLengthSize;
10619
- parameterSets;
10620
- constructor(codec, decoderDescription) {
10621
- super(codec);
10622
- const packetizationMode = getH264PacketizationMode(codec.parameters);
10623
- if (packetizationMode !== 1) {
10624
- throw new Error(
10625
- `Unsupported H264 packetization-mode=${packetizationMode}. File playback requires packetization-mode=1.`
10626
- );
10627
- }
10628
- const avcConfig = parseAvcDecoderConfiguration(decoderDescription);
10629
- this.naluLengthSize = avcConfig?.naluLengthSize ?? 4;
10630
- this.parameterSets = avcConfig ? [...avcConfig.sps.map(Buffer.from), ...avcConfig.pps.map(Buffer.from)] : [];
10631
- }
10632
- packetize(packet, rtpTimestamp) {
10633
- let nalUnits = splitH264Sample(toBuffer(packet.data), this.naluLengthSize);
10634
- if (packet.type === "key" && this.parameterSets.length > 0 && !containsH264ParameterSets(nalUnits)) {
10635
- nalUnits = [...this.parameterSets, ...nalUnits];
10636
- }
10637
- const packets = [];
10638
- nalUnits.forEach((nalUnit, index) => {
10639
- const marker = index === nalUnits.length - 1;
10640
- if (nalUnit.length <= this.maxPayloadSize) {
10641
- packets.push(this.buildPacket(nalUnit, rtpTimestamp, marker));
10642
- return;
10643
- }
10644
- const nalHeader = nalUnit[0];
10645
- const fragmentPayload = nalUnit.subarray(1);
10646
- const fragmentSize = this.maxPayloadSize - 2;
10647
- if (fragmentSize <= 0) {
10648
- throw new Error("invalid H264 RTP payload size");
10649
- }
10650
- const fuIndicator = nalHeader & 224 | 28;
10651
- const nalType = nalHeader & 31;
10652
- for (let offset = 0; offset < fragmentPayload.length; offset += fragmentSize) {
10653
- const chunk = fragmentPayload.subarray(
10654
- offset,
10655
- Math.min(fragmentPayload.length, offset + fragmentSize)
10656
- );
10657
- const fuHeader = Buffer.from([
10658
- (offset === 0 ? 128 : 0) | (offset + chunk.length >= fragmentPayload.length ? 64 : 0) | nalType
10659
- ]);
10660
- packets.push(
10661
- this.buildPacket(
10662
- Buffer.concat([Buffer.from([fuIndicator]), fuHeader, chunk]),
10663
- rtpTimestamp,
10664
- marker && offset + chunk.length >= fragmentPayload.length
10665
- )
10666
- );
10667
- }
10668
- });
10669
- return packets;
10670
- }
10671
- };
10672
- function createAv1AggregationHeader({
10673
- startsWithFragment,
10674
- endsWithFragment,
10675
- startsNewCodedVideoSequence
10676
- }) {
10677
- return new BitWriter(8).set(1, 0, startsWithFragment ? 1 : 0).set(1, 1, endsWithFragment ? 1 : 0).set(2, 2, 1).set(1, 4, startsNewCodedVideoSequence ? 1 : 0).set(3, 5, 0).buffer;
10678
- }
10679
- function parseAvcDecoderConfiguration(decoderDescription) {
10680
- if (!decoderDescription) {
10681
- return null;
10682
- }
10683
- const description = toDescriptionBuffer(decoderDescription);
10684
- if (description.length < 7) {
10685
- throw new Error("invalid H264 decoder configuration");
10686
- }
10687
- const naluLengthSize = (description[4] & 3) + 1;
10688
- const spsCount = description[5] & 31;
10689
- let offset = 6;
10690
- const sps = [];
10691
- for (let index = 0; index < spsCount; index++) {
10692
- const length = description.readUInt16BE(offset);
10693
- offset += 2;
10694
- sps.push(description.subarray(offset, offset + length));
10695
- offset += length;
10696
- }
10697
- const ppsCount = description[offset] ?? 0;
10698
- offset++;
10699
- const pps = [];
10700
- for (let index = 0; index < ppsCount; index++) {
10701
- const length = description.readUInt16BE(offset);
10702
- offset += 2;
10703
- pps.push(description.subarray(offset, offset + length));
10704
- offset += length;
10705
- }
10706
- return { naluLengthSize, sps, pps };
10707
- }
10708
- function splitH264Sample(sample, naluLengthSize) {
10709
- if (looksLikeAnnexB(sample)) {
10710
- const nalUnits2 = [];
10711
- const parser = new H264AnnexBParser(sample);
10712
- let payload = parser.readNextNaluPayload();
10713
- while (payload) {
10714
- nalUnits2.push(Buffer.from(payload.data));
10715
- payload = parser.readNextNaluPayload();
10716
- }
10717
- return nalUnits2;
10718
- }
10719
- const nalUnits = [];
10720
- let offset = 0;
10721
- while (offset < sample.length) {
10722
- const length = readUintLength(sample, offset, naluLengthSize);
10723
- offset += naluLengthSize;
10724
- const end = offset + length;
10725
- if (end > sample.length) {
10726
- throw new Error("invalid H264 sample length");
10727
- }
10728
- nalUnits.push(sample.subarray(offset, end));
10729
- offset = end;
10730
- }
10731
- return nalUnits;
10732
- }
10733
- function splitAv1Obus(sample) {
10734
- const obus = [];
10735
- let offset = 0;
10736
- while (offset < sample.length) {
10737
- const start = offset;
10738
- const header = sample[offset];
10739
- offset += 1;
10740
- if (header == void 0) {
10741
- break;
10742
- }
10743
- const extensionFlag = getBit(header, 5);
10744
- const hasSizeField = getBit(header, 6);
10745
- if (extensionFlag) {
10746
- offset += 1;
10747
- }
10748
- if (!hasSizeField) {
10749
- obus.push(sample.subarray(start));
10750
- break;
10751
- }
10752
- const [obuSize, leb128Length] = leb128decode(sample.subarray(offset));
10753
- offset += leb128Length;
10754
- const end = offset + obuSize;
10755
- if (end > sample.length) {
10756
- throw new Error("invalid AV1 OBU size");
10757
- }
10758
- obus.push(sample.subarray(start, end));
10759
- offset = end;
10760
- }
10761
- return obus;
10762
- }
10763
- function containsH264ParameterSets(nalUnits) {
10764
- return nalUnits.some((nalUnit) => {
10765
- const nalType = nalUnit[0] & 31;
10766
- return nalType === 7 || nalType === 8;
10767
- });
10768
- }
10769
- function looksLikeAnnexB(sample) {
10770
- return sample.length >= 4 && sample[0] === 0 && sample[1] === 0 && (sample[2] === 0 && sample[3] === 1 || sample[2] === 1);
10771
- }
10772
- function readUintLength(buffer2, offset, length) {
10773
- switch (length) {
10774
- case 1:
10775
- return buffer2.readUInt8(offset);
10776
- case 2:
10777
- return buffer2.readUInt16BE(offset);
10778
- case 3:
10779
- return buffer2.readUIntBE(offset, 3);
10780
- case 4:
10781
- return buffer2.readUInt32BE(offset);
10782
- default:
10783
- throw new Error(`unsupported H264 NALU length size: ${length}`);
10784
- }
10785
- }
10786
- function getH264PacketizationMode(parameters) {
10787
- if (!parameters) {
10788
- return 1;
10789
- }
10790
- const packetizationMode = parameters.split(";").map((part) => part.trim()).find((part) => part.startsWith("packetization-mode="));
10791
- if (!packetizationMode) {
10792
- return 1;
10793
- }
10794
- return Number(packetizationMode.split("=")[1] ?? 1);
10795
- }
10796
- function toDescriptionBuffer(decoderDescription) {
10797
- if (ArrayBuffer.isView(decoderDescription)) {
10798
- return Buffer.from(
10799
- decoderDescription.buffer,
10800
- decoderDescription.byteOffset,
10801
- decoderDescription.byteLength
10802
- );
10803
- }
10804
- return Buffer.from(decoderDescription);
10805
- }
10806
- function toBuffer(data) {
10807
- return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
10808
- }
10809
-
10810
- // src/nonstandard/userMedia.ts
10811
- var getUserMedia = async (options) => {
10812
- assertSupportedOptions(options);
10813
- const replayableSource = await createReplayableSource(options);
10814
- const input = await createInput(replayableSource);
10815
- try {
10816
- if (!await input.canRead()) {
10817
- throw new Error("Only MP4 and WebM file playback is supported");
10818
- }
10819
- const streamId = randomUUID6().toString();
10820
- const playbackTracks = await selectPlaybackTracks(input, streamId);
10821
- if (playbackTracks.length === 0) {
10822
- throw new Error(
10823
- "The media source does not contain playable audio or video tracks"
10824
- );
10825
- }
10826
- const mediaStartTimestamp = await input.getFirstTimestamp(
10827
- playbackTracks.map(({ inputTrack }) => inputTrack)
10828
- );
10829
- return new MediaPlayer({
10830
- source: replayableSource,
10831
- loop: options.loop ?? false,
10832
- streamId,
10833
- session: createPlaybackSession({
10834
- input,
10835
- mediaStartTimestamp,
10836
- playbackTracks
10837
- })
10838
- });
10839
- } catch (error) {
10840
- input.dispose();
10841
- throw error;
10842
- }
10843
- };
10844
- var MediaPlayer = class {
10845
- audio;
10846
- video;
10847
- onError = new Event2();
10848
- source;
10849
- loop;
10850
- streamId;
10851
- session;
10852
- running;
10853
- abortController;
10854
- hasStartedPlayback = false;
10855
- stopped = false;
10856
- constructor({
10857
- source,
10858
- loop,
10859
- streamId,
10860
- session
10861
- }) {
10862
- this.source = source;
10863
- this.loop = loop;
10864
- this.streamId = streamId;
10865
- this.session = session;
10866
- this.audio = session.playbackTracks.find(
10867
- ({ track }) => track.kind === "audio"
10868
- )?.track;
10869
- this.video = session.playbackTracks.find(
10870
- ({ track }) => track.kind === "video"
10871
- )?.track;
10872
- }
10873
- async start() {
10874
- if (this.stopped) {
10875
- throw new Error("The media source has already been stopped");
10876
- }
10877
- if (this.running) {
10878
- return;
10879
- }
10880
- const abortController = new AbortController();
10881
- this.abortController = abortController;
10882
- let startupPending = true;
10883
- let session;
10884
- const playback = (async () => {
10885
- session = await this.getOrCreateSession();
10886
- if (abortController.signal.aborted || this.stopped) {
10887
- return;
10888
- }
10889
- session.runners.forEach((runner) => runner.assertReady());
10890
- const initialSourceChanged = this.hasStartedPlayback;
10891
- this.hasStartedPlayback = true;
10892
- await this.run(session, abortController, initialSourceChanged);
10893
- })();
10894
- const observedPlayback = playback.catch((error) => {
10895
- if (abortController.signal.aborted) {
10896
- return;
10897
- }
10898
- this.onError.execute(toError(error));
10899
- if (startupPending) {
10900
- throw error;
10901
- }
10902
- });
10903
- this.running = observedPlayback.finally(() => {
10904
- if (this.abortController === abortController) {
10905
- this.abortController = void 0;
10906
- }
10907
- this.running = void 0;
10908
- this.disposeSession(session);
10909
- });
10910
- try {
10911
- await Promise.race([this.running, onNextTurn()]);
10912
- } finally {
10913
- startupPending = false;
10914
- }
10915
- }
10916
- stop() {
10917
- if (this.stopped) {
10918
- return;
10919
- }
10920
- this.stopped = true;
10921
- this.abortController?.abort();
10922
- if (!this.running) {
10923
- this.disposeSession();
10924
- }
10925
- }
10926
- async run(session, abortController, initialSourceChanged) {
10927
- let sourceChanged = initialSourceChanged;
10928
- do {
10929
- const startedAt = performance.now();
10930
- await Promise.all(
10931
- session.runners.map(
10932
- (runner) => runner.play({
10933
- startedAt,
10934
- signal: abortController.signal,
10935
- sourceChanged
10936
- })
10937
- )
10938
- );
10939
- if (!this.loop || abortController.signal.aborted) {
10940
- break;
10941
- }
10942
- sourceChanged = true;
10943
- } while (!abortController.signal.aborted);
10944
- }
10945
- async getOrCreateSession() {
10946
- if (this.session) {
10947
- return this.session;
10948
- }
10949
- const input = await createInput(this.source);
10950
- try {
10951
- if (!await input.canRead()) {
10952
- throw new Error("Only MP4 and WebM file playback is supported");
10953
- }
10954
- const playbackTracks = await selectPlaybackTracks(
10955
- input,
10956
- this.streamId,
10957
- buildExistingTrackMap(this.audio, this.video)
10958
- );
10959
- const mediaStartTimestamp = await input.getFirstTimestamp(
10960
- playbackTracks.map(({ inputTrack }) => inputTrack)
10961
- );
10962
- const session = createPlaybackSession({
10963
- input,
10964
- mediaStartTimestamp,
10965
- playbackTracks
10966
- });
10967
- this.session = session;
10968
- return session;
10969
- } catch (error) {
10970
- input.dispose();
10971
- throw error;
10972
- }
10973
- }
10974
- disposeSession(session = this.session) {
10975
- if (!session) {
10976
- return;
10977
- }
10978
- session.input.dispose();
10979
- if (this.session === session) {
10980
- this.session = void 0;
10981
- }
10982
- }
10983
- };
10984
- var TrackPlaybackRunner = class {
10985
- constructor(props) {
10986
- this.props = props;
10987
- }
10988
- async play({
10989
- startedAt,
10990
- signal,
10991
- sourceChanged
10992
- }) {
10993
- const codec = this.requireNegotiatedCodec();
10994
- const packetizer = createPacketizer({
10995
- codec,
10996
- sourceCodec: this.props.sourceCodec,
10997
- decoderDescription: this.props.decoderDescription
10998
- });
10999
- const packetSink = new EncodedPacketSink(this.props.inputTrack);
11000
- let sourceChangeNotified = false;
11001
- try {
11002
- for await (const packet of packetSink.packets(void 0, void 0, {
11003
- verifyKeyPackets: this.props.track.kind === "video"
11004
- })) {
11005
- signal.throwIfAborted?.();
11006
- const dueAtMs = (packet.timestamp - this.props.mediaStartTimestamp) * 1e3;
11007
- const remainingMs = dueAtMs - (performance.now() - startedAt);
11008
- if (remainingMs > 0) {
11009
- await wait(remainingMs, void 0, { signal });
11010
- }
11011
- const rtpTimestamp = toRtpTimestamp(
11012
- packet.timestamp,
11013
- this.props.mediaStartTimestamp,
11014
- codec.clockRate
11015
- );
11016
- const packets = packetizer.packetize(packet, rtpTimestamp);
11017
- if (packets.length === 0) {
11018
- continue;
11019
- }
11020
- if (sourceChanged && !sourceChangeNotified) {
11021
- this.props.track.onSourceChanged.execute(packets[0].header);
11022
- sourceChangeNotified = true;
11023
- }
11024
- for (const rtpPacket of packets) {
11025
- this.props.track.writeRtp(rtpPacket);
11026
- }
11027
- }
11028
- } catch (error) {
11029
- if (signal.aborted || isAbortError(error)) {
11030
- return;
11031
- }
11032
- throw error;
11033
- }
11034
- }
11035
- assertReady() {
11036
- const codec = this.requireNegotiatedCodec();
11037
- createPacketizer({
11038
- codec,
11039
- sourceCodec: this.props.sourceCodec,
11040
- decoderDescription: this.props.decoderDescription
11041
- });
11042
- }
11043
- requireNegotiatedCodec() {
11044
- const codec = this.props.track.codec;
11045
- if (!codec) {
11046
- throw new Error(
11047
- `Cannot start ${this.props.track.kind} playback before the track is attached to an RTCRtpSender`
11048
- );
11049
- }
11050
- const expectedMimeType = toSupportedMimeType(this.props.sourceCodec);
11051
- const negotiatedMimeType = normalizeMimeType(codec.mimeType);
11052
- if (negotiatedMimeType !== expectedMimeType) {
11053
- throw new Error(
11054
- `Input ${this.props.track.kind} codec ${expectedMimeType} does not match negotiated codec ${codec.mimeType}`
11055
- );
11056
- }
11057
- const expectedClockRate = this.props.track.kind === "audio" ? 48e3 : 9e4;
11058
- if (codec.clockRate !== expectedClockRate) {
11059
- throw new Error(
11060
- `Input ${this.props.track.kind} clock rate ${expectedClockRate} does not match negotiated clock rate ${codec.clockRate}`
11061
- );
11062
- }
11063
- assertCodecParameters({
11064
- trackKind: this.props.track.kind === "audio" ? "audio" : "video",
11065
- codec,
11066
- sourceCodec: this.props.sourceCodec,
11067
- decoderDescription: this.props.decoderDescription,
11068
- sourceChannels: this.props.sourceChannels
11069
- });
11070
- return codec;
11071
- }
11072
- };
11073
- async function selectPlaybackTracks(input, streamId, existingTracks = {}) {
11074
- const primaryVideoTrack = await input.getPrimaryVideoTrack();
11075
- const primaryAudioTrack = primaryVideoTrack ? await primaryVideoTrack.getPrimaryPairableAudioTrack() ?? await input.getPrimaryAudioTrack() : await input.getPrimaryAudioTrack();
11076
- const playbackTracks = [];
11077
- if (primaryAudioTrack) {
11078
- playbackTracks.push(
11079
- await createPlaybackTrack(
11080
- primaryAudioTrack,
11081
- streamId,
11082
- existingTracks.audio
11083
- )
11084
- );
11085
- }
11086
- if (primaryVideoTrack) {
11087
- playbackTracks.push(
11088
- await createPlaybackTrack(
11089
- primaryVideoTrack,
11090
- streamId,
11091
- existingTracks.video
11092
- )
11093
- );
11094
- }
11095
- if (!primaryVideoTrack && !primaryAudioTrack) {
11096
- const fallbackAudioTrack = await input.getPrimaryAudioTrack();
11097
- if (fallbackAudioTrack) {
11098
- playbackTracks.push(
11099
- await createPlaybackTrack(
11100
- fallbackAudioTrack,
11101
- streamId,
11102
- existingTracks.audio
11103
- )
11104
- );
11105
- }
11106
- }
11107
- return playbackTracks;
11108
- }
11109
- async function createPlaybackTrack(inputTrack, streamId, track) {
11110
- const sourceCodec = await requireSupportedCodec(inputTrack);
11111
- const decoderConfig = await inputTrack.getDecoderConfig();
11112
- const kind = inputTrack.isAudioTrack() ? "audio" : "video";
11113
- return {
11114
- inputTrack,
11115
- sourceCodec,
11116
- decoderDescription: decoderConfig && "description" in decoderConfig ? decoderConfig.description ?? null : null,
11117
- sourceChannels: decoderConfig && "numberOfChannels" in decoderConfig ? decoderConfig.numberOfChannels : void 0,
11118
- track: track ?? new MediaStreamTrack({
11119
- kind,
11120
- streamId
11121
- })
11122
- };
11123
- }
11124
- async function requireSupportedCodec(inputTrack) {
11125
- const codec = await inputTrack.getCodec();
11126
- if (codec && supportedSourceCodecs.includes(codec)) {
11127
- return codec;
11128
- }
11129
- const codecLabel = codec ?? await inputTrack.getCodecParameterString() ?? String(await inputTrack.getInternalCodecId() ?? "unknown");
11130
- throw new Error(
11131
- `Unsupported ${inputTrack.type} codec "${codecLabel}". File playback supports H264, VP8, VP9, AV1, and Opus only.`
11132
- );
11133
- }
11134
- async function createReplayableSource(options) {
11135
- if (typeof options.path === "string") {
11136
- return { path: options.path };
11137
- }
11138
- const buffer2 = options.buffer != void 0 ? toBuffer2(options.buffer) : await readStreamToBuffer(options.stream);
11139
- return { buffer: buffer2 };
11140
- }
11141
- async function createInput(options) {
11142
- if (typeof options.path === "string") {
11143
- const buffer2 = await readFile(resolveUserMediaPath(options.path));
11144
- return new Input({
11145
- source: new BufferSource(buffer2),
11146
- formats: [MP4, WEBM]
11147
- });
11148
- }
11149
- return new Input({
11150
- source: new BufferSource(options.buffer),
11151
- formats: [MP4, WEBM]
11152
- });
11153
- }
11154
- function resolveUserMediaPath(path2) {
11155
- if (path2 === "~") {
11156
- return homedir();
11157
- }
11158
- if (path2.startsWith("~/")) {
11159
- return resolve(homedir(), path2.slice(2));
11160
- }
11161
- return isAbsolute(path2) ? path2 : resolve(path2);
11162
- }
11163
- async function readStreamToBuffer(stream) {
11164
- const chunks = [];
11165
- if (stream instanceof Readable) {
11166
- for await (const chunk of stream) {
11167
- chunks.push(toBuffer2(chunk));
11168
- }
11169
- return Buffer.concat(chunks);
11170
- }
11171
- const reader = stream.getReader();
11172
- try {
11173
- for (; ; ) {
11174
- const { done, value } = await reader.read();
11175
- if (done) {
11176
- break;
11177
- }
11178
- if (value) {
11179
- chunks.push(
11180
- Buffer.from(value.buffer, value.byteOffset, value.byteLength)
11181
- );
11182
- }
11183
- }
11184
- } finally {
11185
- reader.releaseLock();
11186
- }
11187
- return Buffer.concat(chunks);
11188
- }
11189
- function toBuffer2(value) {
11190
- if (Buffer.isBuffer(value)) {
11191
- return value;
11192
- }
11193
- if (typeof value === "string") {
11194
- return Buffer.from(value);
11195
- }
11196
- if (ArrayBuffer.isView(value)) {
11197
- return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
11198
- }
11199
- return Buffer.from(new Uint8Array(value));
11200
- }
11201
- function normalizeMimeType(mimeType) {
11202
- return mimeType.toLowerCase();
11203
- }
11204
- function assertSupportedOptions(options) {
11205
- const legacyOptions = options;
11206
- if (legacyOptions.width != void 0 || legacyOptions.height != void 0) {
11207
- throw new Error(
11208
- "getUserMedia({ width, height }) is no longer supported for file playback. Resize or re-encode the source before calling getUserMedia()."
11209
- );
11210
- }
11211
- }
11212
- function createPlaybackSession({
11213
- input,
11214
- mediaStartTimestamp,
11215
- playbackTracks
11216
- }) {
11217
- return {
11218
- input,
11219
- mediaStartTimestamp,
11220
- playbackTracks,
11221
- runners: playbackTracks.map(
11222
- (playbackTrack) => new TrackPlaybackRunner({
11223
- mediaStartTimestamp,
11224
- ...playbackTrack
11225
- })
11226
- )
11227
- };
11228
- }
11229
- function buildExistingTrackMap(audio, video) {
11230
- return {
11231
- ...audio ? { audio } : {},
11232
- ...video ? { video } : {}
11233
- };
11234
- }
11235
- function assertCodecParameters({
11236
- trackKind,
11237
- codec,
11238
- sourceCodec,
11239
- decoderDescription,
11240
- sourceChannels
11241
- }) {
11242
- if (sourceCodec === "opus" && sourceChannels && codec.channels != void 0) {
11243
- if (codec.channels !== sourceChannels) {
11244
- throw new Error(
11245
- `Input ${trackKind} channels ${sourceChannels} do not match negotiated channels ${codec.channels}`
11246
- );
11247
- }
11248
- return;
11249
- }
11250
- if (sourceCodec !== "avc") {
11251
- return;
11252
- }
11253
- const negotiatedParameters = codecParametersFromString(
11254
- codec.parameters ?? ""
11255
- );
11256
- const negotiatedPacketizationMode = Number(
11257
- negotiatedParameters["packetization-mode"] ?? 1
11258
- );
11259
- if (negotiatedPacketizationMode !== 1) {
11260
- throw new Error(
11261
- `Input ${trackKind} packetization-mode 1 does not match negotiated packetization-mode ${negotiatedPacketizationMode}`
11262
- );
11263
- }
11264
- const sourceProfileLevelId = getH264ProfileLevelId(decoderDescription);
11265
- const negotiatedProfileLevelId = normalizeOptionalHexParameter(
11266
- negotiatedParameters["profile-level-id"]
11267
- );
11268
- if (!sourceProfileLevelId) {
11269
- return;
11270
- }
11271
- if (!negotiatedProfileLevelId) {
11272
- throw new Error(
11273
- `Input ${trackKind} profile-level-id ${sourceProfileLevelId} does not match negotiated profile-level-id <missing>`
11274
- );
11275
- }
11276
- if (sourceProfileLevelId !== negotiatedProfileLevelId) {
11277
- throw new Error(
11278
- `Input ${trackKind} profile-level-id ${sourceProfileLevelId} does not match negotiated profile-level-id ${negotiatedProfileLevelId}`
11279
- );
11280
- }
11281
- }
11282
- function getH264ProfileLevelId(decoderDescription) {
11283
- if (!decoderDescription) {
11284
- return void 0;
11285
- }
11286
- const description = toDescriptionBuffer2(decoderDescription);
11287
- if (description.length < 4) {
11288
- throw new Error("invalid H264 decoder configuration");
11289
- }
11290
- return description.subarray(1, 4).toString("hex");
11291
- }
11292
- function normalizeOptionalHexParameter(value) {
11293
- return typeof value === "string" ? value.toLowerCase() : void 0;
11294
- }
11295
- function toRtpTimestamp(packetTimestamp, mediaStartTimestamp, clockRate) {
11296
- const relativeSeconds = Math.max(0, packetTimestamp - mediaStartTimestamp);
11297
- return Math.round(relativeSeconds * clockRate) >>> 0;
11298
- }
11299
- function isAbortError(error) {
11300
- return error instanceof Error && (error.name === "AbortError" || error.message === "The operation was aborted");
11301
- }
11302
- function toError(error) {
11303
- return error instanceof Error ? error : new Error(String(error));
11304
- }
11305
- function toDescriptionBuffer2(decoderDescription) {
11306
- if (ArrayBuffer.isView(decoderDescription)) {
11307
- return Buffer.from(
11308
- decoderDescription.buffer,
11309
- decoderDescription.byteOffset,
11310
- decoderDescription.byteLength
11311
- );
11312
- }
11313
- return Buffer.from(decoderDescription);
11314
- }
11315
10599
  export {
11316
10600
  AV1Obu,
11317
10601
  AV1RtpPayload,
@@ -11451,7 +10735,6 @@ export {
11451
10735
  getEBMLByteLength,
11452
10736
  getNumberByteLength,
11453
10737
  getSizeMask,
11454
- getUserMedia,
11455
10738
  growBufferSize,
11456
10739
  int,
11457
10740
  int16Bit,