From d195bf1f55e50a1d1b27a08103256b6d7c5e84d6 Mon Sep 17 00:00:00 2001 From: Klevert Opee <81738300+klevert-ope@users.noreply.github.com> Date: Thu, 28 Dec 2023 04:15:42 +0300 Subject: [PATCH] fix: install error --- README.md | 18 +++++++++--------- node_modules/.package-lock.json | 6 +++--- package-lock.json | 18 ++++++++++-------- package.json | 12 +++++++----- src/useHlsVideoPlayer.ts | 11 +++++++++++ usehlsplayer.js | 11 +++++++++++ usehlsplayer.js.map | 2 +- usehlsplayer.mjs | 11 +++++++++++ usehlsplayer.mjs.map | 2 +- 9 files changed, 64 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 057d53d..c1f495d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,18 @@ # Usehlsvideoplayer -[![Static Badge](https://img.shields.io/badge/npm-latest_v1.2.5-blue?logo=npm)](https://www.npmjs.com/package/usehlsvideoplayer) +[![Static Badge](https://img.shields.io/badge/npm-latest_v1.2.6-blue?logo=npm)](https://www.npmjs.com/package/usehlsvideoplayer) ![Static Badge](https://img.shields.io/badge/license-ISC-red) `usehlsvideoplayer` is a React hook designed to simplify the integration of [Hls.js](https://github.com/video-dev/hls.js) for video playback in your React applications. This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source. With `usehlsvideoplayer`, you can effortlessly incorporate Hls.js functionality into your components. ## Installation +## Dependencies + +This package has a dependency on react, [Hls.js](https://github.com/video-dev/hls.js) and typescript, +so make sure to include it in your project. + +```bash +npm install hls.js +``` Install the package using npm: @@ -124,14 +132,6 @@ The hook returns an object with the following property: The hook takes care of cleaning up resources when the component unmounts. It automatically detaches the Hls.js instance and removes event listeners. -## Dependencies - -This package has a dependency on [Hls.js](https://github.com/video-dev/hls.js), so make sure to include it in your project. - -```bash -npm install hls.js -``` - ## License This project is licensed under the `ISC` License. diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 934ea01..f1dccaa 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -1,6 +1,6 @@ { "name": "usehlsvideoplayer", - "version": "1.2.5", + "version": "1.2.6", "lockfileVersion": 3, "requires": true, "packages": { @@ -282,7 +282,8 @@ "node_modules/hls.js": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.14.tgz", - "integrity": "sha512-UppQjyvPVclg+6t2KY/Rv03h0+bA5u6zwqVoz4LAC/L0fgYmIaCD7ZCrwe8WI1Gv01be1XL0QFsRbSdIHV/Wbw==" + "integrity": "sha512-UppQjyvPVclg+6t2KY/Rv03h0+bA5u6zwqVoz4LAC/L0fgYmIaCD7ZCrwe8WI1Gv01be1XL0QFsRbSdIHV/Wbw==", + "optional": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -437,7 +438,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package-lock.json b/package-lock.json index dd16515..f335828 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,26 @@ { "name": "usehlsvideoplayer", - "version": "1.2.5", + "version": "1.2.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "usehlsvideoplayer", - "version": "1.2.5", + "version": "1.2.6", "license": "ISC", "dependencies": { - "hls.js": "^1.4.14", - "react": "^18.2.0" + "react": "^18.2.0", + "typescript": "^5.3.3" }, "devDependencies": { "@types/react": "^18.2.45", "esbuild": "^0.19.10", "rollup": "^4.9.1", "rollup-plugin-dts": "^6.1.0", - "rollup-plugin-esbuild": "^6.1.0", - "typescript": "^5.3.3" + "rollup-plugin-esbuild": "^6.1.0" + }, + "optionalDependencies": { + "hls.js": "^1.4.14" } }, "node_modules/@babel/code-frame": { @@ -821,7 +823,8 @@ "node_modules/hls.js": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.4.14.tgz", - "integrity": "sha512-UppQjyvPVclg+6t2KY/Rv03h0+bA5u6zwqVoz4LAC/L0fgYmIaCD7ZCrwe8WI1Gv01be1XL0QFsRbSdIHV/Wbw==" + "integrity": "sha512-UppQjyvPVclg+6t2KY/Rv03h0+bA5u6zwqVoz4LAC/L0fgYmIaCD7ZCrwe8WI1Gv01be1XL0QFsRbSdIHV/Wbw==", + "optional": true }, "node_modules/js-tokens": { "version": "4.0.0", @@ -976,7 +979,6 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index fd93e11..3dd1066 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "usehlsvideoplayer", - "version": "1.2.5", + "version": "1.2.6", "description": "A react hook for playing hls files", "main": "usehlsplayer.js", "module": "usehlsplayer.mjs", @@ -25,16 +25,18 @@ "url": "https://github.com/klevert-ope/Usehlsvideoplayer/issues" }, "homepage": "https://github.com/klevert-ope/Usehlsvideoplayer#readme", + "optionalDependencies": { + "hls.js": "^1.4.14" + }, "dependencies": { - "hls.js": "^1.4.14", - "react": "^18.2.0" + "react": "^18.2.0", + "typescript": "^5.3.3" }, "devDependencies": { "@types/react": "^18.2.45", "esbuild": "^0.19.10", "rollup": "^4.9.1", "rollup-plugin-dts": "^6.1.0", - "rollup-plugin-esbuild": "^6.1.0", - "typescript": "^5.3.3" + "rollup-plugin-esbuild": "^6.1.0" } } diff --git a/src/useHlsVideoPlayer.ts b/src/useHlsVideoPlayer.ts index 4d86544..13672a0 100644 --- a/src/useHlsVideoPlayer.ts +++ b/src/useHlsVideoPlayer.ts @@ -1,3 +1,14 @@ +/** + * @file + * usehlsvideoplayer is a React hook + * designed to simplify the integration of Hls.js for video playback in your React applications. + * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source. + * With usehlsvideoplayer, you can effortlessly incorporate Hls.js functionality into your components. + * The hook takes care of cleaning up resources when the component unmounts. + * It automatically detaches the Hls.js instance and removes event listeners. + * @copyright (c) 2023 Klevert Opee + * @license ISC + */ import Hls from "hls.js"; import React, { DependencyList, EffectCallback, useEffect, useLayoutEffect, useRef } from "react"; diff --git a/usehlsplayer.js b/usehlsplayer.js index fc9196a..63552e2 100644 --- a/usehlsplayer.js +++ b/usehlsplayer.js @@ -3,6 +3,17 @@ var Hls = require('hls.js'); var react = require('react'); +/** + * @file + * usehlsvideoplayer is a React hook + * designed to simplify the integration of Hls.js for video playback in your React applications. + * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source. + * With usehlsvideoplayer, you can effortlessly incorporate Hls.js functionality into your components. + * The hook takes care of cleaning up resources when the component unmounts. + * It automatically detaches the Hls.js instance and removes event listeners. + * @copyright (c) 2023 Klevert Opee + * @license ISC + */ let useIsomorphicLayoutEffect; if (typeof window !== "undefined") { useIsomorphicLayoutEffect = react.useLayoutEffect; diff --git a/usehlsplayer.js.map b/usehlsplayer.js.map index 47c2511..995c52a 100644 --- a/usehlsplayer.js.map +++ b/usehlsplayer.js.map @@ -1 +1 @@ -{"version":3,"file":"usehlsplayer.js","sources":["src/useHlsVideoPlayer.ts"],"sourcesContent":["import Hls from \"hls.js\";\r\nimport React, { DependencyList, EffectCallback, useEffect, useLayoutEffect, useRef } from \"react\";\r\n\r\ntype Options = {\r\n\t/**\r\n\t * Determines whether the loading of the stream should start automatically\r\n\t * when the Hls.js instance is created.\r\n\t */\r\n\tautoStartLoad?: boolean;\r\n\t/**\r\n\t * Specifies the initial quality level index to start playback with.\r\n\t * Use -1 for automatic level selection.\r\n\t */\r\n\tstartLevel?: number;\r\n\t/**\r\n\t * Sets the maximum buffer length (in seconds) to keep for instant playback.\r\n\t * Adjust for optimizing buffering behavior.\r\n\t */\r\n\tmaxBufferLength?: number;\r\n\t/**\r\n\t * Defines the maximum buffer size (in bytes) for the media\r\n\t * element.\r\n\t * Useful for controlling memory usage.\r\n\t */\r\n\tmaxBufferSize?: number;\r\n\t/**\r\n\t * Specifies the maximum buffer length (in seconds) for live content.\r\n\t * Adjust for optimizing live stream buffering.\r\n\t */\r\n\tmaxMaxBufferLength?: number;\r\n\t/**\r\n\t * Sets the number of target durations to keep in live synchronization\r\n\t * of the manifest.\r\n\t * Affects live stream synchronization.\r\n\t */\r\n\tliveSyncDurationCount?: number;\r\n\t/**\r\n\t * Configures the number of target durations to keep in live\r\n\t * synchronization for low-latency applications.\r\n\t */\r\n\tliveMaxLatencyDurationCount?: number;\r\n\t/**\r\n\t * Enables or disables the use of Web Workers for fetching and parsing\r\n\t * segments.\r\n\t * It Can improve performance.\r\n\t */\r\n\tenableWorker?: boolean;\r\n\t/**\r\n\t * Enables or disables software-based AES decryption.\r\n\t * Adjust based on hardware support for decryption.\r\n\t */\r\n\tenableSoftwareAES?: boolean;\r\n\t/**\r\n\t * Determines whether to force the generation of keyframes on\r\n\t * discontinuity for better seeking in live streams.\r\n\t */\r\n\tforceKeyFrameOnDiscontinuity?: boolean;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for level loading. Useful for handling delays in loading levels.\r\n\t */\r\n\tlevelLoadingTimeOut?: number;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for manifest loading.\r\n\t * Useful for handling delays in loading the manifest.\r\n\t */\r\n\tmanifestLoadingTimeOut?: number;\r\n\t/**\r\n\t * Allows customization of XHR setup function for handling XMLHttpRequest.\r\n\t * Useful for advanced use cases.\r\n\t */\r\n\txhrSetup?: () => void;\r\n\t/**\r\n\t * Limits the selected quality level to the size of the player.\r\n\t * Useful for optimizing quality based on player dimensions.\r\n\t */\r\n\tcapLevelToPlayerSize?: boolean;\r\n\t/**\r\n\t * Initiate fragment is prefetching to improve start-up time by loading\r\n\t * fragments in advance\r\n\t */\r\n\tstartFragPrefetch?: boolean;\r\n\t/**\r\n\t * Specifies the maximum number of retries for appending a segment on\r\n\t * error. Useful for handling segment append errors.\r\n\t */\r\n\tappendErrorMaxRetry?: number;\r\n};\r\n\r\ntype HlsPlayerResult = {\r\n\tvideoRef: React.RefObject;\r\n};\r\n\r\nlet useIsomorphicLayoutEffect: (effect: EffectCallback, deps?: DependencyList) => void;\r\nif (typeof window !== 'undefined') {\r\n\tuseIsomorphicLayoutEffect = useLayoutEffect;\r\n} else {\r\n\tuseIsomorphicLayoutEffect = useEffect;\r\n}\r\n\r\n/**\r\n * usehlsvideoplayer\r\n * is a React hook designed to simplify the integration of Hls.js for video playback in your React applications.\r\n * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source.\r\n * With `usehlsvideoplayer`, you can effortlessly incorporate Hls.js functionality into your components.\r\n *\r\n * The hook takes care of cleaning up resources when the component unmounts.\r\n * It automatically detaches the Hls.js instance and removes event listeners.\r\n *\r\n * @example\r\n * // Basic Usage\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource);\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @example\r\n * // Advanced Usage with Options\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource, {\r\n * startLevel: 2,\r\n * maxBufferLength: 60,\r\n * enableSoftwareAES: false,\r\n * // Add more options as needed. Below are the list of options and their defaults.\r\n * });\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @module usehlsvideoplayer\r\n * @function\r\n * @param {string} videoSource - The URL of the HLS video source to be loaded.\r\n * @param {Options} [options={}] - Optional configuration options for Hls.js.\r\n * @property {Object} videoRef - A React ref object for the video element.\r\n * @returns {Object} An object containing the video reference (`videoRef`).\r\n */\r\nexport function Usehlsplayer(videoSource: string, options: Options = {}): HlsPlayerResult {\r\n\tconst videoRef = useRef(null);\r\n\tconst hlsRef = useRef(null);\r\n\r\n\tconst isHlsSupported = () => Hls?.isSupported();\r\n\tconst createVideoElement = () => document.createElement('video');\r\n\tconst isWebWorkerSupported = () => typeof Worker !== 'undefined';\r\n\tconst checkAESSupport = async (): Promise => {\r\n\t\tif (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) {\r\n\t\t\ttry {\r\n\t\t\t\tawait window.crypto.subtle.importKey(\r\n\t\t\t\t\t'raw',\r\n\t\t\t\t\tnew ArrayBuffer(16),\r\n\t\t\t\t\t{ name: 'AES-CBC' },\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\t['encrypt', 'decrypt']\r\n\t\t\t\t);\r\n\t\t\t\treturn true;\r\n\t\t\t} catch (error) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n\r\n\tconst initializeHlsInstance = async (videoElement: HTMLVideoElement): Promise => {\r\n\t\tconst isWorkerSupported = isWebWorkerSupported();\r\n\t\tconst isAESSupported = await checkAESSupport();\r\n\r\n\t\tconst hlsOptions = {\r\n\t\t\tenableWorker: isWorkerSupported && options.enableWorker,\r\n\t\t\tenableSoftwareAES: isAESSupported && options.enableSoftwareAES,\r\n\t\t\t...options\r\n\t\t};\r\n\r\n\t\thlsRef.current = new Hls(hlsOptions);\r\n\r\n\t\ttry {\r\n\t\t\thlsRef.current.loadSource(videoSource);\r\n\t\t\thlsRef.current.attachMedia(videoElement);\r\n\t\t\thlsRef.current.on(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new Error(`Error initializing Hls.js: ${error.message}`);\r\n\t\t}\r\n\t};\r\n\r\n\tconst handleManifestParsed = (targetDuration: undefined): void => {\r\n\t\tif (hlsRef.current?.media && !isAnyBufferUpdating()) {\r\n\t\t\thlsRef.current.media.currentTime = targetDuration;\r\n\t\t}\r\n\t};\r\n\r\n\tconst isAnyBufferUpdating = (): boolean => {\r\n\t\tif (hlsRef.current) {\r\n\t\t\tconst media = hlsRef.current.media;\r\n\r\n\t\t\tif (media) {\r\n\t\t\t\tconst sourceBuffers = (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).mozSourceBuffers || (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).sourceBuffers;\r\n\r\n\t\t\t\tif (sourceBuffers) {\r\n\t\t\t\t\treturn Array.from(sourceBuffers).some((sb: SourceBuffer) => sb.updating);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t};\r\n\r\n\tuseIsomorphicLayoutEffect(() => {\r\n\t\tconst initializeHls = async ():Promise => {\r\n\t\t\tif (!isHlsSupported() || !videoSource) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst video = videoRef.current || createVideoElement();\r\n\r\n\t\t\tif (!hlsRef.current) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait initializeHlsInstance(video);\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tthrow new Error(`Error during Hls initialization: ${error.message}`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst loadHls = async (): Promise => {\r\n\t\t\ttry {\r\n\t\t\t\tawait initializeHls();\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new Error(`Error during video loading: ${error.message}`);\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst cleanupHls = (): void => {\r\n\t\t\tif (hlsRef.current) {\r\n\t\t\t\thlsRef.current.off(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t\t\thlsRef.current.destroy();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst initializeAndLoadHls = async (): Promise => {\r\n\t\t\tawait loadHls();\r\n\t\t};\r\n\r\n\t\tinitializeAndLoadHls().catch(error => {\r\n\t\t\tthrow new Error(`Error during initialization and loading Hls: ${error.message}`);\r\n\t\t});\r\n\r\n\t\treturn cleanupHls;\r\n\t}, [videoSource, options]);\r\n\treturn { videoRef };\r\n}\r\n"],"names":["useLayoutEffect","useEffect","useRef"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"usehlsplayer.js","sources":["src/useHlsVideoPlayer.ts"],"sourcesContent":["/**\r\n * @file\r\n * usehlsvideoplayer is a React hook\r\n * designed to simplify the integration of Hls.js for video playback in your React applications.\r\n * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source.\r\n * With usehlsvideoplayer, you can effortlessly incorporate Hls.js functionality into your components.\r\n * The hook takes care of cleaning up resources when the component unmounts.\r\n * It automatically detaches the Hls.js instance and removes event listeners.\r\n * @copyright (c) 2023 Klevert Opee\r\n * @license ISC\r\n */\r\nimport Hls from \"hls.js\";\r\nimport React, { DependencyList, EffectCallback, useEffect, useLayoutEffect, useRef } from \"react\";\r\n\r\ntype Options = {\r\n\t/**\r\n\t * Determines whether the loading of the stream should start automatically\r\n\t * when the Hls.js instance is created.\r\n\t */\r\n\tautoStartLoad?: boolean;\r\n\t/**\r\n\t * Specifies the initial quality level index to start playback with.\r\n\t * Use -1 for automatic level selection.\r\n\t */\r\n\tstartLevel?: number;\r\n\t/**\r\n\t * Sets the maximum buffer length (in seconds) to keep for instant playback.\r\n\t * Adjust for optimizing buffering behavior.\r\n\t */\r\n\tmaxBufferLength?: number;\r\n\t/**\r\n\t * Defines the maximum buffer size (in bytes) for the media\r\n\t * element.\r\n\t * Useful for controlling memory usage.\r\n\t */\r\n\tmaxBufferSize?: number;\r\n\t/**\r\n\t * Specifies the maximum buffer length (in seconds) for live content.\r\n\t * Adjust for optimizing live stream buffering.\r\n\t */\r\n\tmaxMaxBufferLength?: number;\r\n\t/**\r\n\t * Sets the number of target durations to keep in live synchronization\r\n\t * of the manifest.\r\n\t * Affects live stream synchronization.\r\n\t */\r\n\tliveSyncDurationCount?: number;\r\n\t/**\r\n\t * Configures the number of target durations to keep in live\r\n\t * synchronization for low-latency applications.\r\n\t */\r\n\tliveMaxLatencyDurationCount?: number;\r\n\t/**\r\n\t * Enables or disables the use of Web Workers for fetching and parsing\r\n\t * segments.\r\n\t * It Can improve performance.\r\n\t */\r\n\tenableWorker?: boolean;\r\n\t/**\r\n\t * Enables or disables software-based AES decryption.\r\n\t * Adjust based on hardware support for decryption.\r\n\t */\r\n\tenableSoftwareAES?: boolean;\r\n\t/**\r\n\t * Determines whether to force the generation of keyframes on\r\n\t * discontinuity for better seeking in live streams.\r\n\t */\r\n\tforceKeyFrameOnDiscontinuity?: boolean;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for level loading. Useful for handling delays in loading levels.\r\n\t */\r\n\tlevelLoadingTimeOut?: number;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for manifest loading.\r\n\t * Useful for handling delays in loading the manifest.\r\n\t */\r\n\tmanifestLoadingTimeOut?: number;\r\n\t/**\r\n\t * Allows customization of XHR setup function for handling XMLHttpRequest.\r\n\t * Useful for advanced use cases.\r\n\t */\r\n\txhrSetup?: () => void;\r\n\t/**\r\n\t * Limits the selected quality level to the size of the player.\r\n\t * Useful for optimizing quality based on player dimensions.\r\n\t */\r\n\tcapLevelToPlayerSize?: boolean;\r\n\t/**\r\n\t * Initiate fragment is prefetching to improve start-up time by loading\r\n\t * fragments in advance\r\n\t */\r\n\tstartFragPrefetch?: boolean;\r\n\t/**\r\n\t * Specifies the maximum number of retries for appending a segment on\r\n\t * error. Useful for handling segment append errors.\r\n\t */\r\n\tappendErrorMaxRetry?: number;\r\n};\r\n\r\ntype HlsPlayerResult = {\r\n\tvideoRef: React.RefObject;\r\n};\r\n\r\nlet useIsomorphicLayoutEffect: (effect: EffectCallback, deps?: DependencyList) => void;\r\nif (typeof window !== 'undefined') {\r\n\tuseIsomorphicLayoutEffect = useLayoutEffect;\r\n} else {\r\n\tuseIsomorphicLayoutEffect = useEffect;\r\n}\r\n\r\n/**\r\n * usehlsvideoplayer\r\n * is a React hook designed to simplify the integration of Hls.js for video playback in your React applications.\r\n * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source.\r\n * With `usehlsvideoplayer`, you can effortlessly incorporate Hls.js functionality into your components.\r\n *\r\n * The hook takes care of cleaning up resources when the component unmounts.\r\n * It automatically detaches the Hls.js instance and removes event listeners.\r\n *\r\n * @example\r\n * // Basic Usage\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource);\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @example\r\n * // Advanced Usage with Options\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource, {\r\n * startLevel: 2,\r\n * maxBufferLength: 60,\r\n * enableSoftwareAES: false,\r\n * // Add more options as needed. Below are the list of options and their defaults.\r\n * });\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @module usehlsvideoplayer\r\n * @function\r\n * @param {string} videoSource - The URL of the HLS video source to be loaded.\r\n * @param {Options} [options={}] - Optional configuration options for Hls.js.\r\n * @property {Object} videoRef - A React ref object for the video element.\r\n * @returns {Object} An object containing the video reference (`videoRef`).\r\n */\r\nexport function Usehlsplayer(videoSource: string, options: Options = {}): HlsPlayerResult {\r\n\tconst videoRef = useRef(null);\r\n\tconst hlsRef = useRef(null);\r\n\r\n\tconst isHlsSupported = () => Hls?.isSupported();\r\n\tconst createVideoElement = () => document.createElement('video');\r\n\tconst isWebWorkerSupported = () => typeof Worker !== 'undefined';\r\n\tconst checkAESSupport = async (): Promise => {\r\n\t\tif (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) {\r\n\t\t\ttry {\r\n\t\t\t\tawait window.crypto.subtle.importKey(\r\n\t\t\t\t\t'raw',\r\n\t\t\t\t\tnew ArrayBuffer(16),\r\n\t\t\t\t\t{ name: 'AES-CBC' },\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\t['encrypt', 'decrypt']\r\n\t\t\t\t);\r\n\t\t\t\treturn true;\r\n\t\t\t} catch (error) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n\r\n\tconst initializeHlsInstance = async (videoElement: HTMLVideoElement): Promise => {\r\n\t\tconst isWorkerSupported = isWebWorkerSupported();\r\n\t\tconst isAESSupported = await checkAESSupport();\r\n\r\n\t\tconst hlsOptions = {\r\n\t\t\tenableWorker: isWorkerSupported && options.enableWorker,\r\n\t\t\tenableSoftwareAES: isAESSupported && options.enableSoftwareAES,\r\n\t\t\t...options\r\n\t\t};\r\n\r\n\t\thlsRef.current = new Hls(hlsOptions);\r\n\r\n\t\ttry {\r\n\t\t\thlsRef.current.loadSource(videoSource);\r\n\t\t\thlsRef.current.attachMedia(videoElement);\r\n\t\t\thlsRef.current.on(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new Error(`Error initializing Hls.js: ${error.message}`);\r\n\t\t}\r\n\t};\r\n\r\n\tconst handleManifestParsed = (targetDuration: undefined): void => {\r\n\t\tif (hlsRef.current?.media && !isAnyBufferUpdating()) {\r\n\t\t\thlsRef.current.media.currentTime = targetDuration;\r\n\t\t}\r\n\t};\r\n\r\n\tconst isAnyBufferUpdating = (): boolean => {\r\n\t\tif (hlsRef.current) {\r\n\t\t\tconst media = hlsRef.current.media;\r\n\r\n\t\t\tif (media) {\r\n\t\t\t\tconst sourceBuffers = (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).mozSourceBuffers || (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).sourceBuffers;\r\n\r\n\t\t\t\tif (sourceBuffers) {\r\n\t\t\t\t\treturn Array.from(sourceBuffers).some((sb: SourceBuffer) => sb.updating);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t};\r\n\r\n\tuseIsomorphicLayoutEffect(() => {\r\n\t\tconst initializeHls = async ():Promise => {\r\n\t\t\tif (!isHlsSupported() || !videoSource) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst video = videoRef.current || createVideoElement();\r\n\r\n\t\t\tif (!hlsRef.current) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait initializeHlsInstance(video);\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tthrow new Error(`Error during Hls initialization: ${error.message}`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst loadHls = async (): Promise => {\r\n\t\t\ttry {\r\n\t\t\t\tawait initializeHls();\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new Error(`Error during video loading: ${error.message}`);\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst cleanupHls = (): void => {\r\n\t\t\tif (hlsRef.current) {\r\n\t\t\t\thlsRef.current.off(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t\t\thlsRef.current.destroy();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst initializeAndLoadHls = async (): Promise => {\r\n\t\t\tawait loadHls();\r\n\t\t};\r\n\r\n\t\tinitializeAndLoadHls().catch(error => {\r\n\t\t\tthrow new Error(`Error during initialization and loading Hls: ${error.message}`);\r\n\t\t});\r\n\r\n\t\treturn cleanupHls;\r\n\t}, [videoSource, options]);\r\n\treturn { videoRef };\r\n}\r\n"],"names":["useLayoutEffect","useEffect","useRef"],"mappings":"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"} \ No newline at end of file diff --git a/usehlsplayer.mjs b/usehlsplayer.mjs index d3add76..2035f0e 100644 --- a/usehlsplayer.mjs +++ b/usehlsplayer.mjs @@ -1,6 +1,17 @@ import Hls from 'hls.js'; import { useRef, useLayoutEffect, useEffect } from 'react'; +/** + * @file + * usehlsvideoplayer is a React hook + * designed to simplify the integration of Hls.js for video playback in your React applications. + * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source. + * With usehlsvideoplayer, you can effortlessly incorporate Hls.js functionality into your components. + * The hook takes care of cleaning up resources when the component unmounts. + * It automatically detaches the Hls.js instance and removes event listeners. + * @copyright (c) 2023 Klevert Opee + * @license ISC + */ let useIsomorphicLayoutEffect; if (typeof window !== "undefined") { useIsomorphicLayoutEffect = useLayoutEffect; diff --git a/usehlsplayer.mjs.map b/usehlsplayer.mjs.map index 65ae06b..2fe5b5e 100644 --- a/usehlsplayer.mjs.map +++ b/usehlsplayer.mjs.map @@ -1 +1 @@ -{"version":3,"file":"usehlsplayer.mjs","sources":["src/useHlsVideoPlayer.ts"],"sourcesContent":["import Hls from \"hls.js\";\r\nimport React, { DependencyList, EffectCallback, useEffect, useLayoutEffect, useRef } from \"react\";\r\n\r\ntype Options = {\r\n\t/**\r\n\t * Determines whether the loading of the stream should start automatically\r\n\t * when the Hls.js instance is created.\r\n\t */\r\n\tautoStartLoad?: boolean;\r\n\t/**\r\n\t * Specifies the initial quality level index to start playback with.\r\n\t * Use -1 for automatic level selection.\r\n\t */\r\n\tstartLevel?: number;\r\n\t/**\r\n\t * Sets the maximum buffer length (in seconds) to keep for instant playback.\r\n\t * Adjust for optimizing buffering behavior.\r\n\t */\r\n\tmaxBufferLength?: number;\r\n\t/**\r\n\t * Defines the maximum buffer size (in bytes) for the media\r\n\t * element.\r\n\t * Useful for controlling memory usage.\r\n\t */\r\n\tmaxBufferSize?: number;\r\n\t/**\r\n\t * Specifies the maximum buffer length (in seconds) for live content.\r\n\t * Adjust for optimizing live stream buffering.\r\n\t */\r\n\tmaxMaxBufferLength?: number;\r\n\t/**\r\n\t * Sets the number of target durations to keep in live synchronization\r\n\t * of the manifest.\r\n\t * Affects live stream synchronization.\r\n\t */\r\n\tliveSyncDurationCount?: number;\r\n\t/**\r\n\t * Configures the number of target durations to keep in live\r\n\t * synchronization for low-latency applications.\r\n\t */\r\n\tliveMaxLatencyDurationCount?: number;\r\n\t/**\r\n\t * Enables or disables the use of Web Workers for fetching and parsing\r\n\t * segments.\r\n\t * It Can improve performance.\r\n\t */\r\n\tenableWorker?: boolean;\r\n\t/**\r\n\t * Enables or disables software-based AES decryption.\r\n\t * Adjust based on hardware support for decryption.\r\n\t */\r\n\tenableSoftwareAES?: boolean;\r\n\t/**\r\n\t * Determines whether to force the generation of keyframes on\r\n\t * discontinuity for better seeking in live streams.\r\n\t */\r\n\tforceKeyFrameOnDiscontinuity?: boolean;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for level loading. Useful for handling delays in loading levels.\r\n\t */\r\n\tlevelLoadingTimeOut?: number;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for manifest loading.\r\n\t * Useful for handling delays in loading the manifest.\r\n\t */\r\n\tmanifestLoadingTimeOut?: number;\r\n\t/**\r\n\t * Allows customization of XHR setup function for handling XMLHttpRequest.\r\n\t * Useful for advanced use cases.\r\n\t */\r\n\txhrSetup?: () => void;\r\n\t/**\r\n\t * Limits the selected quality level to the size of the player.\r\n\t * Useful for optimizing quality based on player dimensions.\r\n\t */\r\n\tcapLevelToPlayerSize?: boolean;\r\n\t/**\r\n\t * Initiate fragment is prefetching to improve start-up time by loading\r\n\t * fragments in advance\r\n\t */\r\n\tstartFragPrefetch?: boolean;\r\n\t/**\r\n\t * Specifies the maximum number of retries for appending a segment on\r\n\t * error. Useful for handling segment append errors.\r\n\t */\r\n\tappendErrorMaxRetry?: number;\r\n};\r\n\r\ntype HlsPlayerResult = {\r\n\tvideoRef: React.RefObject;\r\n};\r\n\r\nlet useIsomorphicLayoutEffect: (effect: EffectCallback, deps?: DependencyList) => void;\r\nif (typeof window !== 'undefined') {\r\n\tuseIsomorphicLayoutEffect = useLayoutEffect;\r\n} else {\r\n\tuseIsomorphicLayoutEffect = useEffect;\r\n}\r\n\r\n/**\r\n * usehlsvideoplayer\r\n * is a React hook designed to simplify the integration of Hls.js for video playback in your React applications.\r\n * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source.\r\n * With `usehlsvideoplayer`, you can effortlessly incorporate Hls.js functionality into your components.\r\n *\r\n * The hook takes care of cleaning up resources when the component unmounts.\r\n * It automatically detaches the Hls.js instance and removes event listeners.\r\n *\r\n * @example\r\n * // Basic Usage\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource);\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @example\r\n * // Advanced Usage with Options\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource, {\r\n * startLevel: 2,\r\n * maxBufferLength: 60,\r\n * enableSoftwareAES: false,\r\n * // Add more options as needed. Below are the list of options and their defaults.\r\n * });\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @module usehlsvideoplayer\r\n * @function\r\n * @param {string} videoSource - The URL of the HLS video source to be loaded.\r\n * @param {Options} [options={}] - Optional configuration options for Hls.js.\r\n * @property {Object} videoRef - A React ref object for the video element.\r\n * @returns {Object} An object containing the video reference (`videoRef`).\r\n */\r\nexport function Usehlsplayer(videoSource: string, options: Options = {}): HlsPlayerResult {\r\n\tconst videoRef = useRef(null);\r\n\tconst hlsRef = useRef(null);\r\n\r\n\tconst isHlsSupported = () => Hls?.isSupported();\r\n\tconst createVideoElement = () => document.createElement('video');\r\n\tconst isWebWorkerSupported = () => typeof Worker !== 'undefined';\r\n\tconst checkAESSupport = async (): Promise => {\r\n\t\tif (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) {\r\n\t\t\ttry {\r\n\t\t\t\tawait window.crypto.subtle.importKey(\r\n\t\t\t\t\t'raw',\r\n\t\t\t\t\tnew ArrayBuffer(16),\r\n\t\t\t\t\t{ name: 'AES-CBC' },\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\t['encrypt', 'decrypt']\r\n\t\t\t\t);\r\n\t\t\t\treturn true;\r\n\t\t\t} catch (error) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n\r\n\tconst initializeHlsInstance = async (videoElement: HTMLVideoElement): Promise => {\r\n\t\tconst isWorkerSupported = isWebWorkerSupported();\r\n\t\tconst isAESSupported = await checkAESSupport();\r\n\r\n\t\tconst hlsOptions = {\r\n\t\t\tenableWorker: isWorkerSupported && options.enableWorker,\r\n\t\t\tenableSoftwareAES: isAESSupported && options.enableSoftwareAES,\r\n\t\t\t...options\r\n\t\t};\r\n\r\n\t\thlsRef.current = new Hls(hlsOptions);\r\n\r\n\t\ttry {\r\n\t\t\thlsRef.current.loadSource(videoSource);\r\n\t\t\thlsRef.current.attachMedia(videoElement);\r\n\t\t\thlsRef.current.on(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new Error(`Error initializing Hls.js: ${error.message}`);\r\n\t\t}\r\n\t};\r\n\r\n\tconst handleManifestParsed = (targetDuration: undefined): void => {\r\n\t\tif (hlsRef.current?.media && !isAnyBufferUpdating()) {\r\n\t\t\thlsRef.current.media.currentTime = targetDuration;\r\n\t\t}\r\n\t};\r\n\r\n\tconst isAnyBufferUpdating = (): boolean => {\r\n\t\tif (hlsRef.current) {\r\n\t\t\tconst media = hlsRef.current.media;\r\n\r\n\t\t\tif (media) {\r\n\t\t\t\tconst sourceBuffers = (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).mozSourceBuffers || (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).sourceBuffers;\r\n\r\n\t\t\t\tif (sourceBuffers) {\r\n\t\t\t\t\treturn Array.from(sourceBuffers).some((sb: SourceBuffer) => sb.updating);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t};\r\n\r\n\tuseIsomorphicLayoutEffect(() => {\r\n\t\tconst initializeHls = async ():Promise => {\r\n\t\t\tif (!isHlsSupported() || !videoSource) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst video = videoRef.current || createVideoElement();\r\n\r\n\t\t\tif (!hlsRef.current) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait initializeHlsInstance(video);\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tthrow new Error(`Error during Hls initialization: ${error.message}`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst loadHls = async (): Promise => {\r\n\t\t\ttry {\r\n\t\t\t\tawait initializeHls();\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new Error(`Error during video loading: ${error.message}`);\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst cleanupHls = (): void => {\r\n\t\t\tif (hlsRef.current) {\r\n\t\t\t\thlsRef.current.off(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t\t\thlsRef.current.destroy();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst initializeAndLoadHls = async (): Promise => {\r\n\t\t\tawait loadHls();\r\n\t\t};\r\n\r\n\t\tinitializeAndLoadHls().catch(error => {\r\n\t\t\tthrow new Error(`Error during initialization and loading Hls: ${error.message}`);\r\n\t\t});\r\n\r\n\t\treturn cleanupHls;\r\n\t}, [videoSource, options]);\r\n\treturn { videoRef };\r\n}\r\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"usehlsplayer.mjs","sources":["src/useHlsVideoPlayer.ts"],"sourcesContent":["/**\r\n * @file\r\n * usehlsvideoplayer is a React hook\r\n * designed to simplify the integration of Hls.js for video playback in your React applications.\r\n * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source.\r\n * With usehlsvideoplayer, you can effortlessly incorporate Hls.js functionality into your components.\r\n * The hook takes care of cleaning up resources when the component unmounts.\r\n * It automatically detaches the Hls.js instance and removes event listeners.\r\n * @copyright (c) 2023 Klevert Opee\r\n * @license ISC\r\n */\r\nimport Hls from \"hls.js\";\r\nimport React, { DependencyList, EffectCallback, useEffect, useLayoutEffect, useRef } from \"react\";\r\n\r\ntype Options = {\r\n\t/**\r\n\t * Determines whether the loading of the stream should start automatically\r\n\t * when the Hls.js instance is created.\r\n\t */\r\n\tautoStartLoad?: boolean;\r\n\t/**\r\n\t * Specifies the initial quality level index to start playback with.\r\n\t * Use -1 for automatic level selection.\r\n\t */\r\n\tstartLevel?: number;\r\n\t/**\r\n\t * Sets the maximum buffer length (in seconds) to keep for instant playback.\r\n\t * Adjust for optimizing buffering behavior.\r\n\t */\r\n\tmaxBufferLength?: number;\r\n\t/**\r\n\t * Defines the maximum buffer size (in bytes) for the media\r\n\t * element.\r\n\t * Useful for controlling memory usage.\r\n\t */\r\n\tmaxBufferSize?: number;\r\n\t/**\r\n\t * Specifies the maximum buffer length (in seconds) for live content.\r\n\t * Adjust for optimizing live stream buffering.\r\n\t */\r\n\tmaxMaxBufferLength?: number;\r\n\t/**\r\n\t * Sets the number of target durations to keep in live synchronization\r\n\t * of the manifest.\r\n\t * Affects live stream synchronization.\r\n\t */\r\n\tliveSyncDurationCount?: number;\r\n\t/**\r\n\t * Configures the number of target durations to keep in live\r\n\t * synchronization for low-latency applications.\r\n\t */\r\n\tliveMaxLatencyDurationCount?: number;\r\n\t/**\r\n\t * Enables or disables the use of Web Workers for fetching and parsing\r\n\t * segments.\r\n\t * It Can improve performance.\r\n\t */\r\n\tenableWorker?: boolean;\r\n\t/**\r\n\t * Enables or disables software-based AES decryption.\r\n\t * Adjust based on hardware support for decryption.\r\n\t */\r\n\tenableSoftwareAES?: boolean;\r\n\t/**\r\n\t * Determines whether to force the generation of keyframes on\r\n\t * discontinuity for better seeking in live streams.\r\n\t */\r\n\tforceKeyFrameOnDiscontinuity?: boolean;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for level loading. Useful for handling delays in loading levels.\r\n\t */\r\n\tlevelLoadingTimeOut?: number;\r\n\t/**\r\n\t * Sets the timeout (in milliseconds) for manifest loading.\r\n\t * Useful for handling delays in loading the manifest.\r\n\t */\r\n\tmanifestLoadingTimeOut?: number;\r\n\t/**\r\n\t * Allows customization of XHR setup function for handling XMLHttpRequest.\r\n\t * Useful for advanced use cases.\r\n\t */\r\n\txhrSetup?: () => void;\r\n\t/**\r\n\t * Limits the selected quality level to the size of the player.\r\n\t * Useful for optimizing quality based on player dimensions.\r\n\t */\r\n\tcapLevelToPlayerSize?: boolean;\r\n\t/**\r\n\t * Initiate fragment is prefetching to improve start-up time by loading\r\n\t * fragments in advance\r\n\t */\r\n\tstartFragPrefetch?: boolean;\r\n\t/**\r\n\t * Specifies the maximum number of retries for appending a segment on\r\n\t * error. Useful for handling segment append errors.\r\n\t */\r\n\tappendErrorMaxRetry?: number;\r\n};\r\n\r\ntype HlsPlayerResult = {\r\n\tvideoRef: React.RefObject;\r\n};\r\n\r\nlet useIsomorphicLayoutEffect: (effect: EffectCallback, deps?: DependencyList) => void;\r\nif (typeof window !== 'undefined') {\r\n\tuseIsomorphicLayoutEffect = useLayoutEffect;\r\n} else {\r\n\tuseIsomorphicLayoutEffect = useEffect;\r\n}\r\n\r\n/**\r\n * usehlsvideoplayer\r\n * is a React hook designed to simplify the integration of Hls.js for video playback in your React applications.\r\n * This hook creates a video player instance and manages the loading of an HTTP Live Streaming (HLS) video source.\r\n * With `usehlsvideoplayer`, you can effortlessly incorporate Hls.js functionality into your components.\r\n *\r\n * The hook takes care of cleaning up resources when the component unmounts.\r\n * It automatically detaches the Hls.js instance and removes event listeners.\r\n *\r\n * @example\r\n * // Basic Usage\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource);\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @example\r\n * // Advanced Usage with Options\r\n * import { Usehlsplayer } from 'usehlsvideoplayer';\r\n *\r\n * const YourComponent = () => {\r\n * const videoSource = 'your-hls-video-source-url';\r\n * const { videoRef } = Usehlsplayer(videoSource, {\r\n * startLevel: 2,\r\n * maxBufferLength: 60,\r\n * enableSoftwareAES: false,\r\n * // Add more options as needed. Below are the list of options and their defaults.\r\n * });\r\n *\r\n * return (
\r\n * \r\n *
);\r\n * };\r\n *\r\n * @module usehlsvideoplayer\r\n * @function\r\n * @param {string} videoSource - The URL of the HLS video source to be loaded.\r\n * @param {Options} [options={}] - Optional configuration options for Hls.js.\r\n * @property {Object} videoRef - A React ref object for the video element.\r\n * @returns {Object} An object containing the video reference (`videoRef`).\r\n */\r\nexport function Usehlsplayer(videoSource: string, options: Options = {}): HlsPlayerResult {\r\n\tconst videoRef = useRef(null);\r\n\tconst hlsRef = useRef(null);\r\n\r\n\tconst isHlsSupported = () => Hls?.isSupported();\r\n\tconst createVideoElement = () => document.createElement('video');\r\n\tconst isWebWorkerSupported = () => typeof Worker !== 'undefined';\r\n\tconst checkAESSupport = async (): Promise => {\r\n\t\tif (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) {\r\n\t\t\ttry {\r\n\t\t\t\tawait window.crypto.subtle.importKey(\r\n\t\t\t\t\t'raw',\r\n\t\t\t\t\tnew ArrayBuffer(16),\r\n\t\t\t\t\t{ name: 'AES-CBC' },\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\t['encrypt', 'decrypt']\r\n\t\t\t\t);\r\n\t\t\t\treturn true;\r\n\t\t\t} catch (error) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n\r\n\tconst initializeHlsInstance = async (videoElement: HTMLVideoElement): Promise => {\r\n\t\tconst isWorkerSupported = isWebWorkerSupported();\r\n\t\tconst isAESSupported = await checkAESSupport();\r\n\r\n\t\tconst hlsOptions = {\r\n\t\t\tenableWorker: isWorkerSupported && options.enableWorker,\r\n\t\t\tenableSoftwareAES: isAESSupported && options.enableSoftwareAES,\r\n\t\t\t...options\r\n\t\t};\r\n\r\n\t\thlsRef.current = new Hls(hlsOptions);\r\n\r\n\t\ttry {\r\n\t\t\thlsRef.current.loadSource(videoSource);\r\n\t\t\thlsRef.current.attachMedia(videoElement);\r\n\t\t\thlsRef.current.on(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new Error(`Error initializing Hls.js: ${error.message}`);\r\n\t\t}\r\n\t};\r\n\r\n\tconst handleManifestParsed = (targetDuration: undefined): void => {\r\n\t\tif (hlsRef.current?.media && !isAnyBufferUpdating()) {\r\n\t\t\thlsRef.current.media.currentTime = targetDuration;\r\n\t\t}\r\n\t};\r\n\r\n\tconst isAnyBufferUpdating = (): boolean => {\r\n\t\tif (hlsRef.current) {\r\n\t\t\tconst media = hlsRef.current.media;\r\n\r\n\t\t\tif (media) {\r\n\t\t\t\tconst sourceBuffers = (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).mozSourceBuffers || (media as HTMLMediaElement & {\r\n\t\t\t\t\tmozSourceBuffers?: SourceBufferList;\r\n\t\t\t\t\tsourceBuffers?: SourceBufferList;\r\n\t\t\t\t}).sourceBuffers;\r\n\r\n\t\t\t\tif (sourceBuffers) {\r\n\t\t\t\t\treturn Array.from(sourceBuffers).some((sb: SourceBuffer) => sb.updating);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t};\r\n\r\n\tuseIsomorphicLayoutEffect(() => {\r\n\t\tconst initializeHls = async ():Promise => {\r\n\t\t\tif (!isHlsSupported() || !videoSource) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst video = videoRef.current || createVideoElement();\r\n\r\n\t\t\tif (!hlsRef.current) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tawait initializeHlsInstance(video);\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tthrow new Error(`Error during Hls initialization: ${error.message}`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst loadHls = async (): Promise => {\r\n\t\t\ttry {\r\n\t\t\t\tawait initializeHls();\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new Error(`Error during video loading: ${error.message}`);\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst cleanupHls = (): void => {\r\n\t\t\tif (hlsRef.current) {\r\n\t\t\t\thlsRef.current.off(Hls.Events.MANIFEST_PARSED, handleManifestParsed);\r\n\t\t\t\thlsRef.current.destroy();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst initializeAndLoadHls = async (): Promise => {\r\n\t\t\tawait loadHls();\r\n\t\t};\r\n\r\n\t\tinitializeAndLoadHls().catch(error => {\r\n\t\t\tthrow new Error(`Error during initialization and loading Hls: ${error.message}`);\r\n\t\t});\r\n\r\n\t\treturn cleanupHls;\r\n\t}, [videoSource, options]);\r\n\treturn { videoRef };\r\n}\r\n"],"names":[],"mappings":"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"} \ No newline at end of file