@daydreamlive/react 0.1.1 → 0.3.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.
package/dist/index.js CHANGED
@@ -4,10 +4,9 @@ import { createBroadcast, createPlayer } from "@daydreamlive/browser";
4
4
  // src/useBroadcast.ts
5
5
  import { useCallback, useEffect, useRef, useState } from "react";
6
6
  function useBroadcast(options, factory) {
7
- const [state, setState] = useState("idle");
8
- const [whepUrl, setWhepUrl] = useState(null);
9
- const [error, setError] = useState(null);
7
+ const [status, setStatus] = useState({ state: "idle" });
10
8
  const broadcastRef = useRef(null);
9
+ const whepUrlRef = useRef(null);
11
10
  const optionsRef = useRef(options);
12
11
  const factoryRef = useRef(factory);
13
12
  useEffect(() => {
@@ -21,47 +20,80 @@ function useBroadcast(options, factory) {
21
20
  broadcastRef.current?.stop();
22
21
  };
23
22
  }, []);
23
+ const updateStatus = useCallback((newState, error) => {
24
+ const whepUrl = whepUrlRef.current;
25
+ switch (newState) {
26
+ case "connecting":
27
+ setStatus({ state: "connecting" });
28
+ break;
29
+ case "live":
30
+ setStatus({ state: "live", whepUrl });
31
+ break;
32
+ case "reconnecting":
33
+ break;
34
+ case "ended":
35
+ setStatus({ state: "ended" });
36
+ break;
37
+ case "error":
38
+ setStatus({ state: "error", error });
39
+ break;
40
+ }
41
+ }, []);
24
42
  const start = useCallback(async (stream) => {
25
- setError(null);
26
43
  if (broadcastRef.current) {
27
44
  await broadcastRef.current.stop();
45
+ broadcastRef.current = null;
28
46
  }
29
- try {
30
- const broadcast = factoryRef.current({
31
- stream,
32
- ...optionsRef.current
33
- });
34
- broadcastRef.current = broadcast;
35
- broadcast.on("stateChange", (newState) => {
36
- setState(newState);
37
- if (newState === "live") {
38
- setWhepUrl(broadcast.whepUrl);
39
- }
40
- });
41
- broadcast.on("error", (err) => {
42
- setError(err);
47
+ setStatus({ state: "connecting" });
48
+ const broadcast = factoryRef.current({
49
+ stream,
50
+ ...optionsRef.current
51
+ });
52
+ broadcastRef.current = broadcast;
53
+ broadcast.on("stateChange", (newState) => {
54
+ if (broadcastRef.current !== broadcast) return;
55
+ if (newState === "live" || newState === "reconnecting") {
56
+ whepUrlRef.current = broadcast.whepUrl;
57
+ }
58
+ updateStatus(newState);
59
+ });
60
+ broadcast.on("error", (err) => {
61
+ if (broadcastRef.current !== broadcast) return;
62
+ updateStatus("error", err);
63
+ });
64
+ broadcast.on("reconnect", (info) => {
65
+ if (broadcastRef.current !== broadcast) return;
66
+ setStatus({
67
+ state: "reconnecting",
68
+ whepUrl: whepUrlRef.current,
69
+ reconnectInfo: info
43
70
  });
71
+ });
72
+ try {
44
73
  await broadcast.connect();
45
- setState(broadcast.state);
46
- setWhepUrl(broadcast.whepUrl);
74
+ if (broadcastRef.current !== broadcast) return;
75
+ whepUrlRef.current = broadcast.whepUrl;
76
+ updateStatus(broadcast.state);
47
77
  } catch (err) {
48
- setError(err);
49
- setState("error");
78
+ if (broadcastRef.current !== broadcast) return;
79
+ setStatus({ state: "error", error: err });
50
80
  throw err;
51
81
  }
52
- }, []);
82
+ }, [updateStatus]);
53
83
  const stop = useCallback(async () => {
54
84
  await broadcastRef.current?.stop();
55
85
  broadcastRef.current = null;
56
- setWhepUrl(null);
57
- setState("idle");
86
+ whepUrlRef.current = null;
87
+ setStatus({ state: "idle" });
88
+ }, []);
89
+ const setMaxFramerate = useCallback((fps) => {
90
+ broadcastRef.current?.setMaxFramerate(fps);
58
91
  }, []);
59
92
  return {
60
- state,
61
- whepUrl,
62
- error,
93
+ status,
63
94
  start,
64
- stop
95
+ stop,
96
+ setMaxFramerate
65
97
  };
66
98
  }
67
99
 
@@ -73,8 +105,7 @@ import {
73
105
  useState as useState2
74
106
  } from "react";
75
107
  function usePlayer(whepUrl, options, factory) {
76
- const [state, setState] = useState2("idle");
77
- const [error, setError] = useState2(null);
108
+ const [status, setStatus] = useState2({ state: "idle" });
78
109
  const playerRef = useRef2(null);
79
110
  const videoRef = useRef2(null);
80
111
  const optionsRef = useRef2(options);
@@ -94,30 +125,64 @@ function usePlayer(whepUrl, options, factory) {
94
125
  playerRef.current?.stop();
95
126
  };
96
127
  }, []);
