@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 +126 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +593 -103
- package/dist/index.d.ts +593 -103
- package/dist/index.js +126 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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;
|