vg-x07df 1.9.4 → 1.10.5

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.
@@ -80,7 +80,10 @@ function useVirtualBackground(options) {
80
80
  outputCategoryMask: true,
81
81
  modelAssetPath: void 0,
82
82
  // Decode base64 to Uint8Array
83
- modelAssetBuffer: Uint8Array.from(atob(selfie_segmenter_default), (c) => c.charCodeAt(0))
83
+ modelAssetBuffer: Uint8Array.from(
84
+ atob(selfie_segmenter_default),
85
+ (c) => c.charCodeAt(0)
86
+ )
84
87
  }
85
88
  };
86
89
  if (mode === "virtual-background" && imagePath) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/useVirtualBackground.ts","../../src/livekit/custom.ts"],"names":["useRoomContext","useLocalParticipant","useRef","useEffect","Track","BackgroundProcessor","RoomEvent","useParticipants"],"mappings":"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","file":"index.cjs","sourcesContent":["import { BackgroundProcessor } from '@livekit/track-processors';\r\nimport { useEffect, useRef } from 'react';\r\nimport selfieSegmenterModelBase64 from '../../assets/models/selfie_segmenter.tflite';\r\n\r\nimport {\r\n useLocalParticipant,\r\n useRoomContext,\r\n} from \"@livekit/components-react\";\r\nimport { Track, RoomEvent, type LocalVideoTrack } from \"livekit-client\";\r\n\r\nexport interface UseVirtualBackgroundOptions {\r\n /**\r\n * Image URL for virtual background mode.\r\n * Required when mode is 'virtual-background'.\r\n * Must have CORS enabled.\r\n */\r\n imagePath?: string | null;\r\n /**\r\n * Background processing mode\r\n * @default 'virtual-background'\r\n */\r\n mode?: \"virtual-background\" | \"blur\";\r\n /**\r\n * Blur radius for blur mode (1-20)\r\n * Only used when mode is 'blur'\r\n */\r\n blurRadius?: number;\r\n /**\r\n * Whether the virtual background is enabled\r\n * @default true\r\n */\r\n enabled?: boolean;\r\n}\r\n\r\nexport function useVirtualBackground(\r\n options: UseVirtualBackgroundOptions\r\n): void {\r\n const {\r\n imagePath,\r\n mode = \"virtual-background\",\r\n blurRadius,\r\n enabled = true,\r\n } = options;\r\n\r\n const room = useRoomContext();\r\n const participant = useLocalParticipant();\r\n const localParticipant = participant?.localParticipant;\r\n const processorRef = useRef<ReturnType<typeof BackgroundProcessor> | null>(\r\n null\r\n );\r\n const isActiveRef = useRef(true);\r\n const pendingOperationRef = useRef<Promise<void> | null>(null);\r\n\r\n useEffect(() => {\r\n // Reset active flag when effect runs\r\n isActiveRef.current = true;\r\n\r\n if (!enabled || !localParticipant || !room) {\r\n isActiveRef.current = false;\r\n return;\r\n }\r\n\r\n if (mode === \"virtual-background\" && !imagePath) {\r\n isActiveRef.current = false;\r\n return;\r\n }\r\n\r\n const applyBackground = async () => {\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n if (pendingOperationRef.current) {\r\n try {\r\n await pendingOperationRef.current;\r\n } catch (error) {\r\n console.error(\"Error in pending operation:\", error);\r\n }\r\n }\r\n\r\n // Check again after waiting (effect might have been cleaned up)\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n const operationPromise = (async () => {\r\n try {\r\n const cameraPublication = localParticipant.getTrackPublication(\r\n Track.Source.Camera\r\n );\r\n\r\n if (!cameraPublication?.track) {\r\n return;\r\n }\r\n\r\n // Check again after async gap\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n const localVideoTrack = cameraPublication.track as LocalVideoTrack\r\n\r\n if (processorRef.current) {\r\n try {\r\n await localVideoTrack.stopProcessor();\r\n } catch (error) {\r\n console.warn(\"Failed to remove background processor:\", error);\r\n }\r\n processorRef.current = null;\r\n }\r\n\r\n // Final check before adding new processor\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n // Create processor configuration\r\n const processorConfig: {\r\n mode: \"virtual-background\" | \"blur\";\r\n imagePath?: string;\r\n blurRadius?: number;\r\n segmenterOptions: {\r\n delegate: \"GPU\" | \"CPU\";\r\n modelAssetPath?: string | undefined;\r\n runningMode?: \"VIDEO\" | \"IMAGE\";\r\n outputConfidenceMasks?: boolean | undefined;\r\n outputCategoryMask?: boolean | undefined;\r\n modelAssetBuffer?: Uint8Array | ReadableStreamDefaultReader | undefined;\r\n };\r\n } = {\r\n mode,\r\n segmenterOptions: {\r\n delegate: \"GPU\",\r\n runningMode: \"IMAGE\",\r\n outputConfidenceMasks: true,\r\n outputCategoryMask: true,\r\n modelAssetPath: undefined,\r\n // Decode base64 to Uint8Array\r\n modelAssetBuffer: Uint8Array.from(atob(selfieSegmenterModelBase64), c => c.charCodeAt(0)),\r\n },\r\n };\r\n\r\n if (mode === \"virtual-background\" && imagePath) {\r\n processorConfig.imagePath = imagePath;\r\n } else if (mode === \"blur\" && blurRadius) {\r\n processorConfig.blurRadius = blurRadius;\r\n }\r\n\r\n // Create and apply new processor\r\n const processor = BackgroundProcessor(processorConfig);\r\n await localVideoTrack.setProcessor(processor);\r\n\r\n // Only set processor if effect is still active\r\n if (isActiveRef.current) {\r\n processorRef.current = processor;\r\n } else {\r\n // Effect was cleaned up, remove the processor we just added\r\n try {\r\n await localVideoTrack.stopProcessor();\r\n } catch (error) {\r\n console.error(\"Failed to remove background processor:\", error);\r\n }\r\n }\r\n } catch (error) {\r\n console.error(\"Failed to apply virtual background:\", error);\r\n }\r\n })();\r\n\r\n pendingOperationRef.current = operationPromise;\r\n\r\n try {\r\n await operationPromise;\r\n } finally {\r\n if (pendingOperationRef.current === operationPromise) {\r\n pendingOperationRef.current = null;\r\n }\r\n }\r\n };\r\n\r\n // Apply background immediately if track exists\r\n applyBackground().catch((error) => {\r\n console.error(\"Error in applyBackground:\", error);\r\n });\r\n\r\n // Listen for track published events (when camera is enabled)\r\n const handleTrackPublished = (publication: any) => {\r\n if (publication.source === Track.Source.Camera) {\r\n applyBackground().catch((error) => {\r\n console.error(\r\n \"Error in applyBackground from track published:\",\r\n error\r\n );\r\n });\r\n }\r\n };\r\n\r\n room.on(RoomEvent.LocalTrackPublished, handleTrackPublished);\r\n\r\n // Cleanup function\r\n return () => {\r\n isActiveRef.current = false;\r\n\r\n room.off(RoomEvent.LocalTrackPublished, handleTrackPublished);\r\n\r\n // Cleanup processor if it exists\r\n if (processorRef.current && localParticipant) {\r\n const cameraPublication = localParticipant.getTrackPublication(\r\n Track.Source.Camera\r\n );\r\n if (cameraPublication?.track) {\r\n const localVideoTrack = cameraPublication.track as LocalVideoTrack\r\n localVideoTrack\r\n .stopProcessor()\r\n .catch((error: unknown) => {\r\n console.warn(\r\n \"Failed to remove background processor on cleanup:\",\r\n error\r\n );\r\n });\r\n }\r\n processorRef.current = null;\r\n }\r\n };\r\n }, [imagePath, mode, blurRadius, enabled, localParticipant, room]);\r\n}\r\n\r\n/**\r\n * Hook to apply virtual background or blur to the local camera track\r\n *\r\n * @example\r\n * ```tsx\r\n * function VideoComponent() {\r\n * const [bgImage, setBgImage] = useState<string | null>(null);\r\n *\r\n * useVirtualBackground({\r\n * imagePath: bgImage,\r\n * mode: 'virtual-background',\r\n * enabled: !!bgImage\r\n * });\r\n *\r\n * return (\r\n * <button onClick= {() => setBgImage('https://example.com/bg.jpg')\r\n } >\r\n * Apply Background\r\n * </button>\r\n * );\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // Blur background\r\n * useVirtualBackground({\r\n * mode: 'blur',\r\n * blurRadius: 10\r\n * });\r\n * ```\r\n */\r\n","import {\r\n type UseParticipantsOptions,\r\n useParticipants,\r\n} from \"@livekit/components-react\";\r\n\r\nexport function useParticipantCount(options?: UseParticipantsOptions): number {\r\n const participants = useParticipants(options);\r\n return participants.length;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../src/hooks/useVirtualBackground.ts","../../src/livekit/custom.ts"],"names":["useRoomContext","useLocalParticipant","useRef","useEffect","Track","BackgroundProcessor","RoomEvent","useParticipants"],"mappings":"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","file":"index.cjs","sourcesContent":["import { BackgroundProcessor } from \"@livekit/track-processors\";\nimport { useEffect, useRef } from \"react\";\nimport selfieSegmenterModelBase64 from \"../../assets/models/selfie_segmenter.tflite\";\n\nimport { useLocalParticipant, useRoomContext } from \"@livekit/components-react\";\nimport { type LocalVideoTrack, RoomEvent, Track } from \"livekit-client\";\n\nexport interface UseVirtualBackgroundOptions {\n /**\n * Image URL for virtual background mode.\n * Required when mode is 'virtual-background'.\n * Must have CORS enabled.\n */\n imagePath?: string | null;\n /**\n * Background processing mode\n * @default 'virtual-background'\n */\n mode?: \"virtual-background\" | \"blur\";\n /**\n * Blur radius for blur mode (1-20)\n * Only used when mode is 'blur'\n */\n blurRadius?: number;\n /**\n * Whether the virtual background is enabled\n * @default true\n */\n enabled?: boolean;\n}\n\nexport function useVirtualBackground(\n options: UseVirtualBackgroundOptions\n): void {\n const {\n imagePath,\n mode = \"virtual-background\",\n blurRadius,\n enabled = true,\n } = options;\n\n const room = useRoomContext();\n const participant = useLocalParticipant();\n const localParticipant = participant?.localParticipant;\n const processorRef = useRef<ReturnType<typeof BackgroundProcessor> | null>(\n null\n );\n const isActiveRef = useRef(true);\n const pendingOperationRef = useRef<Promise<void> | null>(null);\n\n useEffect(() => {\n // Reset active flag when effect runs\n isActiveRef.current = true;\n\n if (!enabled || !localParticipant || !room) {\n isActiveRef.current = false;\n return;\n }\n\n if (mode === \"virtual-background\" && !imagePath) {\n isActiveRef.current = false;\n return;\n }\n\n const applyBackground = async () => {\n if (!isActiveRef.current) {\n return;\n }\n\n if (pendingOperationRef.current) {\n try {\n await pendingOperationRef.current;\n } catch (error) {\n console.error(\"Error in pending operation:\", error);\n }\n }\n\n // Check again after waiting (effect might have been cleaned up)\n if (!isActiveRef.current) {\n return;\n }\n\n const operationPromise = (async () => {\n try {\n const cameraPublication = localParticipant.getTrackPublication(\n Track.Source.Camera\n );\n\n if (!cameraPublication?.track) {\n return;\n }\n\n // Check again after async gap\n if (!isActiveRef.current) {\n return;\n }\n\n const localVideoTrack = cameraPublication.track as LocalVideoTrack;\n\n if (processorRef.current) {\n try {\n await localVideoTrack.stopProcessor();\n } catch (error) {\n console.warn(\"Failed to remove background processor:\", error);\n }\n processorRef.current = null;\n }\n\n // Final check before adding new processor\n if (!isActiveRef.current) {\n return;\n }\n\n // Create processor configuration\n const processorConfig: {\n mode: \"virtual-background\" | \"blur\";\n imagePath?: string;\n blurRadius?: number;\n segmenterOptions: {\n delegate: \"GPU\" | \"CPU\";\n modelAssetPath?: string | undefined;\n runningMode?: \"VIDEO\" | \"IMAGE\";\n outputConfidenceMasks?: boolean | undefined;\n outputCategoryMask?: boolean | undefined;\n modelAssetBuffer?:\n | Uint8Array\n | ReadableStreamDefaultReader\n | undefined;\n };\n } = {\n mode,\n segmenterOptions: {\n delegate: \"GPU\",\n runningMode: \"IMAGE\",\n outputConfidenceMasks: true,\n outputCategoryMask: true,\n modelAssetPath: undefined,\n // Decode base64 to Uint8Array\n modelAssetBuffer: Uint8Array.from(\n atob(selfieSegmenterModelBase64),\n (c) => c.charCodeAt(0)\n ),\n },\n };\n\n if (mode === \"virtual-background\" && imagePath) {\n processorConfig.imagePath = imagePath;\n } else if (mode === \"blur\" && blurRadius) {\n processorConfig.blurRadius = blurRadius;\n }\n\n // Create and apply new processor\n const processor = BackgroundProcessor(processorConfig);\n await localVideoTrack.setProcessor(processor);\n\n // Only set processor if effect is still active\n if (isActiveRef.current) {\n processorRef.current = processor;\n } else {\n // Effect was cleaned up, remove the processor we just added\n try {\n await localVideoTrack.stopProcessor();\n } catch (error) {\n console.error(\"Failed to remove background processor:\", error);\n }\n }\n } catch (error) {\n console.error(\"Failed to apply virtual background:\", error);\n }\n })();\n\n pendingOperationRef.current = operationPromise;\n\n try {\n await operationPromise;\n } finally {\n if (pendingOperationRef.current === operationPromise) {\n pendingOperationRef.current = null;\n }\n }\n };\n\n // Apply background immediately if track exists\n applyBackground().catch((error) => {\n console.error(\"Error in applyBackground:\", error);\n });\n\n // Listen for track published events (when camera is enabled)\n const handleTrackPublished = (publication: any) => {\n if (publication.source === Track.Source.Camera) {\n applyBackground().catch((error) => {\n console.error(\n \"Error in applyBackground from track published:\",\n error\n );\n });\n }\n };\n\n room.on(RoomEvent.LocalTrackPublished, handleTrackPublished);\n\n // Cleanup function\n return () => {\n isActiveRef.current = false;\n\n room.off(RoomEvent.LocalTrackPublished, handleTrackPublished);\n\n // Cleanup processor if it exists\n if (processorRef.current && localParticipant) {\n const cameraPublication = localParticipant.getTrackPublication(\n Track.Source.Camera\n );\n if (cameraPublication?.track) {\n const localVideoTrack = cameraPublication.track as LocalVideoTrack;\n localVideoTrack.stopProcessor().catch((error: unknown) => {\n console.warn(\n \"Failed to remove background processor on cleanup:\",\n error\n );\n });\n }\n processorRef.current = null;\n }\n };\n }, [imagePath, mode, blurRadius, enabled, localParticipant, room]);\n}\n\n/**\n * Hook to apply virtual background or blur to the local camera track\n *\n * @example\n * ```tsx\n * function VideoComponent() {\n * const [bgImage, setBgImage] = useState<string | null>(null);\n *\n * useVirtualBackground({\n * imagePath: bgImage,\n * mode: 'virtual-background',\n * enabled: !!bgImage\n * });\n *\n * return (\n * <button onClick= {() => setBgImage('https://example.com/bg.jpg')\n } >\n * Apply Background\n * </button>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Blur background\n * useVirtualBackground({\n * mode: 'blur',\n * blurRadius: 10\n * });\n * ```\n */\n","import {\n type UseParticipantsOptions,\n useParticipants,\n} from \"@livekit/components-react\";\n\nexport function useParticipantCount(options?: UseParticipantsOptions): number {\n const participants = useParticipants(options);\n return participants.length;\n}\n"]}