128
+ const updateStatus = useCallback2((newState, error) => {
129
+ switch (newState) {
130
+ case "connecting":
131
+ setStatus({ state: "connecting" });
132
+ break;
133
+ case "playing":
134
+ setStatus({ state: "playing" });
135
+ break;
136
+ case "buffering":
137
+ break;
138
+ case "ended":
139
+ setStatus({ state: "ended" });
140
+ break;
141
+ case "error":
142
+ setStatus({ state: "error", error });
143
+ break;
144
+ }
145
+ }, []);
97
146
  const play = useCallback2(async () => {
98
147
  const currentWhepUrl = whepUrlRef.current;
99
148
  if (!currentWhepUrl) {
100
149
  return;
101
150
  }
102
- setError(null);
103
151
  if (playerRef.current) {
104
152
  await playerRef.current.stop();
153
+ playerRef.current = null;
105
154
  }
155
+ setStatus({ state: "connecting" });
156
+ const player = factoryRef.current(currentWhepUrl, {
157
+ reconnect: optionsRef.current?.reconnect,
158
+ iceServers: optionsRef.current?.iceServers,
159
+ connectionTimeout: optionsRef.current?.connectionTimeout,
160
+ skipIceGathering: optionsRef.current?.skipIceGathering,
161
+ onStats: optionsRef.current?.onStats,
162
+ statsIntervalMs: optionsRef.current?.statsIntervalMs
163
+ });
164
+ playerRef.current = player;
165
+ player.on("stateChange", (newState) => {
166
+ if (playerRef.current !== player) return;
167
+ updateStatus(newState);
168
+ if (newState === "playing" && videoRef.current && player.stream) {
169
+ if (videoRef.current.srcObject !== player.stream) {
170
+ player.attachTo(videoRef.current);
171
+ }
172
+ }
173
+ });
174
+ player.on("error", (err) => {
175
+ if (playerRef.current !== player) return;
176
+ updateStatus("error", err);
177
+ });
178
+ player.on("reconnect", (info) => {
179
+ if (playerRef.current !== player) return;
180
+ setStatus({ state: "buffering", reconnectInfo: info });
181
+ });
106
182
  try {
107
- const player = factoryRef.current(currentWhepUrl, {
108
- reconnect: optionsRef.current?.reconnect,
109
- onStats: optionsRef.current?.onStats,
110
- statsIntervalMs: optionsRef.current?.statsIntervalMs
111
- });
112
- playerRef.current = player;
113
- player.on("stateChange", (newState) => {
114
- setState(newState);
115
- });
116
- player.on("error", (err) => {
117
- setError(err);
118
- });
119
183
  await player.connect();
120
- setState(player.state);
184
+ if (playerRef.current !== player) return;
185
+ updateStatus(player.state);
121
186
  if (videoRef.current) {
122
187
  player.attachTo(videoRef.current);
123
188
  if (optionsRef.current?.autoPlay !== false) {
@@ -128,25 +193,222 @@ function usePlayer(whepUrl, options, factory) {
128
193
  }
129
194
  }
130
195
  } catch (err) {
131
- setError(err);
132
- setState("error");
196
+ if (playerRef.current !== player) return;
197
+ setStatus({ state: "error", error: err });
133
198
  throw err;
134
199
  }
135
- }, []);
200
+ }, [updateStatus]);
136
201
  const stop = useCallback2(async () => {
137
202
  await playerRef.current?.stop();
138
203
  playerRef.current = null;
139
- setState("idle");
204
+ setStatus({ state: "idle" });
140
205
  }, []);
141
206
  return {
142
- state,
143
- error,
207
+ status,
144
208
  play,
145
209
  stop,
146
210
  videoRef
147
211
  };
148
212
  }
149
213
 
