@daydreamlive/react 0.2.0 → 0.3.1
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 +108 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -5
- package/dist/index.d.ts +41 -5
- package/dist/index.js +106 -29
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,8 @@ __export(index_exports, {
|
|
|
23
23
|
CompositorProvider: () => CompositorProvider,
|
|
24
24
|
useBroadcast: () => useBroadcast2,
|
|
25
25
|
useCompositor: () => useCompositor,
|
|
26
|
-
usePlayer: () => usePlayer2
|
|
26
|
+
usePlayer: () => usePlayer2,
|
|
27
|
+
useSource: () => useSource
|
|
27
28
|
});
|
|
28
29
|
module.exports = __toCommonJS(index_exports);
|
|
29
30
|
var import_browser2 = require("@daydreamlive/browser");
|
|
@@ -126,12 +127,11 @@ function useBroadcast(options, factory) {
|
|
|
126
127
|
|
|
127
128
|
// src/usePlayer.ts
|
|
128
129
|
var import_react2 = require("react");
|
|
129
|
-
function usePlayer(
|
|
130
|
+
function usePlayer(options, factory) {
|
|
130
131
|
const [status, setStatus] = (0, import_react2.useState)({ state: "idle" });
|
|
131
132
|
const playerRef = (0, import_react2.useRef)(null);
|
|
132
133
|
const videoRef = (0, import_react2.useRef)(null);
|
|
133
134
|
const optionsRef = (0, import_react2.useRef)(options);
|
|
134
|
-
const whepUrlRef = (0, import_react2.useRef)(whepUrl);
|
|
135
135
|
const factoryRef = (0, import_react2.useRef)(factory);
|
|
136
136
|
(0, import_react2.useEffect)(() => {
|
|
137
137
|
optionsRef.current = options;
|
|
@@ -139,34 +139,34 @@ function usePlayer(whepUrl, options, factory) {
|
|
|
139
139
|
(0, import_react2.useEffect)(() => {
|
|
140
140
|
factoryRef.current = factory;
|
|
141
141
|
}, [factory]);
|
|
142
|
-
(0, import_react2.useEffect)(() => {
|
|
143
|
-
whepUrlRef.current = whepUrl;
|
|
144
|
-
}, [whepUrl]);
|
|
145
142
|
(0, import_react2.useEffect)(() => {
|
|
146
143
|
return () => {
|
|
147
144
|
playerRef.current?.stop();
|
|
148
145
|
};
|
|
149
146
|
}, []);
|
|
150
|
-
const updateStatus = (0, import_react2.useCallback)(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
147
|
+
const updateStatus = (0, import_react2.useCallback)(
|
|
148
|
+
(newState, error) => {
|
|
149
|
+
switch (newState) {
|
|
150
|
+
case "connecting":
|
|
151
|
+
setStatus({ state: "connecting" });
|
|
152
|
+
break;
|
|
153
|
+
case "playing":
|
|
154
|
+
setStatus({ state: "playing" });
|
|
155
|
+
break;
|
|
156
|
+
case "buffering":
|
|
157
|
+
break;
|
|
158
|
+
case "ended":
|
|
159
|
+
setStatus({ state: "ended" });
|
|
160
|
+
break;
|
|
161
|
+
case "error":
|
|
162
|
+
setStatus({ state: "error", error });
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
[]
|
|
167
|
+
);
|
|
168
168
|
const play = (0, import_react2.useCallback)(async () => {
|
|
169
|
-
const currentWhepUrl =
|
|
169
|
+
const currentWhepUrl = optionsRef.current.whepUrl;
|
|
170
170
|
if (!currentWhepUrl) {
|
|
171
171
|
return;
|
|
172
172
|
}
|
|
@@ -179,6 +179,7 @@ function usePlayer(whepUrl, options, factory) {
|
|
|
179
179
|
reconnect: optionsRef.current?.reconnect,
|
|
180
180
|
iceServers: optionsRef.current?.iceServers,
|
|
181
181
|
connectionTimeout: optionsRef.current?.connectionTimeout,
|
|
182
|
+
skipIceGathering: optionsRef.current?.skipIceGathering,
|
|
182
183
|
onStats: optionsRef.current?.onStats,
|
|
183
184
|
statsIntervalMs: optionsRef.current?.statsIntervalMs
|
|
184
185
|
});
|
|
@@ -244,7 +245,6 @@ function CompositorProvider({
|
|
|
244
245
|
fps: initialFps = 30,
|
|
245
246
|
sendFps: initialSendFps,
|
|
246
247
|
dpr,
|
|
247
|
-
crossfadeMs = 500,
|
|
248
248
|
keepalive,
|
|
249
249
|
autoUnlockAudio,
|
|
250
250
|
unlockEvents,
|
|
@@ -269,7 +269,6 @@ function CompositorProvider({
|
|
|
269
269
|
fps: initialFps,
|
|
270
270
|
sendFps: initialSendFps,
|
|
271
271
|
dpr,
|
|
272
|
-
crossfadeMs,
|
|
273
272
|
keepalive,
|
|
274
273
|
autoUnlockAudio,
|
|
275
274
|
unlockEvents,
|
|
@@ -309,6 +308,11 @@ function CompositorProvider({
|
|
|
309
308
|
get: (id) => compositorRef.current?.get(id),
|
|
310
309
|
has: (id) => compositorRef.current?.has(id) ?? false,
|
|
311
310
|
list: () => compositorRef.current?.list() ?? [],
|
|
311
|
+
use: (id, source) => {
|
|
312
|
+
compositorRef.current?.register(id, source);
|
|
313
|
+
compositorRef.current?.activate(id);
|
|
314
|
+
return () => compositorRef.current?.unregister(id);
|
|
315
|
+
},
|
|
312
316
|
// Active source
|
|
313
317
|
activate: (id) => compositorRef.current?.activate(id),
|
|
314
318
|
deactivate: () => compositorRef.current?.deactivate(),
|
|
@@ -344,18 +348,92 @@ function useCompositor() {
|
|
|
344
348
|
return ctx;
|
|
345
349
|
}
|
|
346
350
|
|
|
351
|
+
// src/useSource.ts
|
|
352
|
+
var import_react4 = require("react");
|
|
353
|
+
function useSource(id, options) {
|
|
354
|
+
const compositor = useCompositor();
|
|
355
|
+
const compositorRef = (0, import_react4.useRef)(compositor);
|
|
356
|
+
compositorRef.current = compositor;
|
|
357
|
+
const ref = (0, import_react4.useRef)(null);
|
|
358
|
+
const [isActive, setIsActive] = (0, import_react4.useState)(false);
|
|
359
|
+
const registeredRef = (0, import_react4.useRef)(false);
|
|
360
|
+
const idRef = (0, import_react4.useRef)(id);
|
|
361
|
+
idRef.current = id;
|
|
362
|
+
const { kind, contentHint, fit } = options;
|
|
363
|
+
const optionsRef = (0, import_react4.useRef)({ kind, contentHint, fit });
|
|
364
|
+
optionsRef.current = { kind, contentHint, fit };
|
|
365
|
+
const registerSource = (0, import_react4.useCallback)((element) => {
|
|
366
|
+
const { kind: kind2, contentHint: contentHint2, fit: fit2 } = optionsRef.current;
|
|
367
|
+
const source = kind2 === "video" ? {
|
|
368
|
+
kind: "video",
|
|
369
|
+
element,
|
|
370
|
+
contentHint: contentHint2,
|
|
371
|
+
fit: fit2
|
|
372
|
+
} : {
|
|
373
|
+
kind: "canvas",
|
|
374
|
+
element,
|
|
375
|
+
contentHint: contentHint2
|
|
376
|
+
};
|
|
377
|
+
compositorRef.current.register(idRef.current, source);
|
|
378
|
+
registeredRef.current = true;
|
|
379
|
+
}, []);
|
|
380
|
+
(0, import_react4.useEffect)(() => {
|
|
381
|
+
const element = ref.current;
|
|
382
|
+
if (!element) return;
|
|
383
|
+
registerSource(element);
|
|
384
|
+
}, [id, kind, contentHint, fit, registerSource]);
|
|
385
|
+
(0, import_react4.useEffect)(() => {
|
|
386
|
+
const currentId = id;
|
|
387
|
+
return () => {
|
|
388
|
+
if (registeredRef.current) {
|
|
389
|
+
registeredRef.current = false;
|
|
390
|
+
setIsActive(false);
|
|
391
|
+
compositorRef.current.unregister(currentId);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
}, [id]);
|
|
395
|
+
(0, import_react4.useEffect)(() => {
|
|
396
|
+
setIsActive(compositor.activeId === id);
|
|
397
|
+
}, [compositor.activeId, id]);
|
|
398
|
+
const activate = (0, import_react4.useCallback)(() => {
|
|
399
|
+
const element = ref.current;
|
|
400
|
+
if (!element) return;
|
|
401
|
+
if (!registeredRef.current) {
|
|
402
|
+
registerSource(element);
|
|
403
|
+
}
|
|
404
|
+
compositorRef.current.activate(idRef.current);
|
|
405
|
+
setIsActive(true);
|
|
406
|
+
}, [registerSource]);
|
|
407
|
+
const deactivate = (0, import_react4.useCallback)(() => {
|
|
408
|
+
if (compositorRef.current.activeId === idRef.current) {
|
|
409
|
+
compositorRef.current.deactivate();
|
|
410
|
+
setIsActive(false);
|
|
411
|
+
}
|
|
412
|
+
}, []);
|
|
413
|
+
return (0, import_react4.useMemo)(
|
|
414
|
+
() => ({
|
|
415
|
+
ref,
|
|
416
|
+
isActive,
|
|
417
|
+
activate,
|
|
418
|
+
deactivate
|
|
419
|
+
}),
|
|
420
|
+
[isActive, activate, deactivate]
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
347
424
|
// src/index.ts
|
|
348
425
|
function useBroadcast2(options) {
|
|
349
426
|
return useBroadcast(options, import_browser2.createBroadcast);
|
|
350
427
|
}
|
|
351
|
-
function usePlayer2(
|
|
352
|
-
return usePlayer(
|
|
428
|
+
function usePlayer2(options) {
|
|
429
|
+
return usePlayer(options, import_browser2.createPlayer);
|
|
353
430
|
}
|
|
354
431
|
// Annotate the CommonJS export names for ESM import in node:
|
|
355
432
|
0 && (module.exports = {
|
|
356
433
|
CompositorProvider,
|
|
357
434
|
useBroadcast,
|
|
358
435
|
useCompositor,
|
|
359
|
-
usePlayer
|
|
436
|
+
usePlayer,
|
|
437
|
+
useSource
|
|
360
438
|
});
|
|
361
439
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/useBroadcast.ts","../src/usePlayer.ts","../src/useCompositor.tsx"],"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 CustomSource,\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","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 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 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 // Active source\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 crossfadeMs = 500,\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 crossfadeMs,\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\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"],"mappings":"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","names":["useBroadcast","usePlayer","import_browser","import_react","import_react","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(options: UsePlayerOptions): UsePlayerReturn {\n return baseUsePlayer(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 whepUrl: string | null;\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 options: UsePlayerOptions,\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 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 playerRef.current?.stop();\n };\n }, []);\n\n const updateStatus = useCallback(\n (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 );\n\n const play = useCallback(async () => {\n const currentWhepUrl = optionsRef.current.whepUrl;\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":["useBroadcast","usePlayer","import_browser","import_react","import_react","import_react","kind","contentHint","fit","useBroadcast","usePlayer"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReconnectConfig, VideoConfig, AudioConfig, ReconnectInfo, DaydreamError, CompositorOptions, Source, Size, Compositor } from '@daydreamlive/browser';
|
|
2
|
-
export { AudioConfig, BroadcastState, CanvasSource, Compositor, CompositorEvent, CompositorEventMap, CompositorOptions, ContentHint, Ctx2D,
|
|
1
|
+
import { ReconnectConfig, VideoConfig, AudioConfig, ReconnectInfo, DaydreamError, CompositorOptions, Source, Size, Compositor, ContentHint, FitMode } from '@daydreamlive/browser';
|
|
2
|
+
export { AudioConfig, BroadcastState, CanvasSource, Compositor, CompositorEvent, CompositorEventMap, CompositorOptions, ContentHint, Ctx2D, DaydreamError, DaydreamErrorCode, FitMode, PlayerState, ReconnectConfig, ReconnectInfo, Size, Source, VideoConfig, VideoSource } from '@daydreamlive/browser';
|
|
3
3
|
import { RefObject, PropsWithChildren } from 'react';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -38,9 +38,11 @@ interface UseBroadcastReturn {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
interface UsePlayerOptions {
|
|
41
|
+
whepUrl: string | null;
|
|
41
42
|
reconnect?: ReconnectConfig;
|
|
42
43
|
iceServers?: RTCIceServer[];
|
|
43
44
|
connectionTimeout?: number;
|
|
45
|
+
skipIceGathering?: boolean;
|
|
44
46
|
autoPlay?: boolean;
|
|
45
47
|
onStats?: (report: RTCStatsReport) => void;
|
|
46
48
|
statsIntervalMs?: number;
|
|
@@ -76,6 +78,27 @@ interface CompositorApi {
|
|
|
76
78
|
id: string;
|
|
77
79
|
source: Source;
|
|
78
80
|
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Register a source, activate it, and return an unregister function.
|
|
83
|
+
* Convenience method that combines register + activate with automatic cleanup.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```tsx
|
|
87
|
+
* useEffect(() => {
|
|
88
|
+
* const unregister = compositor.use("camera", {
|
|
89
|
+
* kind: "video",
|
|
90
|
+
* element: videoRef.current,
|
|
91
|
+
* fit: "cover",
|
|
92
|
+
* });
|
|
93
|
+
* return unregister;
|
|
94
|
+
* }, [compositor]);
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
use(id: string, source: Source): () => void;
|
|
98
|
+
/**
|
|
99
|
+
* Activate a registered source.
|
|
100
|
+
* @param id - The source ID to activate
|
|
101
|
+
*/
|
|
79
102
|
activate(id: string): void;
|
|
80
103
|
deactivate(): void;
|
|
81
104
|
readonly activeId: string | null;
|
|
@@ -93,10 +116,23 @@ interface CompositorApi {
|
|
|
93
116
|
}
|
|
94
117
|
interface CompositorProviderProps extends PropsWithChildren, Partial<Omit<CompositorOptions, "onSendFpsChange">> {
|
|
95
118
|
}
|
|
96
|
-
declare function CompositorProvider({ children, width, height, fps: initialFps, sendFps: initialSendFps, dpr,
|
|
119
|
+
declare function CompositorProvider({ children, width, height, fps: initialFps, sendFps: initialSendFps, dpr, keepalive, autoUnlockAudio, unlockEvents, disableSilentAudio, }: CompositorProviderProps): react_jsx_runtime.JSX.Element;
|
|
97
120
|
declare function useCompositor(): CompositorApi;
|
|
98
121
|
|
|
122
|
+
interface UseSourceOptions {
|
|
123
|
+
kind: "video" | "canvas";
|
|
124
|
+
contentHint?: ContentHint;
|
|
125
|
+
fit?: FitMode;
|
|
126
|
+
}
|
|
127
|
+
interface UseSourceReturn<T extends HTMLVideoElement | HTMLCanvasElement> {
|
|
128
|
+
ref: React.RefObject<T>;
|
|
129
|
+
isActive: boolean;
|
|
130
|
+
activate: () => void;
|
|
131
|
+
deactivate: () => void;
|
|
132
|
+
}
|
|
133
|
+
declare function useSource<T extends HTMLVideoElement | HTMLCanvasElement = HTMLVideoElement | HTMLCanvasElement>(id: string, options: UseSourceOptions): UseSourceReturn<T>;
|
|
134
|
+
|
|
99
135
|
declare function useBroadcast(options: UseBroadcastOptions): UseBroadcastReturn;
|
|
100
|
-
declare function usePlayer(
|
|
136
|
+
declare function usePlayer(options: UsePlayerOptions): UsePlayerReturn;
|
|
101
137
|
|
|
102
|
-
export { type CompositorApi, CompositorProvider, type CompositorProviderProps, type UseBroadcastOptions, type UseBroadcastReturn, type UseBroadcastStatus, type UsePlayerOptions, type UsePlayerReturn, type UsePlayerStatus, useBroadcast, useCompositor, usePlayer };
|
|
138
|
+
export { type CompositorApi, CompositorProvider, type CompositorProviderProps, type UseBroadcastOptions, type UseBroadcastReturn, type UseBroadcastStatus, type UsePlayerOptions, type UsePlayerReturn, type UsePlayerStatus, type UseSourceOptions, type UseSourceReturn, useBroadcast, useCompositor, usePlayer, useSource };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReconnectConfig, VideoConfig, AudioConfig, ReconnectInfo, DaydreamError, CompositorOptions, Source, Size, Compositor } from '@daydreamlive/browser';
|
|
2
|
-
export { AudioConfig, BroadcastState, CanvasSource, Compositor, CompositorEvent, CompositorEventMap, CompositorOptions, ContentHint, Ctx2D,
|
|
1
|
+
import { ReconnectConfig, VideoConfig, AudioConfig, ReconnectInfo, DaydreamError, CompositorOptions, Source, Size, Compositor, ContentHint, FitMode } from '@daydreamlive/browser';
|
|
2
|
+
export { AudioConfig, BroadcastState, CanvasSource, Compositor, CompositorEvent, CompositorEventMap, CompositorOptions, ContentHint, Ctx2D, DaydreamError, DaydreamErrorCode, FitMode, PlayerState, ReconnectConfig, ReconnectInfo, Size, Source, VideoConfig, VideoSource } from '@daydreamlive/browser';
|
|
3
3
|
import { RefObject, PropsWithChildren } from 'react';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -38,9 +38,11 @@ interface UseBroadcastReturn {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
interface UsePlayerOptions {
|
|
41
|
+
whepUrl: string | null;
|
|
41
42
|
reconnect?: ReconnectConfig;
|
|
42
43
|
iceServers?: RTCIceServer[];
|
|
43
44
|
connectionTimeout?: number;
|
|
45
|
+
skipIceGathering?: boolean;
|
|
44
46
|
autoPlay?: boolean;
|
|
45
47
|
onStats?: (report: RTCStatsReport) => void;
|
|
46
48
|
statsIntervalMs?: number;
|
|
@@ -76,6 +78,27 @@ interface CompositorApi {
|
|
|
76
78
|
id: string;
|
|
77
79
|
source: Source;
|
|
78
80
|
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Register a source, activate it, and return an unregister function.
|
|
83
|
+
* Convenience method that combines register + activate with automatic cleanup.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```tsx
|
|
87
|
+
* useEffect(() => {
|
|
88
|
+
* const unregister = compositor.use("camera", {
|
|
89
|
+
* kind: "video",
|
|
90
|
+
* element: videoRef.current,
|
|
91
|
+
* fit: "cover",
|
|
92
|
+
* });
|
|
93
|
+
* return unregister;
|
|
94
|
+
* }, [compositor]);
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
use(id: string, source: Source): () => void;
|
|
98
|
+
/**
|
|
99
|
+
* Activate a registered source.
|
|
100
|
+
* @param id - The source ID to activate
|
|
101
|
+
*/
|
|
79
102
|
activate(id: string): void;
|
|
80
103
|
deactivate(): void;
|
|
81
104
|
readonly activeId: string | null;
|
|
@@ -93,10 +116,23 @@ interface CompositorApi {
|
|
|
93
116
|
}
|
|
94
117
|
interface CompositorProviderProps extends PropsWithChildren, Partial<Omit<CompositorOptions, "onSendFpsChange">> {
|
|
95
118
|
}
|
|
96
|
-
declare function CompositorProvider({ children, width, height, fps: initialFps, sendFps: initialSendFps, dpr,
|
|
119
|
+
declare function CompositorProvider({ children, width, height, fps: initialFps, sendFps: initialSendFps, dpr, keepalive, autoUnlockAudio, unlockEvents, disableSilentAudio, }: CompositorProviderProps): react_jsx_runtime.JSX.Element;
|
|
97
120
|
declare function useCompositor(): CompositorApi;
|
|
98
121
|
|
|
122
|
+
interface UseSourceOptions {
|
|
123
|
+
kind: "video" | "canvas";
|
|
124
|
+
contentHint?: ContentHint;
|
|
125
|
+
fit?: FitMode;
|
|
126
|
+
}
|
|
127
|
+
interface UseSourceReturn<T extends HTMLVideoElement | HTMLCanvasElement> {
|
|
128
|
+
ref: React.RefObject<T>;
|
|
129
|
+
isActive: boolean;
|
|
130
|
+
activate: () => void;
|
|
131
|
+
deactivate: () => void;
|
|
132
|
+
}
|
|
133
|
+
declare function useSource<T extends HTMLVideoElement | HTMLCanvasElement = HTMLVideoElement | HTMLCanvasElement>(id: string, options: UseSourceOptions): UseSourceReturn<T>;
|
|
134
|
+
|
|
99
135
|
declare function useBroadcast(options: UseBroadcastOptions): UseBroadcastReturn;
|
|
100
|
-
declare function usePlayer(
|
|
136
|
+
declare function usePlayer(options: UsePlayerOptions): UsePlayerReturn;
|
|
101
137
|
|
|
102
|
-
export { type CompositorApi, CompositorProvider, type CompositorProviderProps, type UseBroadcastOptions, type UseBroadcastReturn, type UseBroadcastStatus, type UsePlayerOptions, type UsePlayerReturn, type UsePlayerStatus, useBroadcast, useCompositor, usePlayer };
|
|
138
|
+
export { type CompositorApi, CompositorProvider, type CompositorProviderProps, type UseBroadcastOptions, type UseBroadcastReturn, type UseBroadcastStatus, type UsePlayerOptions, type UsePlayerReturn, type UsePlayerStatus, type UseSourceOptions, type UseSourceReturn, useBroadcast, useCompositor, usePlayer, useSource };
|
package/dist/index.js
CHANGED
|
@@ -104,12 +104,11 @@ import {
|
|
|
104
104
|
useRef as useRef2,
|
|
105
105
|
useState as useState2
|
|
106
106
|
} from "react";
|
|
107
|
-
function usePlayer(
|
|
107
|
+
function usePlayer(options, factory) {
|
|
108
108
|
const [status, setStatus] = useState2({ state: "idle" });
|
|
109
109
|
const playerRef = useRef2(null);
|
|
110
110
|
const videoRef = useRef2(null);
|
|
111
111
|
const optionsRef = useRef2(options);
|
|
112
|
-
const whepUrlRef = useRef2(whepUrl);
|
|
113
112
|
const factoryRef = useRef2(factory);
|
|
114
113
|
useEffect2(() => {
|
|
115
114
|
optionsRef.current = options;
|
|
@@ -117,34 +116,34 @@ function usePlayer(whepUrl, options, factory) {
|
|
|
117
116
|
useEffect2(() => {
|
|
118
117
|
factoryRef.current = factory;
|
|
119
118
|
}, [factory]);
|
|
120
|
-
useEffect2(() => {
|
|
121
|
-
whepUrlRef.current = whepUrl;
|
|
122
|
-
}, [whepUrl]);
|
|
123
119
|
useEffect2(() => {
|
|
124
120
|
return () => {
|
|
125
121
|
playerRef.current?.stop();
|
|
126
122
|
};
|
|
127
123
|
}, []);
|
|
128
|
-
const updateStatus = useCallback2(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
124
|
+
const updateStatus = useCallback2(
|
|
125
|
+
(newState, error) => {
|
|
126
|
+
switch (newState) {
|
|
127
|
+
case "connecting":
|
|
128
|
+
setStatus({ state: "connecting" });
|
|
129
|
+
break;
|
|
130
|
+
case "playing":
|
|
131
|
+
setStatus({ state: "playing" });
|
|
132
|
+
break;
|
|
133
|
+
case "buffering":
|
|
134
|
+
break;
|
|
135
|
+
case "ended":
|
|
136
|
+
setStatus({ state: "ended" });
|
|
137
|
+
break;
|
|
138
|
+
case "error":
|
|
139
|
+
setStatus({ state: "error", error });
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
[]
|
|
144
|
+
);
|
|
146
145
|
const play = useCallback2(async () => {
|
|
147
|
-
const currentWhepUrl =
|
|
146
|
+
const currentWhepUrl = optionsRef.current.whepUrl;
|
|
148
147
|
if (!currentWhepUrl) {
|
|
149
148
|
return;
|
|
150
149
|
}
|
|
@@ -157,6 +156,7 @@ function usePlayer(whepUrl, options, factory) {
|
|
|
157
156
|
reconnect: optionsRef.current?.reconnect,
|
|
158
157
|
iceServers: optionsRef.current?.iceServers,
|
|
159
158
|
connectionTimeout: optionsRef.current?.connectionTimeout,
|
|
159
|
+
skipIceGathering: optionsRef.current?.skipIceGathering,
|
|
160
160
|
onStats: optionsRef.current?.onStats,
|
|
161
161
|
statsIntervalMs: optionsRef.current?.statsIntervalMs
|
|
162
162
|
});
|
|
@@ -232,7 +232,6 @@ function CompositorProvider({
|
|
|
232
232
|
fps: initialFps = 30,
|
|
233
233
|
sendFps: initialSendFps,
|
|
234
234
|
dpr,
|
|
235
|
-
crossfadeMs = 500,
|
|
236
235
|
keepalive,
|
|
237
236
|
autoUnlockAudio,
|
|
238
237
|
unlockEvents,
|
|
@@ -257,7 +256,6 @@ function CompositorProvider({
|
|
|
257
256
|
fps: initialFps,
|
|
258
257
|
sendFps: initialSendFps,
|
|
259
258
|
dpr,
|
|
260
|
-
crossfadeMs,
|
|
261
259
|
keepalive,
|
|
262
260
|
autoUnlockAudio,
|
|
263
261
|
unlockEvents,
|
|
@@ -297,6 +295,11 @@ function CompositorProvider({
|
|
|
297
295
|
get: (id) => compositorRef.current?.get(id),
|
|
298
296
|
has: (id) => compositorRef.current?.has(id) ?? false,
|
|
299
297
|
list: () => compositorRef.current?.list() ?? [],
|
|
298
|
+
use: (id, source) => {
|
|
299
|
+
compositorRef.current?.register(id, source);
|
|
300
|
+
compositorRef.current?.activate(id);
|
|
301
|
+
return () => compositorRef.current?.unregister(id);
|
|
302
|
+
},
|
|
300
303
|
// Active source
|
|
301
304
|
activate: (id) => compositorRef.current?.activate(id),
|
|
302
305
|
deactivate: () => compositorRef.current?.deactivate(),
|
|
@@ -332,17 +335,91 @@ function useCompositor() {
|
|
|
332
335
|
return ctx;
|
|
333
336
|
}
|
|
334
337
|
|
|
338
|
+
// src/useSource.ts
|
|
339
|
+
import { useEffect as useEffect4, useRef as useRef4, useState as useState4, useCallback as useCallback3, useMemo as useMemo2 } from "react";
|
|
340
|
+
function useSource(id, options) {
|
|
341
|
+
const compositor = useCompositor();
|
|
342
|
+
const compositorRef = useRef4(compositor);
|
|
343
|
+
compositorRef.current = compositor;
|
|
344
|
+
const ref = useRef4(null);
|
|
345
|
+
const [isActive, setIsActive] = useState4(false);
|
|
346
|
+
const registeredRef = useRef4(false);
|
|
347
|
+
const idRef = useRef4(id);
|
|
348
|
+
idRef.current = id;
|
|
349
|
+
const { kind, contentHint, fit } = options;
|
|
350
|
+
const optionsRef = useRef4({ kind, contentHint, fit });
|
|
351
|
+
optionsRef.current = { kind, contentHint, fit };
|
|
352
|
+
const registerSource = useCallback3((element) => {
|
|
353
|
+
const { kind: kind2, contentHint: contentHint2, fit: fit2 } = optionsRef.current;
|
|
354
|
+
const source = kind2 === "video" ? {
|
|
355
|
+
kind: "video",
|
|
356
|
+
element,
|
|
357
|
+
contentHint: contentHint2,
|
|
358
|
+
fit: fit2
|
|
359
|
+
} : {
|
|
360
|
+
kind: "canvas",
|
|
361
|
+
element,
|
|
362
|
+
contentHint: contentHint2
|
|
363
|
+
};
|
|
364
|
+
compositorRef.current.register(idRef.current, source);
|
|
365
|
+
registeredRef.current = true;
|
|
366
|
+
}, []);
|
|
367
|
+
useEffect4(() => {
|
|
368
|
+
const element = ref.current;
|
|
369
|
+
if (!element) return;
|
|
370
|
+
registerSource(element);
|
|
371
|
+
}, [id, kind, contentHint, fit, registerSource]);
|
|
372
|
+
useEffect4(() => {
|
|
373
|
+
const currentId = id;
|
|
374
|
+
return () => {
|
|
375
|
+
if (registeredRef.current) {
|
|
376
|
+
registeredRef.current = false;
|
|
377
|
+
setIsActive(false);
|
|
378
|
+
compositorRef.current.unregister(currentId);
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
}, [id]);
|
|
382
|
+
useEffect4(() => {
|
|
383
|
+
setIsActive(compositor.activeId === id);
|
|
384
|
+
}, [compositor.activeId, id]);
|
|
385
|
+
const activate = useCallback3(() => {
|
|
386
|
+
const element = ref.current;
|
|
387
|
+
if (!element) return;
|
|
388
|
+
if (!registeredRef.current) {
|
|
389
|
+
registerSource(element);
|
|
390
|
+
}
|
|
391
|
+
compositorRef.current.activate(idRef.current);
|
|
392
|
+
setIsActive(true);
|
|
393
|
+
}, [registerSource]);
|
|
394
|
+
const deactivate = useCallback3(() => {
|
|
395
|
+
if (compositorRef.current.activeId === idRef.current) {
|
|
396
|
+
compositorRef.current.deactivate();
|
|
397
|
+
setIsActive(false);
|
|
398
|
+
}
|
|
399
|
+
}, []);
|
|
400
|
+
return useMemo2(
|
|
401
|
+
() => ({
|
|
402
|
+
ref,
|
|
403
|
+
isActive,
|
|
404
|
+
activate,
|
|
405
|
+
deactivate
|
|
406
|
+
}),
|
|
407
|
+
[isActive, activate, deactivate]
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
|
|
335
411
|
// src/index.ts
|
|
336
412
|
function useBroadcast2(options) {
|
|
337
413
|
return useBroadcast(options, createBroadcast);
|
|
338
414
|
}
|
|
339
|
-
function usePlayer2(
|
|
340
|
-
return usePlayer(
|
|
415
|
+
function usePlayer2(options) {
|
|
416
|
+
return usePlayer(options, createPlayer);
|
|
341
417
|
}
|
|
342
418
|
export {
|
|
343
419
|
CompositorProvider,
|
|
344
420
|
useBroadcast2 as useBroadcast,
|
|
345
421
|
useCompositor,
|
|
346
|
-
usePlayer2 as usePlayer
|
|
422
|
+
usePlayer2 as usePlayer,
|
|
423
|
+
useSource
|
|
347
424
|
};
|
|
348
425
|
//# 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","../src/useCompositor.tsx"],"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 CustomSource,\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","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 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 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 // Active source\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 crossfadeMs = 500,\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 crossfadeMs,\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\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"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","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(options: UsePlayerOptions): UsePlayerReturn {\n return baseUsePlayer(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 whepUrl: string | null;\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 options: UsePlayerOptions,\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 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 playerRef.current?.stop();\n };\n }, []);\n\n const updateStatus = useCallback(\n (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 );\n\n const play = useCallback(async () => {\n const currentWhepUrl = optionsRef.current.whepUrl;\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.
|
|
3
|
+
"version": "0.3.1",
|
|
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": "
|
|
33
|
+
"@daydreamlive/browser": "*"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": ">=18.0.0"
|