@@ -81,7 +81,10 @@ function useVirtualBackground(options) {
81
81
  outputCategoryMask: true,
82
82
  modelAssetPath: void 0,
83
83
  // Decode base64 to Uint8Array
84
- modelAssetBuffer: Uint8Array.from(atob(selfie_segmenter_default), (c) => c.charCodeAt(0))
84
+ modelAssetBuffer: Uint8Array.from(
85
+ atob(selfie_segmenter_default),
86
+ (c) => c.charCodeAt(0)
87
+ )
85
88
  }
86
89
  };
87
90
  if (mode === "virtual-background" && imagePath) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/useVirtualBackground.ts","../../src/livekit/custom.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { BackgroundProcessor } from '@livekit/track-processors';\r\nimport { useEffect, useRef } from 'react';\r\nimport selfieSegmenterModelBase64 from '../../assets/models/selfie_segmenter.tflite';\r\n\r\nimport {\r\n useLocalParticipant,\r\n useRoomContext,\r\n} from \"@livekit/components-react\";\r\nimport { Track, RoomEvent, type LocalVideoTrack } from \"livekit-client\";\r\n\r\nexport interface UseVirtualBackgroundOptions {\r\n /**\r\n * Image URL for virtual background mode.\r\n * Required when mode is 'virtual-background'.\r\n * Must have CORS enabled.\r\n */\r\n imagePath?: string | null;\r\n /**\r\n * Background processing mode\r\n * @default 'virtual-background'\r\n */\r\n mode?: \"virtual-background\" | \"blur\";\r\n /**\r\n * Blur radius for blur mode (1-20)\r\n * Only used when mode is 'blur'\r\n */\r\n blurRadius?: number;\r\n /**\r\n * Whether the virtual background is enabled\r\n * @default true\r\n */\r\n enabled?: boolean;\r\n}\r\n\r\nexport function useVirtualBackground(\r\n options: UseVirtualBackgroundOptions\r\n): void {\r\n const {\r\n imagePath,\r\n mode = \"virtual-background\",\r\n blurRadius,\r\n enabled = true,\r\n } = options;\r\n\r\n const room = useRoomContext();\r\n const participant = useLocalParticipant();\r\n const localParticipant = participant?.localParticipant;\r\n const processorRef = useRef<ReturnType<typeof BackgroundProcessor> | null>(\r\n null\r\n );\r\n const isActiveRef = useRef(true);\r\n const pendingOperationRef = useRef<Promise<void> | null>(null);\r\n\r\n useEffect(() => {\r\n // Reset active flag when effect runs\r\n isActiveRef.current = true;\r\n\r\n if (!enabled || !localParticipant || !room) {\r\n isActiveRef.current = false;\r\n return;\r\n }\r\n\r\n if (mode === \"virtual-background\" && !imagePath) {\r\n isActiveRef.current = false;\r\n return;\r\n }\r\n\r\n const applyBackground = async () => {\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n if (pendingOperationRef.current) {\r\n try {\r\n await pendingOperationRef.current;\r\n } catch (error) {\r\n console.error(\"Error in pending operation:\", error);\r\n }\r\n }\r\n\r\n // Check again after waiting (effect might have been cleaned up)\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n const operationPromise = (async () => {\r\n try {\r\n const cameraPublication = localParticipant.getTrackPublication(\r\n Track.Source.Camera\r\n );\r\n\r\n if (!cameraPublication?.track) {\r\n return;\r\n }\r\n\r\n // Check again after async gap\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n const localVideoTrack = cameraPublication.track as LocalVideoTrack\r\n\r\n if (processorRef.current) {\r\n try {\r\n await localVideoTrack.stopProcessor();\r\n } catch (error) {\r\n console.warn(\"Failed to remove background processor:\", error);\r\n }\r\n processorRef.current = null;\r\n }\r\n\r\n // Final check before adding new processor\r\n if (!isActiveRef.current) {\r\n return;\r\n }\r\n\r\n // Create processor configuration\r\n const processorConfig: {\r\n mode: \"virtual-background\" | \"blur\";\r\n imagePath?: string;\r\n blurRadius?: number;\r\n segmenterOptions: {\r\n delegate: \"GPU\" | \"CPU\";\r\n modelAssetPath?: string | undefined;\r\n runningMode?: \"VIDEO\" | \"IMAGE\";\r\n outputConfidenceMasks?: boolean | undefined;\r\n outputCategoryMask?: boolean | undefined;\r\n modelAssetBuffer?: Uint8Array | ReadableStreamDefaultReader | undefined;\r\n };\r\n } = {\r\n mode,\r\n segmenterOptions: {\r\n delegate: \"GPU\",\r\n runningMode: \"IMAGE\",\r\n outputConfidenceMasks: true,\r\n outputCategoryMask: true,\r\n modelAssetPath: undefined,\r\n // Decode base64 to Uint8Array\r\n modelAssetBuffer: Uint8Array.from(atob(selfieSegmenterModelBase64), c => c.charCodeAt(0)),\r\n },\r\n };\r\n\r\n if (mode === \"virtual-background\" && imagePath) {\r\n processorConfig.imagePath = imagePath;\r\n } else if (mode === \"blur\" && blurRadius) {\r\n processorConfig.blurRadius = blurRadius;\r\n }\r\n\r\n // Create and apply new processor\r\n const processor = BackgroundProcessor(processorConfig);\r\n await localVideoTrack.setProcessor(processor);\r\n\r\n // Only set processor if effect is still active\r\n if (isActiveRef.current) {\r\n processorRef.current = processor;\r\n } else {\r\n // Effect was cleaned up, remove the processor we just added\r\n try {\r\n await localVideoTrack.stopProcessor();\r\n } catch (error) {\r\n console.error(\"Failed to remove background processor:\", error);\r\n }\r\n }\r\n } catch (error) {\r\n console.error(\"Failed to apply virtual background:\", error);\r\n }\r\n })();\r\n\r\n pendingOperationRef.current = operationPromise;\r\n\r\n try {\r\n await operationPromise;\r\n } finally {\r\n if (pendingOperationRef.current === operationPromise) {\r\n pendingOperationRef.current = null;\r\n }\r\n }\r\n };\r\n\r\n // Apply background immediately if track exists\r\n applyBackground().catch((error) => {\r\n console.error(\"Error in applyBackground:\", error);\r\n });\r\n\r\n // Listen for track published events (when camera is enabled)\r\n const handleTrackPublished = (publication: any) => {\r\n if (publication.source === Track.Source.Camera) {\r\n applyBackground().catch((error) => {\r\n console.error(\r\n \"Error in applyBackground from track published:\",\r\n error\r\n );\r\n });\r\n }\r\n };\r\n\r\n room.on(RoomEvent.LocalTrackPublished, handleTrackPublished);\r\n\r\n // Cleanup function\r\n return () => {\r\n isActiveRef.current = false;\r\n\r\n room.off(RoomEvent.LocalTrackPublished, handleTrackPublished);\r\n\r\n // Cleanup processor if it exists\r\n if (processorRef.current && localParticipant) {\r\n const cameraPublication = localParticipant.getTrackPublication(\r\n Track.Source.Camera\r\n );\r\n if (cameraPublication?.track) {\r\n const localVideoTrack = cameraPublication.track as LocalVideoTrack\r\n localVideoTrack\r\n .stopProcessor()\r\n .catch((error: unknown) => {\r\n console.warn(\r\n \"Failed to remove background processor on cleanup:\",\r\n error\r\n );\r\n });\r\n }\r\n processorRef.current = null;\r\n }\r\n };\r\n }, [imagePath, mode, blurRadius, enabled, localParticipant, room]);\r\n}\r\n\r\n/**\r\n * Hook to apply virtual background or blur to the local camera track\r\n *\r\n * @example\r\n * ```tsx\r\n * function VideoComponent() {\r\n * const [bgImage, setBgImage] = useState<string | null>(null);\r\n *\r\n * useVirtualBackground({\r\n * imagePath: bgImage,\r\n * mode: 'virtual-background',\r\n * enabled: !!bgImage\r\n * });\r\n *\r\n * return (\r\n * <button onClick= {() => setBgImage('https://example.com/bg.jpg')\r\n } >\r\n * Apply Background\r\n * </button>\r\n * );\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // Blur background\r\n * useVirtualBackground({\r\n * mode: 'blur',\r\n * blurRadius: 10\r\n * });\r\n * ```\r\n */\r\n","import {\r\n type UseParticipantsOptions,\r\n useParticipants,\r\n} from \"@livekit/components-react\";\r\n\r\nexport function useParticipantCount(options?: UseParticipantsOptions): number {\r\n const participants = useParticipants(options);\r\n return participants.length;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../src/hooks/useVirtualBackground.ts","../../src/livekit/custom.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { BackgroundProcessor } from \"@livekit/track-processors\";\nimport { useEffect, useRef } from \"react\";\nimport selfieSegmenterModelBase64 from \"../../assets/models/selfie_segmenter.tflite\";\n\nimport { useLocalParticipant, useRoomContext } from \"@livekit/components-react\";\nimport { type LocalVideoTrack, RoomEvent, Track } from \"livekit-client\";\n\nexport interface UseVirtualBackgroundOptions {\n /**\n * Image URL for virtual background mode.\n * Required when mode is 'virtual-background'.\n * Must have CORS enabled.\n */\n imagePath?: string | null;\n /**\n * Background processing mode\n * @default 'virtual-background'\n */\n mode?: \"virtual-background\" | \"blur\";\n /**\n * Blur radius for blur mode (1-20)\n * Only used when mode is 'blur'\n */\n blurRadius?: number;\n /**\n * Whether the virtual background is enabled\n * @default true\n */\n enabled?: boolean;\n}\n\nexport function useVirtualBackground(\n options: UseVirtualBackgroundOptions\n): void {\n const {\n imagePath,\n mode = \"virtual-background\",\n blurRadius,\n enabled = true,\n } = options;\n\n const room = useRoomContext();\n const participant = useLocalParticipant();\n const localParticipant = participant?.localParticipant;\n const processorRef = useRef<ReturnType<typeof BackgroundProcessor> | null>(\n null\n );\n const isActiveRef = useRef(true);\n const pendingOperationRef = useRef<Promise<void> | null>(null);\n\n useEffect(() => {\n // Reset active flag when effect runs\n isActiveRef.current = true;\n\n if (!enabled || !localParticipant || !room) {\n isActiveRef.current = false;\n return;\n }\n\n if (mode === \"virtual-background\" && !imagePath) {\n isActiveRef.current = false;\n return;\n }\n\n const applyBackground = async () => {\n if (!isActiveRef.current) {\n return;\n }\n\n if (pendingOperationRef.current) {\n try {\n await pendingOperationRef.current;\n } catch (error) {\n console.error(\"Error in pending operation:\", error);\n }\n }\n\n // Check again after waiting (effect might have been cleaned up)\n if (!isActiveRef.current) {\n return;\n }\n\n const operationPromise = (async () => {\n try {\n const cameraPublication = localParticipant.getTrackPublication(\n Track.Source.Camera\n );\n\n if (!cameraPublication?.track) {\n return;\n }\n\n // Check again after async gap\n if (!isActiveRef.current) {\n return;\n }\n\n const localVideoTrack = cameraPublication.track as LocalVideoTrack;\n\n if (processorRef.current) {\n try {\n await localVideoTrack.stopProcessor();\n } catch (error) {\n console.warn(\"Failed to remove background processor:\", error);\n }\n processorRef.current = null;\n }\n\n // Final check before adding new processor\n if (!isActiveRef.current) {\n return;\n }\n\n // Create processor configuration\n const processorConfig: {\n mode: \"virtual-background\" | \"blur\";\n imagePath?: string;\n blurRadius?: number;\n segmenterOptions: {\n delegate: \"GPU\" | \"CPU\";\n modelAssetPath?: string | undefined;\n runningMode?: \"VIDEO\" | \"IMAGE\";\n outputConfidenceMasks?: boolean | undefined;\n outputCategoryMask?: boolean | undefined;\n modelAssetBuffer?:\n | Uint8Array\n | ReadableStreamDefaultReader\n | undefined;\n };\n } = {\n mode,\n segmenterOptions: {\n delegate: \"GPU\",\n runningMode: \"IMAGE\",\n outputConfidenceMasks: true,\n outputCategoryMask: true,\n modelAssetPath: undefined,\n // Decode base64 to Uint8Array\n modelAssetBuffer: Uint8Array.from(\n atob(selfieSegmenterModelBase64),\n (c) => c.charCodeAt(0)\n ),\n },\n };\n\n if (mode === \"virtual-background\" && imagePath) {\n processorConfig.imagePath = imagePath;\n } else if (mode === \"blur\" && blurRadius) {\n processorConfig.blurRadius = blurRadius;\n }\n\n // Create and apply new processor\n const processor = BackgroundProcessor(processorConfig);\n await localVideoTrack.setProcessor(processor);\n\n // Only set processor if effect is still active\n if (isActiveRef.current) {\n processorRef.current = processor;\n } else {\n // Effect was cleaned up, remove the processor we just added\n try {\n await localVideoTrack.stopProcessor();\n } catch (error) {\n console.error(\"Failed to remove background processor:\", error);\n }\n }\n } catch (error) {\n console.error(\"Failed to apply virtual background:\", error);\n }\n })();\n\n pendingOperationRef.current = operationPromise;\n\n try {\n await operationPromise;\n } finally {\n if (pendingOperationRef.current === operationPromise) {\n pendingOperationRef.current = null;\n }\n }\n };\n\n // Apply background immediately if track exists\n applyBackground().catch((error) => {\n console.error(\"Error in applyBackground:\", error);\n });\n\n // Listen for track published events (when camera is enabled)\n const handleTrackPublished = (publication: any) => {\n if (publication.source === Track.Source.Camera) {\n applyBackground().catch((error) => {\n console.error(\n \"Error in applyBackground from track published:\",\n error\n );\n });\n }\n };\n\n room.on(RoomEvent.LocalTrackPublished, handleTrackPublished);\n\n // Cleanup function\n return () => {\n isActiveRef.current = false;\n\n room.off(RoomEvent.LocalTrackPublished, handleTrackPublished);\n\n // Cleanup processor if it exists\n if (processorRef.current && localParticipant) {\n const cameraPublication = localParticipant.getTrackPublication(\n Track.Source.Camera\n );\n if (cameraPublication?.track) {\n const localVideoTrack = cameraPublication.track as LocalVideoTrack;\n localVideoTrack.stopProcessor().catch((error: unknown) => {\n console.warn(\n \"Failed to remove background processor on cleanup:\",\n error\n );\n });\n }\n processorRef.current = null;\n }\n };\n }, [imagePath, mode, blurRadius, enabled, localParticipant, room]);\n}\n\n/**\n * Hook to apply virtual background or blur to the local camera track\n *\n * @example\n * ```tsx\n * function VideoComponent() {\n * const [bgImage, setBgImage] = useState<string | null>(null);\n *\n * useVirtualBackground({\n * imagePath: bgImage,\n * mode: 'virtual-background',\n * enabled: !!bgImage\n * });\n *\n * return (\n * <button onClick= {() => setBgImage('https://example.com/bg.jpg')\n } >\n * Apply Background\n * </button>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Blur background\n * useVirtualBackground({\n * mode: 'blur',\n * blurRadius: 10\n * });\n * ```\n */\n","import {\n type UseParticipantsOptions,\n useParticipants,\n} from \"@livekit/components-react\";\n\nexport function useParticipantCount(options?: UseParticipantsOptions): number {\n const participants = useParticipants(options);\n return participants.length;\n}\n"]}