214
+ // src/useCompositor.tsx
215
+ import {
216
+ createContext,
217
+ useContext,
218
+ useEffect as useEffect3,
219
+ useLayoutEffect,
220
+ useMemo,
221
+ useRef as useRef3,
222
+ useState as useState3
223
+ } from "react";
224
+ import {
225
+ createCompositor
226
+ } from "@daydreamlive/browser";
227
+ import { jsx } from "react/jsx-runtime";
228
+ var CompositorContext = createContext(null);
229
+ function CompositorProvider({
230
+ children,
231
+ width = 512,
232
+ height = 512,
233
+ fps: initialFps = 30,
234
+ sendFps: initialSendFps,
235
+ dpr,
236
+ keepalive,
237
+ autoUnlockAudio,
238
+ unlockEvents,
239
+ disableSilentAudio = true
240
+ }) {
241
+ const compositorRef = useRef3(null);
242
+ const [stream, setStream] = useState3(null);
243
+ const [size, setSize] = useState3({
244
+ width,
245
+ height,
246
+ dpr: Math.min(
247
+ 2,
248
+ dpr ?? (typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1)
249
+ )
250
+ });
251
+ const [fps, setFpsState] = useState3(initialFps);
252
+ const [sendFps, setSendFpsState] = useState3(initialSendFps ?? initialFps);
253
+ useLayoutEffect(() => {
254
+ const compositor = createCompositor({
255
+ width,
256
+ height,
257
+ fps: initialFps,
258
+ sendFps: initialSendFps,
259
+ dpr,
260
+ keepalive,
261
+ autoUnlockAudio,
262
+ unlockEvents,
263
+ disableSilentAudio,
264
+ onSendFpsChange: (newFps) => setSendFpsState(newFps)
265
+ });
266
+ compositorRef.current = compositor;
267
+ setStream(compositor.stream);
268
+ setSize(compositor.size);
269
+ return () => {
270
+ compositor.destroy();
271
+ compositorRef.current = null;
272
+ };
273
+ }, []);
274
+ useEffect3(() => {
275
+ const compositor = compositorRef.current;
276
+ if (!compositor) return;
277
+ compositor.resize(size.width, size.height, size.dpr);
278
+ setStream(compositor.stream);
279
+ }, [size.width, size.height, size.dpr]);
280
+ useEffect3(() => {
281
+ const compositor = compositorRef.current;
282
+ if (!compositor) return;
283
+ compositor.setFps(fps);
284
+ setStream(compositor.stream);
285
+ }, [fps]);
286
+ useEffect3(() => {
287
+ const compositor = compositorRef.current;
288
+ if (!compositor) return;
289
+ compositor.setSendFps(sendFps);
290
+ }, [sendFps]);
291
+ const api = useMemo(
292
+ () => ({
293
+ // Registry
294
+ register: (id, source) => compositorRef.current?.register(id, source),
295
+ unregister: (id) => compositorRef.current?.unregister(id),
296
+ get: (id) => compositorRef.current?.get(id),
297
+ has: (id) => compositorRef.current?.has(id) ?? false,
298
+ list: () => compositorRef.current?.list() ?? [],
299
+ use: (id, source) => {
300
+ compositorRef.current?.register(id, source);
301
+ compositorRef.current?.activate(id);
302
+ return () => compositorRef.current?.unregister(id);
303
+ },
304
+ // Active source
305
+ activate: (id) => compositorRef.current?.activate(id),
306
+ deactivate: () => compositorRef.current?.deactivate(),
307
+ get activeId() {
308
+ return compositorRef.current?.activeId ?? null;
309
+ },
310
+ // Stream & size
311
+ stream,
312
+ size,
313
+ setSize: (w, h, d) => setSize({ width: w, height: h, dpr: d ?? size.dpr }),
314
+ // FPS
315
+ fps,
316
+ setFps: setFpsState,
317
+ sendFps,
318
+ setSendFps: setSendFpsState,
319
+ // Audio
320
+ addAudioTrack: (t) => compositorRef.current?.addAudioTrack(t),
321
+ removeAudioTrack: (id) => compositorRef.current?.removeAudioTrack(id),
322
+ unlockAudio: () => compositorRef.current?.unlockAudio() ?? Promise.resolve(false),
323
+ // Events
324
+ on: (event, cb) => compositorRef.current?.on(event, cb) ?? (() => {
325
+ })
326
+ }),
327
+ [stream, size, fps, sendFps]
328
+ );
329
+ return /* @__PURE__ */ jsx(CompositorContext.Provider, { value: api, children });
330
+ }
331
+ function useCompositor() {
332
+ const ctx = useContext(CompositorContext);
333
+ if (!ctx) {
334
+ throw new Error("useCompositor must be used within <CompositorProvider>");
335
+ }
336
+ return ctx;
337
+ }
338
+
339
+ // src/useSource.ts
340
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState4, useCallback as useCallback3, useMemo as useMemo2 } from "react";
341
+ function useSource(id, options) {
342
+ const compositor = useCompositor();
343
+ const compositorRef = useRef4(compositor);
344
+ compositorRef.current = compositor;
345
+ const ref = useRef4(null);
346
+ const [isActive, setIsActive] = useState4(false);
347
+ const registeredRef = useRef4(false);
348
+ const idRef = useRef4(id);
349
+ idRef.current = id;
350
+ const { kind, contentHint, fit } = options;
351
+ const optionsRef = useRef4({ kind, contentHint, fit });
352
+ optionsRef.current = { kind, contentHint, fit };
353
+ const registerSource = useCallback3((element) => {
354
+ const { kind: kind2, contentHint: contentHint2, fit: fit2 } = optionsRef.current;
355
+ const source = kind2 === "video" ? {
356
+ kind: "video",
357
+ element,
358
+ contentHint: contentHint2,
359
+ fit: fit2
360
+ } : {
361
+ kind: "canvas",
362
+ element,
363
+ contentHint: contentHint2
364
+ };
365
+ compositorRef.current.register(idRef.current, source);
366
+ registeredRef.current = true;
367
+ }, []);
368
+ useEffect4(() => {
369
+ const element = ref.current;
370
+ if (!element) return;
371
+ registerSource(element);
372
+ }, [id, kind, contentHint, fit, registerSource]);
373
+ useEffect4(() => {
374
+ const currentId = id;
375
+ return () => {
376
+ if (registeredRef.current) {
377
+ registeredRef.current = false;
378
+ setIsActive(false);
379
+ compositorRef.current.unregister(currentId);
380
+ }
381
+ };
382
+ }, [id]);
383
+ useEffect4(() => {
384
+ setIsActive(compositor.activeId === id);
385
+ }, [compositor.activeId, id]);
386
+ const activate = useCallback3(() => {
387
+ const element = ref.current;
388
+ if (!element) return;
389
+ if (!registeredRef.current) {
390
+ registerSource(element);
391
+ }
392
+ compositorRef.current.activate(idRef.current);
393
+ setIsActive(true);
394
+ }, [registerSource]);
395
+ const deactivate = useCallback3(() => {
396
+ if (compositorRef.current.activeId === idRef.current) {
397
+ compositorRef.current.deactivate();
398
+ setIsActive(false);
399
+ }
400
+ }, []);
401
+ return useMemo2(
402
+ () => ({
403
+ ref,
404
+ isActive,
405
+ activate,
406
+ deactivate
407
+ }),
408
+ [isActive, activate, deactivate]
409
+ );
410
+ }
411
+
150
412
  // src/index.ts
