@daydreamlive/browser 0.3.0 → 0.3.2

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.js CHANGED
@@ -1,4 +1,4 @@
1
- // src/types.ts
1
+ // src/types/common.ts
2
2
  var DEFAULT_ICE_SERVERS = [
3
3
  { urls: "stun:stun.l.google.com:19302" },
4
4
  { urls: "stun:stun1.l.google.com:19302" },
@@ -9,6 +9,12 @@ var DEFAULT_AUDIO_BITRATE = 64e3;
9
9
 
10
10
  // src/errors.ts
11
11
  var BaseDaydreamError = class extends Error {
12
+ /**
13
+ * Creates a new DaydreamError.
14
+ * @param code - Error code
15
+ * @param message - Human-readable error message
16
+ * @param cause - Optional underlying cause
17
+ */
12
18
  constructor(code, message, cause) {
13
19
  super(message);
14
20
  this.name = "DaydreamError";
@@ -417,7 +423,7 @@ var TypedEventEmitter = class {
417
423
  this.listeners.set(event, /* @__PURE__ */ new Set());
418
424
  }
419
425
  this.listeners.get(event).add(handler);
420
- return this;
426
+ return () => this.off(event, handler);
421
427
  }
422
428
  off(event, handler) {
423
429
  this.listeners.get(event)?.delete(handler);
@@ -467,6 +473,10 @@ var BROADCAST_TRANSITIONS = {
467
473
  error: ["connecting"]
468
474
  };
469
475
  var Broadcast = class extends TypedEventEmitter {
476
+ /**
477
+ * Creates a new Broadcast instance.
478
+ * @param config - Broadcast configuration
479
+ */
470
480
  constructor(config) {
471
481
  super();
472
482
  this._whepUrl = null;
@@ -489,15 +499,19 @@ var Broadcast = class extends TypedEventEmitter {
489
499
  (_from, to) => this.emit("stateChange", to)
490
500
  );
491
501
  }
502
+ /** Current broadcast state. */
492
503
  get state() {
493
504
  return this.stateMachine.current;
494
505
  }
506
+ /** WHEP playback URL for viewers, available after connecting. */
495
507
  get whepUrl() {
496
508
  return this._whepUrl;
497
509
  }
510
+ /** The MediaStream being broadcast. */
498
511
  get stream() {
499
512
  return this.currentStream;
500
513
  }
514
+ /** Information about the current reconnection attempt, or null if not reconnecting. */
501
515
  get reconnectInfo() {
502
516
  if (this.state !== "reconnecting") return null;
503
517
  const baseDelay = this.reconnectConfig.baseDelayMs ?? 1e3;
@@ -508,6 +522,10 @@ var Broadcast = class extends TypedEventEmitter {
508
522
  delayMs: delay
509
523
  };
510
524
  }
525
+ /**
526
+ * Establishes the WebRTC connection and starts broadcasting.
527
+ * @throws {DaydreamError} If connection fails
528
+ */
511
529
  async connect() {
512
530
  try {
513
531
  const result = await this.whipClient.connect(this.currentStream);
@@ -523,15 +541,28 @@ var Broadcast = class extends TypedEventEmitter {
523
541
  throw daydreamError;
524
542
  }
525
543
  }
544
+ /**
545
+ * Stops the broadcast and disconnects.
546
+ * After calling this, the instance cannot be reused.
547
+ */
526
548
  async stop() {
527
549
  this.stateMachine.force("ended");
528
550
  this.clearTimeouts();
529
551
  await this.whipClient.disconnect();
530
552
  this.clearListeners();
531
553
  }
554
+ /**
555
+ * Sets the maximum frame rate for the video track.
556
+ * @param fps - Maximum frame rate, or undefined to remove the limit
557
+ */
532
558
  setMaxFramerate(fps) {
533
559
  this.whipClient.setMaxFramerate(fps);
534
560
  }
561
+ /**
562
+ * Replaces the current MediaStream with a new one.
563
+ * The tracks are replaced in-place if connected, otherwise just stored.
564
+ * @param newStream - The new MediaStream to use
565
+ */
535
566
  async replaceStream(newStream) {
536
567
  if (!this.whipClient.isConnected()) {
537
568
  this.currentStream = newStream;
@@ -863,6 +894,10 @@ var PLAYER_TRANSITIONS = {
863
894
  error: ["connecting"]
864
895
  };
865
896
  var Player = class extends TypedEventEmitter {
897
+ /**
898
+ * Creates a new Player instance.
899
+ * @param config - Player configuration
900
+ */
866
901
  constructor(config) {
867
902
  super();
868
903
  this._stream = null;
@@ -886,12 +921,15 @@ var Player = class extends TypedEventEmitter {
886
921
  (_from, to) => this.emit("stateChange", to)
887
922
  );
888
923
  }
924
+ /** Current player state. */
889
925
  get state() {
890
926
  return this.stateMachine.current;
891
927
  }
928
+ /** The received MediaStream, or null if not connected. */
892
929
  get stream() {
893
930
  return this._stream;
894
931
  }
932
+ /** Information about the current reconnection attempt, or null if not buffering. */
895
933
  get reconnectInfo() {
896
934
  if (this.state !== "buffering") return null;
897
935
  const baseDelay = this.reconnectConfig.baseDelayMs ?? 200;
@@ -905,6 +943,10 @@ var Player = class extends TypedEventEmitter {
905
943
  delayMs: delay
906
944
  };
907
945
  }
946
+ /**
947
+ * Establishes the WebRTC connection and starts receiving the stream.
948
+ * @throws {DaydreamError} If connection fails after all retry attempts
949
+ */
908
950
  async connect() {
909
951
  try {
910
952
  this._stream = await this.whepClient.connect();
@@ -922,11 +964,19 @@ var Player = class extends TypedEventEmitter {
922
964
  throw daydreamError;
923
965
  }
924
966
  }
967
+ /**
968
+ * Attaches the received stream to a video element.
969
+ * @param video - The HTMLVideoElement to display the stream
970
+ */
925
971
  attachTo(video) {
926
972
  if (this._stream) {
927
973
  video.srcObject = this._stream;
928
974
  }
929
975
  }
976
+ /**
977
+ * Stops playback and disconnects.
978
+ * After calling this, the instance cannot be reused.
979
+ */
930
980
  async stop() {
931
981
  this.stateMachine.force("ended");
932
982
  this.clearTimeouts();
@@ -1784,30 +1834,7 @@ function createVisibilityHandler(options) {
1784
1834
  }
1785
1835
 
1786
1836
  // src/Compositor.ts
1787
- var CompositorEventEmitter = class {
1788
- constructor() {
1789
- this.listeners = /* @__PURE__ */ new Map();
1790
- }
1791
- on(event, handler) {
1792
- if (!this.listeners.has(event)) {
1793
- this.listeners.set(event, /* @__PURE__ */ new Set());
1794
- }
1795
- this.listeners.get(event).add(handler);
1796
- return () => this.off(event, handler);
1797
- }
1798
- off(event, handler) {
1799
- this.listeners.get(event)?.delete(handler);
1800
- }
1801
- emit(event, ...args) {
1802
- this.listeners.get(event)?.forEach((handler) => {
1803
- handler(...args);
1804
- });
1805
- }
1806
- clearListeners() {
1807
- this.listeners.clear();
1808
- }
1809
- };
1810
- var Compositor = class extends CompositorEventEmitter {
1837
+ var Compositor = class extends TypedEventEmitter {
1811
1838
  constructor(options = {}) {
1812
1839
  super();
1813
1840
  this._activeId = null;
@@ -1875,10 +1902,20 @@ var Compositor = class extends CompositorEventEmitter {
1875
1902
  // ============================================================================
1876
1903
  // Source Registry
1877
1904
  // ============================================================================
1905
+ /**
1906
+ * Registers a source with a unique ID.
1907
+ * @param id - Unique identifier for the source
1908
+ * @param source - The source configuration (video or canvas element)
1909
+ */
1878
1910
  register(id, source) {
1879
1911
  if (this.destroyed) return;
1880
1912
  this.registry.register(id, source);
1881
1913
  }
1914
+ /**
1915
+ * Unregisters a source by ID.
1916
+ * If the source is currently active, it will be deactivated first.
1917
+ * @param id - The source ID to unregister
1918
+ */
1882
1919
  unregister(id) {
1883
1920
  if (this.destroyed) return;
1884
1921
  const wasActive = this._activeId === id;
@@ -1890,18 +1927,38 @@ var Compositor = class extends CompositorEventEmitter {
1890
1927
  this.emit("activated", null, void 0);
1891
1928
  }
1892
1929
  }
1930
+ /**
1931
+ * Gets a registered source by ID.
1932
+ * @param id - The source ID
1933
+ * @returns The source, or undefined if not found
1934
+ */
1893
1935
  get(id) {
1894
1936
  return this.registry.get(id);
1895
1937
  }
1938
+ /**
1939
+ * Checks if a source is registered.
1940
+ * @param id - The source ID to check
1941
+ * @returns True if the source is registered
1942
+ */
1896
1943
  has(id) {
1897
1944
  return this.registry.has(id);
1898
1945
  }
1946
+ /**
1947
+ * Lists all registered sources.
1948
+ * @returns Array of source entries with id and source
1949
+ */
1899
1950
  list() {
1900
1951
  return this.registry.list();
1901
1952
  }
1902
1953
  // ============================================================================
1903
1954
  // Active Source Management
1904
1955
  // ============================================================================
1956
+ /**
1957
+ * Activates a registered source for rendering.
1958
+ * Only one source can be active at a time.
1959
+ * @param id - The source ID to activate
1960
+ * @throws {Error} If the source is not registered
1961
+ */
1905
1962
  activate(id) {
1906
1963
  if (this.destroyed) return;
1907
1964
  const source = this.registry.get(id);
@@ -1914,6 +1971,10 @@ var Compositor = class extends CompositorEventEmitter {
1914
1971
  this.scheduler.start(videoEl);
1915
1972
  this.emit("activated", id, source);
1916
1973
  }
1974
+ /**
1975
+ * Deactivates the current source.
1976
+ * The compositor will stop rendering until another source is activated.
1977
+ */
1917
1978
  deactivate() {
1918
1979
  if (this.destroyed) return;
1919
1980
  this._activeId = null;
@@ -1921,18 +1982,27 @@ var Compositor = class extends CompositorEventEmitter {
1921
1982
  this.scheduler.stop();
1922
1983
  this.emit("activated", null, void 0);
1923
1984
  }
1985
+ /** ID of the currently active source, or null if none. */
1924
1986
  get activeId() {
1925
1987
  return this._activeId;
1926
1988
  }
1927
1989
  // ============================================================================
1928
1990
  // Output Stream
1929
1991
  // ============================================================================
1992
+ /** The composited output MediaStream. Can be used with Broadcast or other consumers. */
1930
1993
  get stream() {
1931
1994
  return this.outputStream;
1932
1995
  }
1933
1996
  // ============================================================================
1934
1997
  // Settings
1935
1998
  // ============================================================================
1999
+ /**
2000
+ * Resizes the output canvas.
2001
+ * This recreates the output stream, so consumers may need to be updated.
2002
+ * @param width - New width in logical pixels
2003
+ * @param height - New height in logical pixels
2004
+ * @param dpr - Optional device pixel ratio (defaults to window.devicePixelRatio, capped at 2)
2005
+ */
1936
2006
  resize(width, height, dpr) {
1937
2007
  if (this.destroyed) return;
1938
2008
  const effectiveDpr = Math.min(
@@ -1942,9 +2012,15 @@ var Compositor = class extends CompositorEventEmitter {
1942
2012
  this.renderer.resize(width, height, effectiveDpr);
1943
2013
  this.recreateStream();
1944
2014
  }
2015
+ /** Current output size configuration. */
1945
2016
  get size() {
1946
2017
  return this.renderer.size;
1947
2018
  }
2019
+ /**
2020
+ * Sets the rendering frame rate.
2021
+ * This recreates the output stream, so consumers may need to be updated.
2022
+ * @param fps - Frame rate (minimum 1)
2023
+ */
1948
2024
  setFps(fps) {
1949
2025
  if (this.destroyed) return;
1950
2026
  const next = Math.max(1, fps);
@@ -1953,9 +2029,15 @@ var Compositor = class extends CompositorEventEmitter {
1953
2029
  this.scheduler.setFps(next);
1954
2030
  this.recreateStream();
1955
2031
  }
2032
+ /** Current rendering frame rate. */
1956
2033
  get fps() {
1957
2034
  return this._fps;
1958
2035
  }
2036
+ /**
2037
+ * Sets the frame rate for sending to the stream.
2038
+ * Can be different from the rendering FPS (e.g., render at 60fps, send at 30fps).
2039
+ * @param fps - Frame rate (minimum 1)
2040
+ */
1959
2041
  setSendFps(fps) {
1960
2042
  if (this.destroyed) return;
1961
2043
  const next = Math.max(1, fps);
@@ -1963,20 +2045,34 @@ var Compositor = class extends CompositorEventEmitter {
1963
2045
  this._sendFps = next;
1964
2046
  this.scheduler.setSendFps(next);
1965
2047
  }
2048
+ /** Current send frame rate. */
1966
2049
  get sendFps() {
1967
2050
  return this._sendFps;
1968
2051
  }
1969
2052
  // ============================================================================
1970
2053
  // Audio
1971
2054
  // ============================================================================
2055
+ /**
2056
+ * Adds an audio track to the output stream.
2057
+ * @param track - The MediaStreamTrack to add (must be an audio track)
2058
+ */
1972
2059
  addAudioTrack(track) {
1973
2060
  if (this.destroyed) return;
1974
2061
  this.audioManager.addTrack(track);
1975
2062
  }
2063
+ /**
2064
+ * Removes an audio track from the output stream.
2065
+ * @param trackId - The track ID to remove
2066
+ */
1976
2067
  removeAudioTrack(trackId) {
1977
2068
  if (this.destroyed) return;
1978
2069
  this.audioManager.removeTrack(trackId);
1979
2070
  }
2071
+ /**
2072
+ * Manually unlocks the audio context.
2073
+ * Usually not needed as audio is auto-unlocked on user interaction.
2074
+ * @returns True if the audio context was successfully unlocked
2075
+ */
1980
2076
  unlockAudio() {
1981
2077
  if (this.destroyed) return Promise.resolve(false);
1982
2078
  return this.audioManager.unlock();
@@ -1984,6 +2080,10 @@ var Compositor = class extends CompositorEventEmitter {
1984
2080
  // ============================================================================
1985
2081
  // Lifecycle
1986
2082
  // ============================================================================
2083
+ /**
2084
+ * Destroys the compositor and releases all resources.
2085
+ * After calling this, the instance cannot be reused.
2086
+ */
1987
2087
  destroy() {
1988
2088
  if (this.destroyed) return;
1989
2089
  this.destroyed = true;