@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.cjs CHANGED
@@ -37,7 +37,7 @@ __export(index_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(index_exports);
39
39
 
40
- // src/types.ts
40
+ // src/types/common.ts
41
41
  var DEFAULT_ICE_SERVERS = [
42
42
  { urls: "stun:stun.l.google.com:19302" },
43
43
  { urls: "stun:stun1.l.google.com:19302" },
@@ -48,6 +48,12 @@ var DEFAULT_AUDIO_BITRATE = 64e3;
48
48
 
49
49
  // src/errors.ts
50
50
  var BaseDaydreamError = class extends Error {
51
+ /**
52
+ * Creates a new DaydreamError.
53
+ * @param code - Error code
54
+ * @param message - Human-readable error message
55
+ * @param cause - Optional underlying cause
56
+ */
51
57
  constructor(code, message, cause) {
52
58
  super(message);
53
59
  this.name = "DaydreamError";
@@ -456,7 +462,7 @@ var TypedEventEmitter = class {
456
462
  this.listeners.set(event, /* @__PURE__ */ new Set());
457
463
  }
458
464
  this.listeners.get(event).add(handler);
459
- return this;
465
+ return () => this.off(event, handler);
460
466
  }
461
467
  off(event, handler) {
462
468
  this.listeners.get(event)?.delete(handler);
@@ -506,6 +512,10 @@ var BROADCAST_TRANSITIONS = {
506
512
  error: ["connecting"]
507
513
  };
508
514
  var Broadcast = class extends TypedEventEmitter {
515
+ /**
516
+ * Creates a new Broadcast instance.
517
+ * @param config - Broadcast configuration
518
+ */
509
519
  constructor(config) {
510
520
  super();
511
521
  this._whepUrl = null;
@@ -528,15 +538,19 @@ var Broadcast = class extends TypedEventEmitter {
528
538
  (_from, to) => this.emit("stateChange", to)
529
539
  );
530
540
  }
541
+ /** Current broadcast state. */
531
542
  get state() {
532
543
  return this.stateMachine.current;
533
544
  }
545
+ /** WHEP playback URL for viewers, available after connecting. */
534
546
  get whepUrl() {
535
547
  return this._whepUrl;
536
548
  }
549
+ /** The MediaStream being broadcast. */
537
550
  get stream() {
538
551
  return this.currentStream;
539
552
  }
553
+ /** Information about the current reconnection attempt, or null if not reconnecting. */
540
554
  get reconnectInfo() {
541
555
  if (this.state !== "reconnecting") return null;
542
556
  const baseDelay = this.reconnectConfig.baseDelayMs ?? 1e3;
@@ -547,6 +561,10 @@ var Broadcast = class extends TypedEventEmitter {
547
561
  delayMs: delay
548
562
  };
549
563
  }
564
+ /**
565
+ * Establishes the WebRTC connection and starts broadcasting.
566
+ * @throws {DaydreamError} If connection fails
567
+ */
550
568
  async connect() {
551
569
  try {
552
570
  const result = await this.whipClient.connect(this.currentStream);
@@ -562,15 +580,28 @@ var Broadcast = class extends TypedEventEmitter {
562
580
  throw daydreamError;
563
581
  }
564
582
  }
583
+ /**
584
+ * Stops the broadcast and disconnects.
585
+ * After calling this, the instance cannot be reused.
586
+ */
565
587
  async stop() {
566
588
  this.stateMachine.force("ended");
567
589
  this.clearTimeouts();
568
590
  await this.whipClient.disconnect();
569
591
  this.clearListeners();
570
592
  }
593
+ /**
594
+ * Sets the maximum frame rate for the video track.
595
+ * @param fps - Maximum frame rate, or undefined to remove the limit
596
+ */
571
597
  setMaxFramerate(fps) {
572
598
  this.whipClient.setMaxFramerate(fps);
573
599
  }
600
+ /**
601
+ * Replaces the current MediaStream with a new one.
602
+ * The tracks are replaced in-place if connected, otherwise just stored.
603
+ * @param newStream - The new MediaStream to use
604
+ */
574
605
  async replaceStream(newStream) {
575
606
  if (!this.whipClient.isConnected()) {
576
607
  this.currentStream = newStream;
@@ -902,6 +933,10 @@ var PLAYER_TRANSITIONS = {
902
933
  error: ["connecting"]
903
934
  };
904
935
  var Player = class extends TypedEventEmitter {
936
+ /**
937
+ * Creates a new Player instance.
938
+ * @param config - Player configuration
939
+ */
905
940
  constructor(config) {
906
941
  super();
907
942
  this._stream = null;
@@ -925,12 +960,15 @@ var Player = class extends TypedEventEmitter {
925
960
  (_from, to) => this.emit("stateChange", to)
926
961
  );
927
962
  }
963
+ /** Current player state. */
928
964
  get state() {
929
965
  return this.stateMachine.current;
930
966
  }
967
+ /** The received MediaStream, or null if not connected. */
931
968
  get stream() {
932
969
  return this._stream;
933
970
  }
971
+ /** Information about the current reconnection attempt, or null if not buffering. */
934
972
  get reconnectInfo() {
935
973
  if (this.state !== "buffering") return null;
936
974
  const baseDelay = this.reconnectConfig.baseDelayMs ?? 200;
@@ -944,6 +982,10 @@ var Player = class extends TypedEventEmitter {
944
982
  delayMs: delay
945
983
  };
946
984
  }
985
+ /**
986
+ * Establishes the WebRTC connection and starts receiving the stream.
987
+ * @throws {DaydreamError} If connection fails after all retry attempts
988
+ */
947
989
  async connect() {
948
990
  try {
949
991
  this._stream = await this.whepClient.connect();
@@ -961,11 +1003,19 @@ var Player = class extends TypedEventEmitter {
961
1003
  throw daydreamError;
962
1004
  }
963
1005
  }
1006
+ /**
1007
+ * Attaches the received stream to a video element.
1008
+ * @param video - The HTMLVideoElement to display the stream
1009
+ */
964
1010
  attachTo(video) {
965
1011
  if (this._stream) {
966
1012
  video.srcObject = this._stream;
967
1013
  }
968
1014
  }
1015
+ /**
1016
+ * Stops playback and disconnects.
1017
+ * After calling this, the instance cannot be reused.
1018
+ */
969
1019
  async stop() {
970
1020
  this.stateMachine.force("ended");
971
1021
  this.clearTimeouts();
@@ -1823,30 +1873,7 @@ function createVisibilityHandler(options) {
1823
1873
  }
1824
1874
 
1825
1875
  // src/Compositor.ts
1826
- var CompositorEventEmitter = class {
1827
- constructor() {
1828
- this.listeners = /* @__PURE__ */ new Map();
1829
- }
1830
- on(event, handler) {
1831
- if (!this.listeners.has(event)) {
1832
- this.listeners.set(event, /* @__PURE__ */ new Set());
1833
- }
1834
- this.listeners.get(event).add(handler);
1835
- return () => this.off(event, handler);
1836
- }
1837
- off(event, handler) {
1838
- this.listeners.get(event)?.delete(handler);
1839
- }
1840
- emit(event, ...args) {
1841
- this.listeners.get(event)?.forEach((handler) => {
1842
- handler(...args);
1843
- });
1844
- }
1845
- clearListeners() {
1846
- this.listeners.clear();
1847
- }
1848
- };
1849
- var Compositor = class extends CompositorEventEmitter {
1876
+ var Compositor = class extends TypedEventEmitter {
1850
1877
  constructor(options = {}) {
1851
1878
  super();
1852
1879
  this._activeId = null;
@@ -1914,10 +1941,20 @@ var Compositor = class extends CompositorEventEmitter {
1914
1941
  // ============================================================================
1915
1942
  // Source Registry
1916
1943
  // ============================================================================
1944
+ /**
1945
+ * Registers a source with a unique ID.
1946
+ * @param id - Unique identifier for the source
1947
+ * @param source - The source configuration (video or canvas element)
1948
+ */
1917
1949
  register(id, source) {
1918
1950
  if (this.destroyed) return;
1919
1951
  this.registry.register(id, source);
1920
1952
  }
1953
+ /**
1954
+ * Unregisters a source by ID.
1955
+ * If the source is currently active, it will be deactivated first.
1956
+ * @param id - The source ID to unregister
1957
+ */
1921
1958
  unregister(id) {
1922
1959
  if (this.destroyed) return;
1923
1960
  const wasActive = this._activeId === id;
@@ -1929,18 +1966,38 @@ var Compositor = class extends CompositorEventEmitter {
1929
1966
  this.emit("activated", null, void 0);
1930
1967
  }
1931
1968
  }
1969
+ /**
1970
+ * Gets a registered source by ID.
1971
+ * @param id - The source ID
1972
+ * @returns The source, or undefined if not found
1973
+ */
1932
1974
  get(id) {
1933
1975
  return this.registry.get(id);
1934
1976
  }
1977
+ /**
1978
+ * Checks if a source is registered.
1979
+ * @param id - The source ID to check
1980
+ * @returns True if the source is registered
1981
+ */
1935
1982
  has(id) {
1936
1983
  return this.registry.has(id);
1937
1984
  }
1985
+ /**
1986
+ * Lists all registered sources.
1987
+ * @returns Array of source entries with id and source
1988
+ */
1938
1989
  list() {
1939
1990
  return this.registry.list();
1940
1991
  }
1941
1992
  // ============================================================================
1942
1993
  // Active Source Management
1943
1994
  // ============================================================================
1995
+ /**
1996
+ * Activates a registered source for rendering.
1997
+ * Only one source can be active at a time.
1998
+ * @param id - The source ID to activate
1999
+ * @throws {Error} If the source is not registered
2000
+ */
1944
2001
  activate(id) {
1945
2002
  if (this.destroyed) return;
1946
2003
  const source = this.registry.get(id);
@@ -1953,6 +2010,10 @@ var Compositor = class extends CompositorEventEmitter {
1953
2010
  this.scheduler.start(videoEl);
1954
2011
  this.emit("activated", id, source);
1955
2012
  }
2013
+ /**
2014
+ * Deactivates the current source.
2015
+ * The compositor will stop rendering until another source is activated.
2016
+ */
1956
2017
  deactivate() {
1957
2018
  if (this.destroyed) return;
1958
2019
  this._activeId = null;
@@ -1960,18 +2021,27 @@ var Compositor = class extends CompositorEventEmitter {
1960
2021
  this.scheduler.stop();
1961
2022
  this.emit("activated", null, void 0);
1962
2023
  }
2024
+ /** ID of the currently active source, or null if none. */
1963
2025
  get activeId() {
1964
2026
  return this._activeId;
1965
2027
  }
1966
2028
  // ============================================================================
1967
2029
  // Output Stream
1968
2030
  // ============================================================================
2031
+ /** The composited output MediaStream. Can be used with Broadcast or other consumers. */
1969
2032
  get stream() {
1970
2033
  return this.outputStream;
1971
2034
  }
1972
2035
  // ============================================================================
1973
2036
  // Settings
1974
2037
  // ============================================================================
2038
+ /**
2039
+ * Resizes the output canvas.
2040
+ * This recreates the output stream, so consumers may need to be updated.
2041
+ * @param width - New width in logical pixels
2042
+ * @param height - New height in logical pixels
2043
+ * @param dpr - Optional device pixel ratio (defaults to window.devicePixelRatio, capped at 2)
2044
+ */
1975
2045
  resize(width, height, dpr) {
1976
2046
  if (this.destroyed) return;
1977
2047
  const effectiveDpr = Math.min(
@@ -1981,9 +2051,15 @@ var Compositor = class extends CompositorEventEmitter {
1981
2051
  this.renderer.resize(width, height, effectiveDpr);
1982
2052
  this.recreateStream();
1983
2053
  }
2054
+ /** Current output size configuration. */
1984
2055
  get size() {
1985
2056
  return this.renderer.size;
1986
2057
  }
2058
+ /**
2059
+ * Sets the rendering frame rate.
2060
+ * This recreates the output stream, so consumers may need to be updated.
2061
+ * @param fps - Frame rate (minimum 1)
2062
+ */
1987
2063
  setFps(fps) {
1988
2064
  if (this.destroyed) return;
1989
2065
  const next = Math.max(1, fps);
@@ -1992,9 +2068,15 @@ var Compositor = class extends CompositorEventEmitter {
1992
2068
  this.scheduler.setFps(next);
1993
2069
  this.recreateStream();
1994
2070
  }
2071
+ /** Current rendering frame rate. */
1995
2072
  get fps() {
1996
2073
  return this._fps;
1997
2074
  }
2075
+ /**
2076
+ * Sets the frame rate for sending to the stream.
2077
+ * Can be different from the rendering FPS (e.g., render at 60fps, send at 30fps).
2078
+ * @param fps - Frame rate (minimum 1)
2079
+ */
1998
2080
  setSendFps(fps) {
1999
2081
  if (this.destroyed) return;
2000
2082
  const next = Math.max(1, fps);
@@ -2002,20 +2084,34 @@ var Compositor = class extends CompositorEventEmitter {
2002
2084
  this._sendFps = next;
2003
2085
  this.scheduler.setSendFps(next);
2004
2086
  }
2087
+ /** Current send frame rate. */
2005
2088
  get sendFps() {
2006
2089
  return this._sendFps;
2007
2090
  }
2008
2091
  // ============================================================================
2009
2092
  // Audio
2010
2093
  // ============================================================================
2094
+ /**
2095
+ * Adds an audio track to the output stream.
2096
+ * @param track - The MediaStreamTrack to add (must be an audio track)
2097
+ */
2011
2098
  addAudioTrack(track) {
2012
2099
  if (this.destroyed) return;
2013
2100
  this.audioManager.addTrack(track);
2014
2101
  }
2102
+ /**
2103
+ * Removes an audio track from the output stream.
2104
+ * @param trackId - The track ID to remove
2105
+ */
2015
2106
  removeAudioTrack(trackId) {
2016
2107
  if (this.destroyed) return;
2017
2108
  this.audioManager.removeTrack(trackId);
2018
2109
  }
2110
+ /**
2111
+ * Manually unlocks the audio context.
2112
+ * Usually not needed as audio is auto-unlocked on user interaction.
2113
+ * @returns True if the audio context was successfully unlocked
2114
+ */
2019
2115
  unlockAudio() {
2020
2116
  if (this.destroyed) return Promise.resolve(false);
2021
2117
  return this.audioManager.unlock();
@@ -2023,6 +2119,10 @@ var Compositor = class extends CompositorEventEmitter {
2023
2119
  // ============================================================================
2024
2120
  // Lifecycle
2025
2121
  // ============================================================================
2122
+ /**
2123
+ * Destroys the compositor and releases all resources.
2124
+ * After calling this, the instance cannot be reused.
2125
+ */
2026
2126
  destroy() {
2027
2127
  if (this.destroyed) return;
2028
2128
  this.destroyed = true;