151
413
  function useBroadcast2(options) {
152
414
  return useBroadcast(options, createBroadcast);
@@ -155,7 +417,10 @@ function usePlayer2(whepUrl, options) {
155
417
  return usePlayer(whepUrl, options, createPlayer);
156
418
  }
157
419
  export {
420
+ CompositorProvider,
158
421
  useBroadcast2 as useBroadcast,
159
- usePlayer2 as usePlayer
422
+ useCompositor,
423
+ usePlayer2 as usePlayer,
424
+ useSource
160
425
  };
161
426
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/useBroadcast.ts","../src/usePlayer.ts"],"sourcesContent":["import { createBroadcast, createPlayer } from \"@daydreamlive/browser\";\nimport {\n useBroadcast as baseUseBroadcast,\n type UseBroadcastOptions,\n type UseBroadcastReturn,\n} from \"./useBroadcast\";\nimport {\n usePlayer as baseUsePlayer,\n type UsePlayerOptions,\n type UsePlayerReturn,\n} from \"./usePlayer\";\n\nexport function useBroadcast(options: UseBroadcastOptions): UseBroadcastReturn {\n return baseUseBroadcast(options, createBroadcast);\n}\n\nexport function usePlayer(\n whepUrl: string | null,\n options?: UsePlayerOptions,\n): UsePlayerReturn {\n return baseUsePlayer(whepUrl, options, createPlayer);\n}\n\nexport type {\n UseBroadcastOptions,\n UseBroadcastReturn,\n UsePlayerOptions,\n UsePlayerReturn,\n};\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n Broadcast,\n BroadcastOptions,\n BroadcastState,\n DaydreamError,\n ReconnectConfig,\n VideoConfig,\n} from \"@daydreamlive/browser\";\n\nexport interface UseBroadcastOptions {\n whipUrl: string;\n reconnect?: ReconnectConfig;\n video?: VideoConfig;\n onStats?: (report: RTCStatsReport) => void;\n statsIntervalMs?: number;\n}\n\nexport type BroadcastFactory = (options: BroadcastOptions) => Broadcast;\n\nexport interface UseBroadcastReturn {\n state: BroadcastState | \"idle\";\n whepUrl: string | null;\n error: DaydreamError | null;\n start: (stream: MediaStream) => Promise<void>;\n stop: () => Promise<void>;\n}\n\nexport function useBroadcast(\n options: UseBroadcastOptions,\n factory: BroadcastFactory,\n): UseBroadcastReturn {\n const [state, setState] = useState<BroadcastState | \"idle\">(\"idle\");\n const [whepUrl, setWhepUrl] = useState<string | null>(null);\n const [error, setError] = useState<DaydreamError | null>(null);\n const broadcastRef = useRef<Broadcast | null>(null);\n const optionsRef = useRef(options);\n const factoryRef = useRef(factory);\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n factoryRef.current = factory;\n }, [factory]);\n\n useEffect(() => {\n return () => {\n broadcastRef.current?.stop();\n };\n }, []);\n\n const start = useCallback(async (stream: MediaStream) => {\n setError(null);\n\n if (broadcastRef.current) {\n await broadcastRef.current.stop();\n }\n\n try {\n const broadcast = factoryRef.current({\n stream,\n ...optionsRef.current,\n });\n\n broadcastRef.current = broadcast;\n\n broadcast.on(\"stateChange\", (newState) => {\n setState(newState);\n if (newState === \"live\") {\n setWhepUrl(broadcast.whepUrl);\n }\n });\n\n broadcast.on(\"error\", (err) => {\n setError(err);\n });\n\n await broadcast.connect();\n setState(broadcast.state);\n setWhepUrl(broadcast.whepUrl);\n } catch (err) {\n setError(err as DaydreamError);\n setState(\"error\");\n throw err;\n }\n }, []);\n\n const stop = useCallback(async () => {\n await broadcastRef.current?.stop();\n broadcastRef.current = null;\n setWhepUrl(null);\n setState(\"idle\");\n }, []);\n\n return {\n state,\n whepUrl,\n error,\n start,\n stop,\n };\n}\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type RefObject,\n} from \"react\";\nimport type {\n Player,\n PlayerOptions,\n PlayerState,\n DaydreamError,\n ReconnectConfig,\n} from \"@daydreamlive/browser\";\n\nexport interface UsePlayerOptions {\n reconnect?: ReconnectConfig;\n autoPlay?: boolean;\n onStats?: (report: RTCStatsReport) => void;\n statsIntervalMs?: number;\n}\n\nexport type PlayerFactory = (\n whepUrl: string,\n options?: PlayerOptions,\n) => Player;\n\nexport interface UsePlayerReturn {\n state: PlayerState | \"idle\";\n error: DaydreamError | null;\n play: () => Promise<void>;\n stop: () => Promise<void>;\n videoRef: RefObject<HTMLVideoElement | null>;\n}\n\nexport function usePlayer(\n whepUrl: string | null,\n options: UsePlayerOptions | undefined,\n factory: PlayerFactory,\n): UsePlayerReturn {\n const [state, setState] = useState<PlayerState | \"idle\">(\"idle\");\n const [error, setError] = useState<DaydreamError | null>(null);\n const playerRef = useRef<Player | null>(null);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const optionsRef = useRef(options);\n const whepUrlRef = useRef(whepUrl);\n const factoryRef = useRef(factory);\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n factoryRef.current = factory;\n }, [factory]);\n\n useEffect(() => {\n whepUrlRef.current = whepUrl;\n }, [whepUrl]);\n\n useEffect(() => {\n return () => {\n playerRef.current?.stop();\n };\n }, []);\n\n const play = useCallback(async () => {\n const currentWhepUrl = whepUrlRef.current;\n if (!currentWhepUrl) {\n return;\n }\n\n setError(null);\n\n if (playerRef.current) {\n await playerRef.current.stop();\n }\n\n try {\n const player = factoryRef.current(currentWhepUrl, {\n reconnect: optionsRef.current?.reconnect,\n onStats: optionsRef.current?.onStats,\n statsIntervalMs: optionsRef.current?.statsIntervalMs,\n });\n\n playerRef.current = player;\n\n player.on(\"stateChange\", (newState) => {\n setState(newState);\n });\n\n player.on(\"error\", (err) => {\n setError(err);\n });\n\n await player.connect();\n setState(player.state);\n\n if (videoRef.current) {\n player.attachTo(videoRef.current);\n if (optionsRef.current?.autoPlay !== false) {\n try {\n await videoRef.current.play();\n } catch {\n // Autoplay blocked\n }\n }\n }\n } catch (err) {\n setError(err as DaydreamError);\n setState(\"error\");\n throw err;\n }\n }, []);\n\n const stop = useCallback(async () => {\n await playerRef.current?.stop();\n playerRef.current = null;\n setState(\"idle\");\n }, []);\n\n return {\n state,\n error,\n play,\n stop,\n videoRef,\n };\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","useBroadcast","usePlayer"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/useBroadcast.ts","../src/usePlayer.ts","../src/useCompositor.tsx","../src/useSource.ts"],"sourcesContent":["import { createBroadcast, createPlayer } from \"@daydreamlive/browser\";\nimport {\n useBroadcast as baseUseBroadcast,\n type UseBroadcastOptions,\n type UseBroadcastReturn,\n type UseBroadcastStatus,\n} from \"./useBroadcast\";\nimport {\n usePlayer as baseUsePlayer,\n type UsePlayerOptions,\n type UsePlayerReturn,\n type UsePlayerStatus,\n} from \"./usePlayer\";\n\nexport function useBroadcast(options: UseBroadcastOptions): UseBroadcastReturn {\n return baseUseBroadcast(options, createBroadcast);\n}\n\nexport function usePlayer(\n whepUrl: string | null,\n options?: UsePlayerOptions,\n): UsePlayerReturn {\n return baseUsePlayer(whepUrl, options, createPlayer);\n}\n\nexport type {\n UseBroadcastOptions,\n UseBroadcastReturn,\n UseBroadcastStatus,\n UsePlayerOptions,\n UsePlayerReturn,\n UsePlayerStatus,\n};\n\nexport type {\n AudioConfig,\n BroadcastState,\n PlayerState,\n ReconnectConfig,\n ReconnectInfo,\n VideoConfig,\n DaydreamError,\n DaydreamErrorCode,\n // Compositor types\n Compositor,\n CompositorOptions,\n CompositorEvent,\n CompositorEventMap,\n Source,\n VideoSource,\n CanvasSource,\n Size,\n FitMode,\n ContentHint,\n Ctx2D,\n} from \"@daydreamlive/browser\";\n\nexport {\n CompositorProvider,\n useCompositor,\n type CompositorApi,\n type CompositorProviderProps,\n} from \"./useCompositor\";\n\nexport {\n useSource,\n type UseSourceOptions,\n type UseSourceReturn,\n} from \"./useSource\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n AudioConfig,\n Broadcast,\n BroadcastOptions,\n BroadcastState,\n DaydreamError,\n ReconnectConfig,\n ReconnectInfo,\n VideoConfig,\n} from \"@daydreamlive/browser\";\n\nexport interface UseBroadcastOptions {\n whipUrl: string;\n reconnect?: ReconnectConfig;\n video?: VideoConfig;\n audio?: AudioConfig;\n iceServers?: RTCIceServer[];\n connectionTimeout?: number;\n onStats?: (report: RTCStatsReport) => void;\n statsIntervalMs?: number;\n}\n\nexport type BroadcastFactory = (options: BroadcastOptions) => Broadcast;\n\nexport type UseBroadcastStatus =\n | { state: \"idle\" }\n | { state: \"connecting\" }\n | { state: \"live\"; whepUrl: string }\n | { state: \"reconnecting\"; whepUrl: string; reconnectInfo: ReconnectInfo }\n | { state: \"ended\" }\n | { state: \"error\"; error: DaydreamError };\n\nexport interface UseBroadcastReturn {\n status: UseBroadcastStatus;\n start: (stream: MediaStream) => Promise<void>;\n stop: () => Promise<void>;\n setMaxFramerate: (fps?: number) => void;\n}\n\nexport function useBroadcast(\n options: UseBroadcastOptions,\n factory: BroadcastFactory,\n): UseBroadcastReturn {\n const [status, setStatus] = useState<UseBroadcastStatus>({ state: \"idle\" });\n const broadcastRef = useRef<Broadcast | null>(null);\n const whepUrlRef = useRef<string | null>(null);\n const optionsRef = useRef(options);\n const factoryRef = useRef(factory);\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n factoryRef.current = factory;\n }, [factory]);\n\n useEffect(() => {\n return () => {\n broadcastRef.current?.stop();\n };\n }, []);\n\n const updateStatus = useCallback((newState: BroadcastState, error?: DaydreamError) => {\n const whepUrl = whepUrlRef.current;\n switch (newState) {\n case \"connecting\":\n setStatus({ state: \"connecting\" });\n break;\n case \"live\":\n setStatus({ state: \"live\", whepUrl: whepUrl! });\n break;\n case \"reconnecting\":\n // reconnectInfo will be set by the reconnect event\n break;\n case \"ended\":\n setStatus({ state: \"ended\" });\n break;\n case \"error\":\n setStatus({ state: \"error\", error: error! });\n break;\n }\n }, []);\n\n const start = useCallback(async (stream: MediaStream) => {\n if (broadcastRef.current) {\n await broadcastRef.current.stop();\n broadcastRef.current = null;\n }\n\n setStatus({ state: \"connecting\" });\n\n const broadcast = factoryRef.current({\n stream,\n ...optionsRef.current,\n });\n\n broadcastRef.current = broadcast;\n\n broadcast.on(\"stateChange\", (newState) => {\n // Guard against events from stopped broadcast\n if (broadcastRef.current !== broadcast) return;\n if (newState === \"live\" || newState === \"reconnecting\") {\n whepUrlRef.current = broadcast.whepUrl;\n }\n updateStatus(newState);\n });\n\n broadcast.on(\"error\", (err) => {\n if (broadcastRef.current !== broadcast) return;\n updateStatus(\"error\", err);\n });\n\n broadcast.on(\"reconnect\", (info) => {\n if (broadcastRef.current !== broadcast) return;\n setStatus({\n state: \"reconnecting\",\n whepUrl: whepUrlRef.current!,\n reconnectInfo: info,\n });\n });\n\n try {\n await broadcast.connect();\n if (broadcastRef.current !== broadcast) return;\n whepUrlRef.current = broadcast.whepUrl;\n updateStatus(broadcast.state);\n } catch (err) {\n if (broadcastRef.current !== broadcast) return;\n setStatus({ state: \"error\", error: err as DaydreamError });\n throw err;\n }\n }, [updateStatus]);\n\n const stop = useCallback(async () => {\n await broadcastRef.current?.stop();\n broadcastRef.current = null;\n whepUrlRef.current = null;\n setStatus({ state: \"idle\" });\n }, []);\n\n const setMaxFramerate = useCallback((fps?: number) => {\n broadcastRef.current?.setMaxFramerate(fps);\n }, []);\n\n return {\n status,\n start,\n stop,\n setMaxFramerate,\n };\n}\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type RefObject,\n} from \"react\";\nimport type {\n Player,\n PlayerOptions,\n PlayerState,\n DaydreamError,\n ReconnectConfig,\n ReconnectInfo,\n} from \"@daydreamlive/browser\";\n\nexport interface UsePlayerOptions {\n reconnect?: ReconnectConfig;\n iceServers?: RTCIceServer[];\n connectionTimeout?: number;\n skipIceGathering?: boolean;\n autoPlay?: boolean;\n onStats?: (report: RTCStatsReport) => void;\n statsIntervalMs?: number;\n}\n\nexport type PlayerFactory = (\n whepUrl: string,\n options?: PlayerOptions,\n) => Player;\n\nexport type UsePlayerStatus =\n | { state: \"idle\" }\n | { state: \"connecting\" }\n | { state: \"playing\" }\n | { state: \"buffering\"; reconnectInfo: ReconnectInfo }\n | { state: \"ended\" }\n | { state: \"error\"; error: DaydreamError };\n\nexport interface UsePlayerReturn {\n status: UsePlayerStatus;\n play: () => Promise<void>;\n stop: () => Promise<void>;\n videoRef: RefObject<HTMLVideoElement | null>;\n}\n\nexport function usePlayer(\n whepUrl: string | null,\n options: UsePlayerOptions | undefined,\n factory: PlayerFactory,\n): UsePlayerReturn {\n const [status, setStatus] = useState<UsePlayerStatus>({ state: \"idle\" });\n const playerRef = useRef<Player | null>(null);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const optionsRef = useRef(options);\n const whepUrlRef = useRef(whepUrl);\n const factoryRef = useRef(factory);\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n factoryRef.current = factory;\n }, [factory]);\n\n useEffect(() => {\n whepUrlRef.current = whepUrl;\n }, [whepUrl]);\n\n useEffect(() => {\n return () => {\n playerRef.current?.stop();\n };\n }, []);\n\n const updateStatus = useCallback((newState: PlayerState, error?: DaydreamError) => {\n switch (newState) {\n case \"connecting\":\n setStatus({ state: \"connecting\" });\n break;\n case \"playing\":\n setStatus({ state: \"playing\" });\n break;\n case \"buffering\":\n // reconnectInfo will be set by the reconnect event\n break;\n case \"ended\":\n setStatus({ state: \"ended\" });\n break;\n case \"error\":\n setStatus({ state: \"error\", error: error! });\n break;\n }\n }, []);\n\n const play = useCallback(async () => {\n const currentWhepUrl = whepUrlRef.current;\n if (!currentWhepUrl) {\n return;\n }\n\n if (playerRef.current) {\n await playerRef.current.stop();\n playerRef.current = null;\n }\n\n setStatus({ state: \"connecting\" });\n\n const player = factoryRef.current(currentWhepUrl, {\n reconnect: optionsRef.current?.reconnect,\n iceServers: optionsRef.current?.iceServers,\n connectionTimeout: optionsRef.current?.connectionTimeout,\n skipIceGathering: optionsRef.current?.skipIceGathering,\n onStats: optionsRef.current?.onStats,\n statsIntervalMs: optionsRef.current?.statsIntervalMs,\n });\n\n playerRef.current = player;\n\n player.on(\"stateChange\", (newState) => {\n // Guard against events from stopped player\n if (playerRef.current !== player) return;\n updateStatus(newState);\n // Re-attach stream after reconnect\n if (newState === \"playing\" && videoRef.current && player.stream) {\n if (videoRef.current.srcObject !== player.stream) {\n player.attachTo(videoRef.current);\n }\n }\n });\n\n player.on(\"error\", (err) => {\n if (playerRef.current !== player) return;\n updateStatus(\"error\", err);\n });\n\n player.on(\"reconnect\", (info) => {\n if (playerRef.current !== player) return;\n setStatus({ state: \"buffering\", reconnectInfo: info });\n });\n\n try {\n await player.connect();\n if (playerRef.current !== player) return;\n updateStatus(player.state);\n\n if (videoRef.current) {\n player.attachTo(videoRef.current);\n if (optionsRef.current?.autoPlay !== false) {\n try {\n await videoRef.current.play();\n } catch {\n // Autoplay blocked\n }\n }\n }\n } catch (err) {\n if (playerRef.current !== player) return;\n setStatus({ state: \"error\", error: err as DaydreamError });\n throw err;\n }\n }, [updateStatus]);\n\n const stop = useCallback(async () => {\n await playerRef.current?.stop();\n playerRef.current = null;\n setStatus({ state: \"idle\" });\n }, []);\n\n return {\n status,\n play,\n stop,\n videoRef,\n };\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type PropsWithChildren,\n} from \"react\";\nimport {\n createCompositor,\n type Compositor,\n type CompositorOptions,\n type Size,\n type Source,\n} from \"@daydreamlive/browser\";\n\nexport interface CompositorApi {\n // Registry\n register(id: string, source: Source): void;\n unregister(id: string): void;\n get(id: string): Source | undefined;\n has(id: string): boolean;\n list(): Array<{ id: string; source: Source }>;\n\n /**\n * Register a source, activate it, and return an unregister function.\n * Convenience method that combines register + activate with automatic cleanup.\n *\n * @example\n * ```tsx\n * useEffect(() => {\n * const unregister = compositor.use(\"camera\", {\n * kind: \"video\",\n * element: videoRef.current,\n * fit: \"cover\",\n * });\n * return unregister;\n * }, [compositor]);\n * ```\n */\n use(id: string, source: Source): () => void;\n\n // Active source\n /**\n * Activate a registered source.\n * @param id - The source ID to activate\n */\n activate(id: string): void;\n deactivate(): void;\n readonly activeId: string | null;\n\n // Output (reactive)\n readonly stream: MediaStream | null;\n readonly size: Size;\n setSize(width: number, height: number, dpr?: number): void;\n\n // FPS (reactive)\n readonly fps: number;\n setFps(fps: number): void;\n readonly sendFps: number;\n setSendFps(fps: number): void;\n\n // Audio\n addAudioTrack(track: MediaStreamTrack): void;\n removeAudioTrack(trackId: string): void;\n unlockAudio(): Promise<boolean>;\n\n // Events\n on: Compositor[\"on\"];\n}\n\nconst CompositorContext = createContext<CompositorApi | null>(null);\n\nexport interface CompositorProviderProps\n extends PropsWithChildren,\n Partial<Omit<CompositorOptions, \"onSendFpsChange\">> {}\n\nexport function CompositorProvider({\n children,\n width = 512,\n height = 512,\n fps: initialFps = 30,\n sendFps: initialSendFps,\n dpr,\n keepalive,\n autoUnlockAudio,\n unlockEvents,\n disableSilentAudio = true,\n}: CompositorProviderProps) {\n const compositorRef = useRef<Compositor | null>(null);\n const [stream, setStream] = useState<MediaStream | null>(null);\n const [size, setSize] = useState<Size>({\n width,\n height,\n dpr: Math.min(\n 2,\n dpr ?? (typeof window !== \"undefined\" ? window.devicePixelRatio || 1 : 1),\n ),\n });\n const [fps, setFpsState] = useState(initialFps);\n const [sendFps, setSendFpsState] = useState(initialSendFps ?? initialFps);\n\n // Create compositor once\n useLayoutEffect(() => {\n const compositor = createCompositor({\n width,\n height,\n fps: initialFps,\n sendFps: initialSendFps,\n dpr,\n keepalive,\n autoUnlockAudio,\n unlockEvents,\n disableSilentAudio,\n onSendFpsChange: (newFps) => setSendFpsState(newFps),\n });\n\n compositorRef.current = compositor;\n setStream(compositor.stream);\n setSize(compositor.size);\n\n return () => {\n compositor.destroy();\n compositorRef.current = null;\n };\n }, []);\n\n // Sync size changes\n useEffect(() => {\n const compositor = compositorRef.current;\n if (!compositor) return;\n\n compositor.resize(size.width, size.height, size.dpr);\n setStream(compositor.stream);\n }, [size.width, size.height, size.dpr]);\n\n // Sync fps changes\n useEffect(() => {\n const compositor = compositorRef.current;\n if (!compositor) return;\n\n compositor.setFps(fps);\n setStream(compositor.stream);\n }, [fps]);\n\n // Sync sendFps changes\n useEffect(() => {\n const compositor = compositorRef.current;\n if (!compositor) return;\n\n compositor.setSendFps(sendFps);\n }, [sendFps]);\n\n // Memoized API\n const api = useMemo<CompositorApi>(\n () => ({\n // Registry\n register: (id, source) => compositorRef.current?.register(id, source),\n unregister: (id) => compositorRef.current?.unregister(id),\n get: (id) => compositorRef.current?.get(id),\n has: (id) => compositorRef.current?.has(id) ?? false,\n list: () => compositorRef.current?.list() ?? [],\n use: (id, source) => {\n compositorRef.current?.register(id, source);\n compositorRef.current?.activate(id);\n return () => compositorRef.current?.unregister(id);\n },\n\n // Active source\n activate: (id) => compositorRef.current?.activate(id),\n deactivate: () => compositorRef.current?.deactivate(),\n get activeId() {\n return compositorRef.current?.activeId ?? null;\n },\n\n // Stream & size\n stream,\n size,\n setSize: (w, h, d) =>\n setSize({ width: w, height: h, dpr: d ?? size.dpr }),\n\n // FPS\n fps,\n setFps: setFpsState,\n sendFps,\n setSendFps: setSendFpsState,\n\n // Audio\n addAudioTrack: (t) => compositorRef.current?.addAudioTrack(t),\n removeAudioTrack: (id) => compositorRef.current?.removeAudioTrack(id),\n unlockAudio: () =>\n compositorRef.current?.unlockAudio() ?? Promise.resolve(false),\n\n // Events\n on: (event, cb) => compositorRef.current?.on(event, cb) ?? (() => {}),\n }),\n [stream, size, fps, sendFps],\n );\n\n return (\n <CompositorContext.Provider value={api}>\n {children}\n </CompositorContext.Provider>\n );\n}\n\nexport function useCompositor(): CompositorApi {\n const ctx = useContext(CompositorContext);\n if (!ctx) {\n throw new Error(\"useCompositor must be used within <CompositorProvider>\");\n }\n return ctx;\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState, useCallback, useMemo } from \"react\";\nimport type { Source, FitMode, ContentHint } from \"@daydreamlive/browser\";\nimport { useCompositor } from \"./useCompositor\";\n\nexport interface UseSourceOptions {\n kind: \"video\" | \"canvas\";\n contentHint?: ContentHint;\n fit?: FitMode;\n}\n\nexport interface UseSourceReturn<\n T extends HTMLVideoElement | HTMLCanvasElement,\n> {\n ref: React.RefObject<T>;\n isActive: boolean;\n activate: () => void;\n deactivate: () => void;\n}\n\nexport function useSource<\n T extends HTMLVideoElement | HTMLCanvasElement =\n | HTMLVideoElement\n | HTMLCanvasElement,\n>(id: string, options: UseSourceOptions): UseSourceReturn<T> {\n const compositor = useCompositor();\n const compositorRef = useRef(compositor);\n compositorRef.current = compositor;\n\n const ref = useRef<T>(null);\n const [isActive, setIsActive] = useState(false);\n const registeredRef = useRef(false);\n const idRef = useRef(id);\n idRef.current = id;\n\n const { kind, contentHint, fit } = options;\n\n const optionsRef = useRef({ kind, contentHint, fit });\n optionsRef.current = { kind, contentHint, fit };\n\n const registerSource = useCallback((element: T) => {\n const { kind, contentHint, fit } = optionsRef.current;\n const source =\n kind === \"video\"\n ? {\n kind: \"video\" as const,\n element: element as HTMLVideoElement,\n contentHint,\n fit,\n }\n : {\n kind: \"canvas\" as const,\n element: element as HTMLCanvasElement,\n contentHint,\n };\n\n compositorRef.current.register(idRef.current, source);\n registeredRef.current = true;\n }, []);\n\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n\n registerSource(element);\n }, [id, kind, contentHint, fit, registerSource]);\n\n useEffect(() => {\n const currentId = id;\n return () => {\n if (registeredRef.current) {\n registeredRef.current = false;\n setIsActive(false);\n compositorRef.current.unregister(currentId);\n }\n };\n }, [id]);\n\n useEffect(() => {\n setIsActive(compositor.activeId === id);\n }, [compositor.activeId, id]);\n\n const activate = useCallback(() => {\n const element = ref.current;\n if (!element) return;\n\n if (!registeredRef.current) {\n registerSource(element);\n }\n\n compositorRef.current.activate(idRef.current);\n setIsActive(true);\n }, [registerSource]);\n\n const deactivate = useCallback(() => {\n if (compositorRef.current.activeId === idRef.current) {\n compositorRef.current.deactivate();\n setIsActive(false);\n }\n }, []);\n\n return useMemo(\n () => ({\n ref,\n isActive,\n activate,\n deactivate,\n }),\n [isActive, activate, deactivate],\n );\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","useEffect","useRef","useState","useEffect","useRef","useState","useCallback","useMemo","useRef","useState","useCallback","kind","contentHint","fit","useEffect","useMemo","useBroadcast","usePlayer"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daydreamlive/react",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -30,7 +30,7 @@
30
30
  "typecheck": "tsc --noEmit"
31
31
  },
32
32
  "dependencies": {
33
- "@daydreamlive/browser": "^0.1.1"
33
+ "@daydreamlive/browser": "*"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=18.0.0"