@@ -38,6 +38,11 @@ interface RecordingInfo {
38
38
  startedAt: string;
39
39
  initiatedBy?: string;
40
40
  }
41
+ type SessionType = "CALL" | "MEETING";
42
+ interface MeetingInfo {
43
+ meetingId: string;
44
+ meetingCode: string;
45
+ }
41
46
  interface Session {
42
47
  id: string;
43
48
  status: "initializing" | "pending" | "ready" | "active" | "ended";
@@ -47,6 +52,8 @@ interface Session {
47
52
  startedAt?: string;
48
53
  ringTimeoutMs?: number;
49
54
  recording?: RecordingInfo | null;
55
+ sessionType?: SessionType;
56
+ meetingInfo?: MeetingInfo;
50
57
  }
51
58
  interface IncomingInvite {
52
59
  callId: string;
@@ -59,7 +66,7 @@ interface IncomingInvite {
59
66
  }
60
67
  interface OutgoingInvite {
61
68
  userId: string;
62
- status: "sent" | "accepted" | "declined" | "missed";
69
+ status: "sent" | "accepted" | "declined" | "missed" | "left";
63
70
  participant?: Omit<ParticipantMetadata, "permissions"> | undefined;
64
71
  }
65
72
  interface RtcError {
@@ -68,12 +75,18 @@ interface RtcError {
68
75
  timestamp: number;
69
76
  context?: any;
70
77
  }
78
+ interface GuestIdentity {
79
+ guestId: string;
80
+ displayName: string;
81
+ }
71
82
  interface RtcState {
72
83
  initiated: boolean;
73
84
  session: Session | null;
74
85
  incomingInvite: IncomingInvite | null;
75
86
  outgoingInvites: Record<string, OutgoingInvite>;
76
87
  errors: RtcError[];
88
+ guestIdentity: GuestIdentity | null;
89
+ isGuestMode: boolean;
77
90
  }
78
91
  interface ParticipantListOptions {
79
92
  pageSize?: number;
@@ -97,4 +110,4 @@ interface ParticipantListReturn {
97
110
  isPinned: (participantId: string) => boolean;
98
111
  }
99
112
 
100
- export type { IncomingInvite as I, LiveKitJoinInfo as L, OutgoingInvite as O, ParticipantMetadata as P, RtcState as R, Session as S, RtcError as a, ParticipantPermissions as b, Profile as c, ParticipantListOptions as d, ParticipantListReturn as e, RecordingInfo as f };
113
+ export type { GuestIdentity as G, IncomingInvite as I, LiveKitJoinInfo as L, MeetingInfo as M, OutgoingInvite as O, ParticipantMetadata as P, RtcState as R, Session as S, RtcError as a, ParticipantPermissions as b, Profile as c, ParticipantListOptions as d, ParticipantListReturn as e, RecordingInfo as f, SessionType as g };
@@ -38,6 +38,11 @@ interface RecordingInfo {
38
38
  startedAt: string;
39
39
  initiatedBy?: string;
40
40
  }
41
+ type SessionType = "CALL" | "MEETING";
42
+ interface MeetingInfo {
43
+ meetingId: string;
44
+ meetingCode: string;
45
+ }
41
46
  interface Session {
42
47
  id: string;
43
48
  status: "initializing" | "pending" | "ready" | "active" | "ended";
@@ -47,6 +52,8 @@ interface Session {
47
52
  startedAt?: string;
48
53
  ringTimeoutMs?: number;
49
54
  recording?: RecordingInfo | null;
55
+ sessionType?: SessionType;
56
+ meetingInfo?: MeetingInfo;
50
57
  }
51
58
  interface IncomingInvite {
52
59
  callId: string;
@@ -59,7 +66,7 @@ interface IncomingInvite {
59
66
  }
60
67
  interface OutgoingInvite {
61
68
  userId: string;
62
- status: "sent" | "accepted" | "declined" | "missed";
69
+ status: "sent" | "accepted" | "declined" | "missed" | "left";
63
70
  participant?: Omit<ParticipantMetadata, "permissions"> | undefined;
64
71
  }
65
72
  interface RtcError {
@@ -68,12 +75,18 @@ interface RtcError {
68
75
  timestamp: number;
69
76
  context?: any;
70
77
  }
78
+ interface GuestIdentity {
79
+ guestId: string;
80
+ displayName: string;
81
+ }
71
82
  interface RtcState {
72
83
  initiated: boolean;
73
84
  session: Session | null;
74
85
  incomingInvite: IncomingInvite | null;
75
86
  outgoingInvites: Record<string, OutgoingInvite>;
76
87
  errors: RtcError[];
88
+ guestIdentity: GuestIdentity | null;
89
+ isGuestMode: boolean;
77
90
  }
78
91
  interface ParticipantListOptions {
79
92
  pageSize?: number;
@@ -97,4 +110,4 @@ interface ParticipantListReturn {
97
110
  isPinned: (participantId: string) => boolean;
98
111
  }
99
112
 
100
- export type { IncomingInvite as I, LiveKitJoinInfo as L, OutgoingInvite as O, ParticipantMetadata as P, RtcState as R, Session as S, RtcError as a, ParticipantPermissions as b, Profile as c, ParticipantListOptions as d, ParticipantListReturn as e, RecordingInfo as f };
113
+ export type { GuestIdentity as G, IncomingInvite as I, LiveKitJoinInfo as L, MeetingInfo as M, OutgoingInvite as O, ParticipantMetadata as P, RtcState as R, Session as S, RtcError as a, ParticipantPermissions as b, Profile as c, ParticipantListOptions as d, ParticipantListReturn as e, RecordingInfo as f, SessionType as g };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/logger.ts","../../src/utils/duration.ts","../../src/utils/video.ts"],"names":["Track"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Comprehensive logging system for the Callpad Web SDK\r\n *\r\n * Features:\r\n * - Log level filtering (debug, info, warn, error)\r\n * - Environment variable configuration (DEBUG, CALLPAD_LOG_LEVEL)\r\n * - Hierarchical namespacing (callpad:socket:connection)\r\n * - Custom logger integration\r\n * - Zero-cost when disabled\r\n */\r\n\r\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\r\n\r\nexport interface LoggerOptions {\r\n level?: LogLevel;\r\n enableDebug?: boolean;\r\n customLogger?: (level: LogLevel, message: string, meta?: any) => void;\r\n}\r\n\r\nexport interface CallpadLogger {\r\n debug(message: string, meta?: any): void;\r\n info(message: string, meta?: any): void;\r\n warn(message: string, meta?: any): void;\r\n error(message: string, meta?: any): void;\r\n child(namespace: string): CallpadLogger;\r\n setLevel(level: LogLevel): void;\r\n isLevelEnabled(level: LogLevel): boolean;\r\n}\r\n\r\nconst LOG_LEVELS: Record<LogLevel, number> = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n};\r\n\r\nclass CallpadLoggerImpl implements CallpadLogger {\r\n private namespace: string;\r\n private level: LogLevel;\r\n private enableDebug: boolean;\r\n private customLogger?: (level: LogLevel, message: string, meta?: any) => void;\r\n\r\n constructor(namespace = \"callpad\", options: LoggerOptions = {}) {\r\n this.namespace = namespace;\r\n this.level = options.level ?? this.getDefaultLevel();\r\n this.enableDebug = options.enableDebug ?? this.shouldEnableDebug();\r\n if (options.customLogger) {\r\n this.customLogger = options.customLogger;\r\n }\r\n }\r\n\r\n private getDefaultLevel(): LogLevel {\r\n const envLevel =\r\n typeof window !== \"undefined\"\r\n ? (window as any).__CALLPAD_LOG_LEVEL__\r\n : typeof globalThis !== \"undefined\" &&\r\n (globalThis as any).process?.env?.CALLPAD_LOG_LEVEL;\r\n\r\n if (envLevel && this.isValidLogLevel(envLevel)) {\r\n return envLevel as LogLevel;\r\n }\r\n\r\n const isProduction =\r\n typeof globalThis !== \"undefined\" &&\r\n (globalThis as any).process?.env?.NODE_ENV === \"production\";\r\n\r\n return isProduction ? \"warn\" : \"info\";\r\n }\r\n\r\n private shouldEnableDebug(): boolean {\r\n const debugEnv =\r\n typeof window !== \"undefined\"\r\n ? (window as any).__DEBUG__\r\n : typeof globalThis !== \"undefined\" &&\r\n (globalThis as any).process?.env?.DEBUG;\r\n\r\n if (!debugEnv) return false;\r\n\r\n const debugPatterns = debugEnv.split(/[\\s,]+/);\r\n return debugPatterns.some((pattern: string) => {\r\n if (pattern === \"*\") return true;\r\n if (pattern.endsWith(\"*\")) {\r\n const prefix = pattern.slice(0, -1);\r\n return this.namespace.startsWith(prefix);\r\n }\r\n return this.namespace === pattern;\r\n });\r\n }\r\n\r\n private isValidLogLevel(level: string): boolean {\r\n return Object.keys(LOG_LEVELS).includes(level);\r\n }\r\n\r\n private shouldLog(level: LogLevel): boolean {\r\n if (level === \"debug\" && !this.enableDebug) {\r\n return false;\r\n }\r\n return LOG_LEVELS[level] >= LOG_LEVELS[this.level];\r\n }\r\n\r\n private formatMessage(level: LogLevel, message: string, meta?: any): void {\r\n if (!this.shouldLog(level)) return;\r\n\r\n const timestamp = new Date().toISOString();\r\n const prefix = `[${timestamp}] [${this.namespace}] [${level.toUpperCase()}]`;\r\n\r\n if (this.customLogger) {\r\n this.customLogger(level, message, meta);\r\n return;\r\n }\r\n\r\n const logMethod =\r\n level === \"error\"\r\n ? console.error\r\n : level === \"warn\"\r\n ? console.warn\r\n : level === \"info\"\r\n ? console.info\r\n : console.log;\r\n\r\n if (meta !== undefined) {\r\n logMethod(`${prefix} ${message}`, meta);\r\n } else {\r\n logMethod(`${prefix} ${message}`);\r\n }\r\n }\r\n\r\n debug(message: string, meta?: any): void {\r\n this.formatMessage(\"debug\", message, meta);\r\n }\r\n\r\n info(message: string, meta?: any): void {\r\n this.formatMessage(\"info\", message, meta);\r\n }\r\n\r\n warn(message: string, meta?: any): void {\r\n this.formatMessage(\"warn\", message, meta);\r\n }\r\n\r\n error(message: string, meta?: any): void {\r\n this.formatMessage(\"error\", message, meta);\r\n }\r\n\r\n child(namespace: string): CallpadLogger {\r\n const childNamespace = `${this.namespace}:${namespace}`;\r\n const childOptions: LoggerOptions = {\r\n level: this.level,\r\n enableDebug: this.enableDebug,\r\n };\r\n if (this.customLogger) {\r\n childOptions.customLogger = this.customLogger;\r\n }\r\n return new CallpadLoggerImpl(childNamespace, childOptions);\r\n }\r\n\r\n setLevel(level: LogLevel): void {\r\n this.level = level;\r\n }\r\n\r\n isLevelEnabled(level: LogLevel): boolean {\r\n return this.shouldLog(level);\r\n }\r\n}\r\n\r\nlet rootLogger: CallpadLogger | null = null;\r\n\r\nexport function createLogger(\r\n namespace?: string,\r\n options?: LoggerOptions\r\n): CallpadLogger {\r\n if (!namespace) {\r\n if (!rootLogger) {\r\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\r\n }\r\n return rootLogger;\r\n }\r\n\r\n return new CallpadLoggerImpl(`callpad:${namespace}`, options);\r\n}\r\n\r\nexport function setGlobalLoggerOptions(options: LoggerOptions): void {\r\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\r\n}\r\n","export interface DurationResult {\r\n seconds: number;\r\n minutes: number;\r\n hours: number;\r\n formatted: string;\r\n}\r\n\r\nexport const computeDuration = (\r\n startTime: string | Date | number,\r\n endTime?: string | Date | number\r\n): DurationResult => {\r\n const startTimestamp = parseTimeInput(startTime);\r\n if (startTimestamp === null) {\r\n throw new Error(\"Invalid start time provided\");\r\n }\r\n\r\n const endTimestamp = endTime ? parseTimeInput(endTime) : Date.now();\r\n if (endTimestamp === null) {\r\n throw new Error(\"Invalid end time provided\");\r\n }\r\n\r\n let durationMs = endTimestamp - startTimestamp;\r\n if (durationMs < 0) {\r\n durationMs = 0;\r\n // throw new Error(\"End time cannot be before start time\");\r\n }\r\n\r\n const totalSeconds = Math.round(durationMs / 1000);\r\n const totalMinutes = Math.round(totalSeconds / 60);\r\n const totalHours = Math.round(totalSeconds / 3600);\r\n\r\n const hours = Math.floor(totalSeconds / 3600);\r\n const minutes = Math.floor((totalSeconds % 3600) / 60);\r\n const seconds = totalSeconds % 60;\r\n\r\n const formatted =\r\n hours === 0\r\n ? `${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\r\n : `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\r\n\r\n return {\r\n seconds: totalSeconds,\r\n minutes: totalMinutes,\r\n hours: totalHours,\r\n formatted,\r\n };\r\n};\r\n\r\nconst parseTimeInput = (input: string | Date | number): number | null => {\r\n if (typeof input === \"number\") {\r\n return Number.isFinite(input) ? input : null;\r\n }\r\n\r\n if (input instanceof Date) {\r\n return Number.isFinite(input.getTime()) ? input.getTime() : null;\r\n }\r\n\r\n const timestamp = Date.parse(input);\r\n return Number.isFinite(timestamp) ? timestamp : null;\r\n};\r\n","import { type Participant, Track } from \"livekit-client\";\r\n\r\n/**\r\n * Check if a participant has video enabled and published\r\n */\r\nexport function hasVideoTrack(participant: Participant): boolean {\r\n const videoTrack = participant.getTrackPublication(Track.Source.Camera);\r\n return videoTrack !== undefined && !videoTrack.isMuted;\r\n}\r\n\r\n/**\r\n * Get video track from participant\r\n */\r\nexport function getVideoTrack(participant: Participant) {\r\n return participant.getTrackPublication(Track.Source.Camera);\r\n}\r\n\r\n/**\r\n * Check if participant has video capability (track exists, may be muted)\r\n */\r\nexport function hasVideoCapability(participant: Participant): boolean {\r\n return participant.getTrackPublication(Track.Source.Camera) !== undefined;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../src/utils/logger.ts","../../src/utils/duration.ts","../../src/utils/video.ts"],"names":["Track"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Comprehensive logging system for the Callpad Web SDK\n *\n * Features:\n * - Log level filtering (debug, info, warn, error)\n * - Environment variable configuration (DEBUG, CALLPAD_LOG_LEVEL)\n * - Hierarchical namespacing (callpad:socket:connection)\n * - Custom logger integration\n * - Zero-cost when disabled\n */\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport interface LoggerOptions {\n level?: LogLevel;\n enableDebug?: boolean;\n customLogger?: (level: LogLevel, message: string, meta?: any) => void;\n}\n\nexport interface CallpadLogger {\n debug(message: string, meta?: any): void;\n info(message: string, meta?: any): void;\n warn(message: string, meta?: any): void;\n error(message: string, meta?: any): void;\n child(namespace: string): CallpadLogger;\n setLevel(level: LogLevel): void;\n isLevelEnabled(level: LogLevel): boolean;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nclass CallpadLoggerImpl implements CallpadLogger {\n private namespace: string;\n private level: LogLevel;\n private enableDebug: boolean;\n private customLogger?: (level: LogLevel, message: string, meta?: any) => void;\n\n constructor(namespace = \"callpad\", options: LoggerOptions = {}) {\n this.namespace = namespace;\n this.level = options.level ?? this.getDefaultLevel();\n this.enableDebug = options.enableDebug ?? this.shouldEnableDebug();\n if (options.customLogger) {\n this.customLogger = options.customLogger;\n }\n }\n\n private getDefaultLevel(): LogLevel {\n const envLevel =\n typeof window !== \"undefined\"\n ? (window as any).__CALLPAD_LOG_LEVEL__\n : typeof globalThis !== \"undefined\" &&\n (globalThis as any).process?.env?.CALLPAD_LOG_LEVEL;\n\n if (envLevel && this.isValidLogLevel(envLevel)) {\n return envLevel as LogLevel;\n }\n\n const isProduction =\n typeof globalThis !== \"undefined\" &&\n (globalThis as any).process?.env?.NODE_ENV === \"production\";\n\n return isProduction ? \"warn\" : \"info\";\n }\n\n private shouldEnableDebug(): boolean {\n const debugEnv =\n typeof window !== \"undefined\"\n ? (window as any).__DEBUG__\n : typeof globalThis !== \"undefined\" &&\n (globalThis as any).process?.env?.DEBUG;\n\n if (!debugEnv) return false;\n\n const debugPatterns = debugEnv.split(/[\\s,]+/);\n return debugPatterns.some((pattern: string) => {\n if (pattern === \"*\") return true;\n if (pattern.endsWith(\"*\")) {\n const prefix = pattern.slice(0, -1);\n return this.namespace.startsWith(prefix);\n }\n return this.namespace === pattern;\n });\n }\n\n private isValidLogLevel(level: string): boolean {\n return Object.keys(LOG_LEVELS).includes(level);\n }\n\n private shouldLog(level: LogLevel): boolean {\n if (level === \"debug\" && !this.enableDebug) {\n return false;\n }\n return LOG_LEVELS[level] >= LOG_LEVELS[this.level];\n }\n\n private formatMessage(level: LogLevel, message: string, meta?: any): void {\n if (!this.shouldLog(level)) return;\n\n const timestamp = new Date().toISOString();\n const prefix = `[${timestamp}] [${this.namespace}] [${level.toUpperCase()}]`;\n\n if (this.customLogger) {\n this.customLogger(level, message, meta);\n return;\n }\n\n const logMethod =\n level === \"error\"\n ? console.error\n : level === \"warn\"\n ? console.warn\n : level === \"info\"\n ? console.info\n : console.log;\n\n if (meta !== undefined) {\n logMethod(`${prefix} ${message}`, meta);\n } else {\n logMethod(`${prefix} ${message}`);\n }\n }\n\n debug(message: string, meta?: any): void {\n this.formatMessage(\"debug\", message, meta);\n }\n\n info(message: string, meta?: any): void {\n this.formatMessage(\"info\", message, meta);\n }\n\n warn(message: string, meta?: any): void {\n this.formatMessage(\"warn\", message, meta);\n }\n\n error(message: string, meta?: any): void {\n this.formatMessage(\"error\", message, meta);\n }\n\n child(namespace: string): CallpadLogger {\n const childNamespace = `${this.namespace}:${namespace}`;\n const childOptions: LoggerOptions = {\n level: this.level,\n enableDebug: this.enableDebug,\n };\n if (this.customLogger) {\n childOptions.customLogger = this.customLogger;\n }\n return new CallpadLoggerImpl(childNamespace, childOptions);\n }\n\n setLevel(level: LogLevel): void {\n this.level = level;\n }\n\n isLevelEnabled(level: LogLevel): boolean {\n return this.shouldLog(level);\n }\n}\n\nlet rootLogger: CallpadLogger | null = null;\n\nexport function createLogger(\n namespace?: string,\n options?: LoggerOptions\n): CallpadLogger {\n if (!namespace) {\n if (!rootLogger) {\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\n }\n return rootLogger;\n }\n\n return new CallpadLoggerImpl(`callpad:${namespace}`, options);\n}\n\nexport function setGlobalLoggerOptions(options: LoggerOptions): void {\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\n}\n","export interface DurationResult {\n seconds: number;\n minutes: number;\n hours: number;\n formatted: string;\n}\n\nexport const computeDuration = (\n startTime: string | Date | number,\n endTime?: string | Date | number\n): DurationResult => {\n const startTimestamp = parseTimeInput(startTime);\n if (startTimestamp === null) {\n throw new Error(\"Invalid start time provided\");\n }\n\n const endTimestamp = endTime ? parseTimeInput(endTime) : Date.now();\n if (endTimestamp === null) {\n throw new Error(\"Invalid end time provided\");\n }\n\n let durationMs = endTimestamp - startTimestamp;\n if (durationMs < 0) {\n durationMs = 0;\n // throw new Error(\"End time cannot be before start time\");\n }\n\n const totalSeconds = Math.round(durationMs / 1000);\n const totalMinutes = Math.round(totalSeconds / 60);\n const totalHours = Math.round(totalSeconds / 3600);\n\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n const formatted =\n hours === 0\n ? `${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\n : `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n\n return {\n seconds: totalSeconds,\n minutes: totalMinutes,\n hours: totalHours,\n formatted,\n };\n};\n\nconst parseTimeInput = (input: string | Date | number): number | null => {\n if (typeof input === \"number\") {\n return Number.isFinite(input) ? input : null;\n }\n\n if (input instanceof Date) {\n return Number.isFinite(input.getTime()) ? input.getTime() : null;\n }\n\n const timestamp = Date.parse(input);\n return Number.isFinite(timestamp) ? timestamp : null;\n};\n","import { type Participant, Track } from \"livekit-client\";\n\n/**\n * Check if a participant has video enabled and published\n */\nexport function hasVideoTrack(participant: Participant): boolean {\n const videoTrack = participant.getTrackPublication(Track.Source.Camera);\n return videoTrack !== undefined && !videoTrack.isMuted;\n}\n\n/**\n * Get video track from participant\n */\nexport function getVideoTrack(participant: Participant) {\n return participant.getTrackPublication(Track.Source.Camera);\n}\n\n/**\n * Check if participant has video capability (track exists, may be muted)\n */\nexport function hasVideoCapability(participant: Participant): boolean {\n return participant.getTrackPublication(Track.Source.Camera) !== undefined;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/logger.ts","../../src/utils/duration.ts","../../src/utils/video.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Comprehensive logging system for the Callpad Web SDK\r\n *\r\n * Features:\r\n * - Log level filtering (debug, info, warn, error)\r\n * - Environment variable configuration (DEBUG, CALLPAD_LOG_LEVEL)\r\n * - Hierarchical namespacing (callpad:socket:connection)\r\n * - Custom logger integration\r\n * - Zero-cost when disabled\r\n */\r\n\r\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\r\n\r\nexport interface LoggerOptions {\r\n level?: LogLevel;\r\n enableDebug?: boolean;\r\n customLogger?: (level: LogLevel, message: string, meta?: any) => void;\r\n}\r\n\r\nexport interface CallpadLogger {\r\n debug(message: string, meta?: any): void;\r\n info(message: string, meta?: any): void;\r\n warn(message: string, meta?: any): void;\r\n error(message: string, meta?: any): void;\r\n child(namespace: string): CallpadLogger;\r\n setLevel(level: LogLevel): void;\r\n isLevelEnabled(level: LogLevel): boolean;\r\n}\r\n\r\nconst LOG_LEVELS: Record<LogLevel, number> = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n};\r\n\r\nclass CallpadLoggerImpl implements CallpadLogger {\r\n private namespace: string;\r\n private level: LogLevel;\r\n private enableDebug: boolean;\r\n private customLogger?: (level: LogLevel, message: string, meta?: any) => void;\r\n\r\n constructor(namespace = \"callpad\", options: LoggerOptions = {}) {\r\n this.namespace = namespace;\r\n this.level = options.level ?? this.getDefaultLevel();\r\n this.enableDebug = options.enableDebug ?? this.shouldEnableDebug();\r\n if (options.customLogger) {\r\n this.customLogger = options.customLogger;\r\n }\r\n }\r\n\r\n private getDefaultLevel(): LogLevel {\r\n const envLevel =\r\n typeof window !== \"undefined\"\r\n ? (window as any).__CALLPAD_LOG_LEVEL__\r\n : typeof globalThis !== \"undefined\" &&\r\n (globalThis as any).process?.env?.CALLPAD_LOG_LEVEL;\r\n\r\n if (envLevel && this.isValidLogLevel(envLevel)) {\r\n return envLevel as LogLevel;\r\n }\r\n\r\n const isProduction =\r\n typeof globalThis !== \"undefined\" &&\r\n (globalThis as any).process?.env?.NODE_ENV === \"production\";\r\n\r\n return isProduction ? \"warn\" : \"info\";\r\n }\r\n\r\n private shouldEnableDebug(): boolean {\r\n const debugEnv =\r\n typeof window !== \"undefined\"\r\n ? (window as any).__DEBUG__\r\n : typeof globalThis !== \"undefined\" &&\r\n (globalThis as any).process?.env?.DEBUG;\r\n\r\n if (!debugEnv) return false;\r\n\r\n const debugPatterns = debugEnv.split(/[\\s,]+/);\r\n return debugPatterns.some((pattern: string) => {\r\n if (pattern === \"*\") return true;\r\n if (pattern.endsWith(\"*\")) {\r\n const prefix = pattern.slice(0, -1);\r\n return this.namespace.startsWith(prefix);\r\n }\r\n return this.namespace === pattern;\r\n });\r\n }\r\n\r\n private isValidLogLevel(level: string): boolean {\r\n return Object.keys(LOG_LEVELS).includes(level);\r\n }\r\n\r\n private shouldLog(level: LogLevel): boolean {\r\n if (level === \"debug\" && !this.enableDebug) {\r\n return false;\r\n }\r\n return LOG_LEVELS[level] >= LOG_LEVELS[this.level];\r\n }\r\n\r\n private formatMessage(level: LogLevel, message: string, meta?: any): void {\r\n if (!this.shouldLog(level)) return;\r\n\r\n const timestamp = new Date().toISOString();\r\n const prefix = `[${timestamp}] [${this.namespace}] [${level.toUpperCase()}]`;\r\n\r\n if (this.customLogger) {\r\n this.customLogger(level, message, meta);\r\n return;\r\n }\r\n\r\n const logMethod =\r\n level === \"error\"\r\n ? console.error\r\n : level === \"warn\"\r\n ? console.warn\r\n : level === \"info\"\r\n ? console.info\r\n : console.log;\r\n\r\n if (meta !== undefined) {\r\n logMethod(`${prefix} ${message}`, meta);\r\n } else {\r\n logMethod(`${prefix} ${message}`);\r\n }\r\n }\r\n\r\n debug(message: string, meta?: any): void {\r\n this.formatMessage(\"debug\", message, meta);\r\n }\r\n\r\n info(message: string, meta?: any): void {\r\n this.formatMessage(\"info\", message, meta);\r\n }\r\n\r\n warn(message: string, meta?: any): void {\r\n this.formatMessage(\"warn\", message, meta);\r\n }\r\n\r\n error(message: string, meta?: any): void {\r\n this.formatMessage(\"error\", message, meta);\r\n }\r\n\r\n child(namespace: string): CallpadLogger {\r\n const childNamespace = `${this.namespace}:${namespace}`;\r\n const childOptions: LoggerOptions = {\r\n level: this.level,\r\n enableDebug: this.enableDebug,\r\n };\r\n if (this.customLogger) {\r\n childOptions.customLogger = this.customLogger;\r\n }\r\n return new CallpadLoggerImpl(childNamespace, childOptions);\r\n }\r\n\r\n setLevel(level: LogLevel): void {\r\n this.level = level;\r\n }\r\n\r\n isLevelEnabled(level: LogLevel): boolean {\r\n return this.shouldLog(level);\r\n }\r\n}\r\n\r\nlet rootLogger: CallpadLogger | null = null;\r\n\r\nexport function createLogger(\r\n namespace?: string,\r\n options?: LoggerOptions\r\n): CallpadLogger {\r\n if (!namespace) {\r\n if (!rootLogger) {\r\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\r\n }\r\n return rootLogger;\r\n }\r\n\r\n return new CallpadLoggerImpl(`callpad:${namespace}`, options);\r\n}\r\n\r\nexport function setGlobalLoggerOptions(options: LoggerOptions): void {\r\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\r\n}\r\n","export interface DurationResult {\r\n seconds: number;\r\n minutes: number;\r\n hours: number;\r\n formatted: string;\r\n}\r\n\r\nexport const computeDuration = (\r\n startTime: string | Date | number,\r\n endTime?: string | Date | number\r\n): DurationResult => {\r\n const startTimestamp = parseTimeInput(startTime);\r\n if (startTimestamp === null) {\r\n throw new Error(\"Invalid start time provided\");\r\n }\r\n\r\n const endTimestamp = endTime ? parseTimeInput(endTime) : Date.now();\r\n if (endTimestamp === null) {\r\n throw new Error(\"Invalid end time provided\");\r\n }\r\n\r\n let durationMs = endTimestamp - startTimestamp;\r\n if (durationMs < 0) {\r\n durationMs = 0;\r\n // throw new Error(\"End time cannot be before start time\");\r\n }\r\n\r\n const totalSeconds = Math.round(durationMs / 1000);\r\n const totalMinutes = Math.round(totalSeconds / 60);\r\n const totalHours = Math.round(totalSeconds / 3600);\r\n\r\n const hours = Math.floor(totalSeconds / 3600);\r\n const minutes = Math.floor((totalSeconds % 3600) / 60);\r\n const seconds = totalSeconds % 60;\r\n\r\n const formatted =\r\n hours === 0\r\n ? `${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\r\n : `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\r\n\r\n return {\r\n seconds: totalSeconds,\r\n minutes: totalMinutes,\r\n hours: totalHours,\r\n formatted,\r\n };\r\n};\r\n\r\nconst parseTimeInput = (input: string | Date | number): number | null => {\r\n if (typeof input === \"number\") {\r\n return Number.isFinite(input) ? input : null;\r\n }\r\n\r\n if (input instanceof Date) {\r\n return Number.isFinite(input.getTime()) ? input.getTime() : null;\r\n }\r\n\r\n const timestamp = Date.parse(input);\r\n return Number.isFinite(timestamp) ? timestamp : null;\r\n};\r\n","import { type Participant, Track } from \"livekit-client\";\r\n\r\n/**\r\n * Check if a participant has video enabled and published\r\n */\r\nexport function hasVideoTrack(participant: Participant): boolean {\r\n const videoTrack = participant.getTrackPublication(Track.Source.Camera);\r\n return videoTrack !== undefined && !videoTrack.isMuted;\r\n}\r\n\r\n/**\r\n * Get video track from participant\r\n */\r\nexport function getVideoTrack(participant: Participant) {\r\n return participant.getTrackPublication(Track.Source.Camera);\r\n}\r\n\r\n/**\r\n * Check if participant has video capability (track exists, may be muted)\r\n */\r\nexport function hasVideoCapability(participant: Participant): boolean {\r\n return participant.getTrackPublication(Track.Source.Camera) !== undefined;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../src/utils/logger.ts","../../src/utils/duration.ts","../../src/utils/video.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Comprehensive logging system for the Callpad Web SDK\n *\n * Features:\n * - Log level filtering (debug, info, warn, error)\n * - Environment variable configuration (DEBUG, CALLPAD_LOG_LEVEL)\n * - Hierarchical namespacing (callpad:socket:connection)\n * - Custom logger integration\n * - Zero-cost when disabled\n */\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport interface LoggerOptions {\n level?: LogLevel;\n enableDebug?: boolean;\n customLogger?: (level: LogLevel, message: string, meta?: any) => void;\n}\n\nexport interface CallpadLogger {\n debug(message: string, meta?: any): void;\n info(message: string, meta?: any): void;\n warn(message: string, meta?: any): void;\n error(message: string, meta?: any): void;\n child(namespace: string): CallpadLogger;\n setLevel(level: LogLevel): void;\n isLevelEnabled(level: LogLevel): boolean;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nclass CallpadLoggerImpl implements CallpadLogger {\n private namespace: string;\n private level: LogLevel;\n private enableDebug: boolean;\n private customLogger?: (level: LogLevel, message: string, meta?: any) => void;\n\n constructor(namespace = \"callpad\", options: LoggerOptions = {}) {\n this.namespace = namespace;\n this.level = options.level ?? this.getDefaultLevel();\n this.enableDebug = options.enableDebug ?? this.shouldEnableDebug();\n if (options.customLogger) {\n this.customLogger = options.customLogger;\n }\n }\n\n private getDefaultLevel(): LogLevel {\n const envLevel =\n typeof window !== \"undefined\"\n ? (window as any).__CALLPAD_LOG_LEVEL__\n : typeof globalThis !== \"undefined\" &&\n (globalThis as any).process?.env?.CALLPAD_LOG_LEVEL;\n\n if (envLevel && this.isValidLogLevel(envLevel)) {\n return envLevel as LogLevel;\n }\n\n const isProduction =\n typeof globalThis !== \"undefined\" &&\n (globalThis as any).process?.env?.NODE_ENV === \"production\";\n\n return isProduction ? \"warn\" : \"info\";\n }\n\n private shouldEnableDebug(): boolean {\n const debugEnv =\n typeof window !== \"undefined\"\n ? (window as any).__DEBUG__\n : typeof globalThis !== \"undefined\" &&\n (globalThis as any).process?.env?.DEBUG;\n\n if (!debugEnv) return false;\n\n const debugPatterns = debugEnv.split(/[\\s,]+/);\n return debugPatterns.some((pattern: string) => {\n if (pattern === \"*\") return true;\n if (pattern.endsWith(\"*\")) {\n const prefix = pattern.slice(0, -1);\n return this.namespace.startsWith(prefix);\n }\n return this.namespace === pattern;\n });\n }\n\n private isValidLogLevel(level: string): boolean {\n return Object.keys(LOG_LEVELS).includes(level);\n }\n\n private shouldLog(level: LogLevel): boolean {\n if (level === \"debug\" && !this.enableDebug) {\n return false;\n }\n return LOG_LEVELS[level] >= LOG_LEVELS[this.level];\n }\n\n private formatMessage(level: LogLevel, message: string, meta?: any): void {\n if (!this.shouldLog(level)) return;\n\n const timestamp = new Date().toISOString();\n const prefix = `[${timestamp}] [${this.namespace}] [${level.toUpperCase()}]`;\n\n if (this.customLogger) {\n this.customLogger(level, message, meta);\n return;\n }\n\n const logMethod =\n level === \"error\"\n ? console.error\n : level === \"warn\"\n ? console.warn\n : level === \"info\"\n ? console.info\n : console.log;\n\n if (meta !== undefined) {\n logMethod(`${prefix} ${message}`, meta);\n } else {\n logMethod(`${prefix} ${message}`);\n }\n }\n\n debug(message: string, meta?: any): void {\n this.formatMessage(\"debug\", message, meta);\n }\n\n info(message: string, meta?: any): void {\n this.formatMessage(\"info\", message, meta);\n }\n\n warn(message: string, meta?: any): void {\n this.formatMessage(\"warn\", message, meta);\n }\n\n error(message: string, meta?: any): void {\n this.formatMessage(\"error\", message, meta);\n }\n\n child(namespace: string): CallpadLogger {\n const childNamespace = `${this.namespace}:${namespace}`;\n const childOptions: LoggerOptions = {\n level: this.level,\n enableDebug: this.enableDebug,\n };\n if (this.customLogger) {\n childOptions.customLogger = this.customLogger;\n }\n return new CallpadLoggerImpl(childNamespace, childOptions);\n }\n\n setLevel(level: LogLevel): void {\n this.level = level;\n }\n\n isLevelEnabled(level: LogLevel): boolean {\n return this.shouldLog(level);\n }\n}\n\nlet rootLogger: CallpadLogger | null = null;\n\nexport function createLogger(\n namespace?: string,\n options?: LoggerOptions\n): CallpadLogger {\n if (!namespace) {\n if (!rootLogger) {\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\n }\n return rootLogger;\n }\n\n return new CallpadLoggerImpl(`callpad:${namespace}`, options);\n}\n\nexport function setGlobalLoggerOptions(options: LoggerOptions): void {\n rootLogger = new CallpadLoggerImpl(\"callpad\", options);\n}\n","export interface DurationResult {\n seconds: number;\n minutes: number;\n hours: number;\n formatted: string;\n}\n\nexport const computeDuration = (\n startTime: string | Date | number,\n endTime?: string | Date | number\n): DurationResult => {\n const startTimestamp = parseTimeInput(startTime);\n if (startTimestamp === null) {\n throw new Error(\"Invalid start time provided\");\n }\n\n const endTimestamp = endTime ? parseTimeInput(endTime) : Date.now();\n if (endTimestamp === null) {\n throw new Error(\"Invalid end time provided\");\n }\n\n let durationMs = endTimestamp - startTimestamp;\n if (durationMs < 0) {\n durationMs = 0;\n // throw new Error(\"End time cannot be before start time\");\n }\n\n const totalSeconds = Math.round(durationMs / 1000);\n const totalMinutes = Math.round(totalSeconds / 60);\n const totalHours = Math.round(totalSeconds / 3600);\n\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n const formatted =\n hours === 0\n ? `${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\n : `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n\n return {\n seconds: totalSeconds,\n minutes: totalMinutes,\n hours: totalHours,\n formatted,\n };\n};\n\nconst parseTimeInput = (input: string | Date | number): number | null => {\n if (typeof input === \"number\") {\n return Number.isFinite(input) ? input : null;\n }\n\n if (input instanceof Date) {\n return Number.isFinite(input.getTime()) ? input.getTime() : null;\n }\n\n const timestamp = Date.parse(input);\n return Number.isFinite(timestamp) ? timestamp : null;\n};\n","import { type Participant, Track } from \"livekit-client\";\n\n/**\n * Check if a participant has video enabled and published\n */\nexport function hasVideoTrack(participant: Participant): boolean {\n const videoTrack = participant.getTrackPublication(Track.Source.Camera);\n return videoTrack !== undefined && !videoTrack.isMuted;\n}\n\n/**\n * Get video track from participant\n */\nexport function getVideoTrack(participant: Participant) {\n return participant.getTrackPublication(Track.Source.Camera);\n}\n\n/**\n * Check if participant has video capability (track exists, may be muted)\n */\nexport function hasVideoCapability(participant: Participant): boolean {\n return participant.getTrackPublication(Track.Source.Camera) !== undefined;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vg-x07df",
3
- "version": "1.9.4",
3
+ "version": "1.10.5",
4
4
  "description": "Headless SDK for callpad audio/video",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",