@livepeer-frameworks/player-react 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -9
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +359 -0
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
- package/dist/cjs/assets/logomark.svg.js +8 -0
- package/dist/cjs/assets/logomark.svg.js.map +1 -0
- package/dist/cjs/components/DevModePanel.js +826 -0
- package/dist/cjs/components/DevModePanel.js.map +1 -0
- package/dist/cjs/components/DvdLogo.js +200 -0
- package/dist/cjs/components/DvdLogo.js.map +1 -0
- package/dist/cjs/components/Icons.js +439 -0
- package/dist/cjs/components/Icons.js.map +1 -0
- package/dist/cjs/components/IdleScreen.js +587 -0
- package/dist/cjs/components/IdleScreen.js.map +1 -0
- package/dist/cjs/components/LoadingScreen.js +523 -0
- package/dist/cjs/components/LoadingScreen.js.map +1 -0
- package/dist/cjs/components/Player.js +420 -0
- package/dist/cjs/components/Player.js.map +1 -0
- package/dist/cjs/components/PlayerControls.js +798 -0
- package/dist/cjs/components/PlayerControls.js.map +1 -0
- package/dist/cjs/components/PlayerErrorBoundary.js +80 -0
- package/dist/cjs/components/PlayerErrorBoundary.js.map +1 -0
- package/dist/cjs/components/SeekBar.js +253 -0
- package/dist/cjs/components/SeekBar.js.map +1 -0
- package/dist/cjs/components/SkipIndicator.js +92 -0
- package/dist/cjs/components/SkipIndicator.js.map +1 -0
- package/dist/cjs/components/SpeedIndicator.js +43 -0
- package/dist/cjs/components/SpeedIndicator.js.map +1 -0
- package/dist/cjs/components/StatsPanel.js +202 -0
- package/dist/cjs/components/StatsPanel.js.map +1 -0
- package/dist/cjs/components/StreamStateOverlay.js +229 -0
- package/dist/cjs/components/StreamStateOverlay.js.map +1 -0
- package/dist/cjs/components/ThumbnailOverlay.js +86 -0
- package/dist/cjs/components/ThumbnailOverlay.js.map +1 -0
- package/dist/cjs/components/TitleOverlay.js +32 -0
- package/dist/cjs/components/TitleOverlay.js.map +1 -0
- package/dist/cjs/context/PlayerContext.js +46 -0
- package/dist/cjs/context/PlayerContext.js.map +1 -0
- package/dist/cjs/hooks/useMetaTrack.js +165 -0
- package/dist/cjs/hooks/useMetaTrack.js.map +1 -0
- package/dist/cjs/hooks/usePlaybackQuality.js +131 -0
- package/dist/cjs/hooks/usePlaybackQuality.js.map +1 -0
- package/dist/cjs/hooks/usePlayerController.js +518 -0
- package/dist/cjs/hooks/usePlayerController.js.map +1 -0
- package/dist/cjs/hooks/usePlayerSelection.js +90 -0
- package/dist/cjs/hooks/usePlayerSelection.js.map +1 -0
- package/dist/cjs/hooks/useStreamState.js +360 -0
- package/dist/cjs/hooks/useStreamState.js.map +1 -0
- package/dist/cjs/hooks/useTelemetry.js +120 -0
- package/dist/cjs/hooks/useTelemetry.js.map +1 -0
- package/dist/cjs/hooks/useViewerEndpoints.js +222 -0
- package/dist/cjs/hooks/useViewerEndpoints.js.map +1 -0
- package/dist/cjs/index.js +97 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/ui/badge.js +34 -0
- package/dist/cjs/ui/badge.js.map +1 -0
- package/dist/cjs/ui/button.js +74 -0
- package/dist/cjs/ui/button.js.map +1 -0
- package/dist/cjs/ui/context-menu.js +163 -0
- package/dist/cjs/ui/context-menu.js.map +1 -0
- package/dist/cjs/ui/slider.js +60 -0
- package/dist/cjs/ui/slider.js.map +1 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +329 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
- package/dist/esm/assets/logomark.svg.js +4 -0
- package/dist/esm/assets/logomark.svg.js.map +1 -0
- package/dist/esm/components/DevModePanel.js +822 -0
- package/dist/esm/components/DevModePanel.js.map +1 -0
- package/dist/esm/components/DvdLogo.js +196 -0
- package/dist/esm/components/DvdLogo.js.map +1 -0
- package/dist/esm/components/Icons.js +421 -0
- package/dist/esm/components/Icons.js.map +1 -0
- package/dist/esm/components/IdleScreen.js +582 -0
- package/dist/esm/components/IdleScreen.js.map +1 -0
- package/dist/esm/components/LoadingScreen.js +519 -0
- package/dist/esm/components/LoadingScreen.js.map +1 -0
- package/dist/esm/components/Player.js +416 -0
- package/dist/esm/components/Player.js.map +1 -0
- package/dist/esm/components/PlayerControls.js +794 -0
- package/dist/esm/components/PlayerControls.js.map +1 -0
- package/dist/esm/components/PlayerErrorBoundary.js +76 -0
- package/dist/esm/components/PlayerErrorBoundary.js.map +1 -0
- package/dist/esm/components/SeekBar.js +249 -0
- package/dist/esm/components/SeekBar.js.map +1 -0
- package/dist/esm/components/SkipIndicator.js +88 -0
- package/dist/esm/components/SkipIndicator.js.map +1 -0
- package/dist/esm/components/SpeedIndicator.js +39 -0
- package/dist/esm/components/SpeedIndicator.js.map +1 -0
- package/dist/esm/components/StatsPanel.js +198 -0
- package/dist/esm/components/StatsPanel.js.map +1 -0
- package/dist/esm/components/StreamStateOverlay.js +224 -0
- package/dist/esm/components/StreamStateOverlay.js.map +1 -0
- package/dist/esm/components/ThumbnailOverlay.js +82 -0
- package/dist/esm/components/ThumbnailOverlay.js.map +1 -0
- package/dist/esm/components/TitleOverlay.js +28 -0
- package/dist/esm/components/TitleOverlay.js.map +1 -0
- package/dist/esm/context/PlayerContext.js +41 -0
- package/dist/esm/context/PlayerContext.js.map +1 -0
- package/dist/esm/hooks/useMetaTrack.js +163 -0
- package/dist/esm/hooks/useMetaTrack.js.map +1 -0
- package/dist/esm/hooks/usePlaybackQuality.js +129 -0
- package/dist/esm/hooks/usePlaybackQuality.js.map +1 -0
- package/dist/esm/hooks/usePlayerController.js +516 -0
- package/dist/esm/hooks/usePlayerController.js.map +1 -0
- package/dist/esm/hooks/usePlayerSelection.js +88 -0
- package/dist/esm/hooks/usePlayerSelection.js.map +1 -0
- package/dist/esm/hooks/useStreamState.js +358 -0
- package/dist/esm/hooks/useStreamState.js.map +1 -0
- package/dist/esm/hooks/useTelemetry.js +118 -0
- package/dist/esm/hooks/useTelemetry.js.map +1 -0
- package/dist/esm/hooks/useViewerEndpoints.js +220 -0
- package/dist/esm/hooks/useViewerEndpoints.js.map +1 -0
- package/dist/esm/index.js +23 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/ui/badge.js +31 -0
- package/dist/esm/ui/badge.js.map +1 -0
- package/dist/esm/ui/button.js +52 -0
- package/dist/esm/ui/button.js.map +1 -0
- package/dist/esm/ui/context-menu.js +132 -0
- package/dist/esm/ui/context-menu.js.map +1 -0
- package/dist/esm/ui/slider.js +38 -0
- package/dist/esm/ui/slider.js.map +1 -0
- package/dist/types/components/DvdLogo.d.ts +1 -1
- package/dist/types/components/Icons.d.ts +1 -1
- package/dist/types/components/Player.d.ts +1 -1
- package/dist/types/components/PlayerErrorBoundary.d.ts +2 -1
- package/dist/types/components/StreamStateOverlay.d.ts +2 -2
- package/dist/types/components/SubtitleRenderer.d.ts +2 -2
- package/dist/types/context/PlayerContext.d.ts +2 -2
- package/dist/types/context/index.d.ts +2 -2
- package/dist/types/hooks/useMetaTrack.d.ts +3 -3
- package/dist/types/hooks/usePlaybackQuality.d.ts +2 -2
- package/dist/types/hooks/usePlayerController.d.ts +26 -3
- package/dist/types/hooks/usePlayerSelection.d.ts +1 -1
- package/dist/types/hooks/useStreamState.d.ts +1 -1
- package/dist/types/hooks/useTelemetry.d.ts +1 -1
- package/dist/types/hooks/useViewerEndpoints.d.ts +3 -3
- package/dist/types/index.d.ts +28 -28
- package/dist/types/types.d.ts +3 -3
- package/dist/types/ui/select.d.ts +1 -1
- package/package.json +22 -14
- package/src/components/DevModePanel.tsx +244 -143
- package/src/components/DvdLogo.tsx +1 -1
- package/src/components/Icons.tsx +105 -25
- package/src/components/IdleScreen.tsx +262 -128
- package/src/components/LoadingScreen.tsx +169 -151
- package/src/components/LogoOverlay.tsx +3 -6
- package/src/components/Player.tsx +126 -59
- package/src/components/PlayerControls.tsx +384 -272
- package/src/components/PlayerErrorBoundary.tsx +7 -13
- package/src/components/SeekBar.tsx +96 -88
- package/src/components/SkipIndicator.tsx +2 -12
- package/src/components/SpeedIndicator.tsx +2 -11
- package/src/components/StatsPanel.tsx +31 -22
- package/src/components/StreamStateOverlay.tsx +105 -49
- package/src/components/SubtitleRenderer.tsx +29 -29
- package/src/components/ThumbnailOverlay.tsx +5 -6
- package/src/components/TitleOverlay.tsx +2 -8
- package/src/context/PlayerContext.tsx +4 -8
- package/src/context/index.ts +3 -3
- package/src/hooks/useMetaTrack.ts +27 -27
- package/src/hooks/usePlaybackQuality.ts +3 -3
- package/src/hooks/usePlayerController.ts +246 -138
- package/src/hooks/usePlayerSelection.ts +6 -6
- package/src/hooks/useStreamState.ts +51 -56
- package/src/hooks/useTelemetry.ts +18 -3
- package/src/hooks/useViewerEndpoints.ts +34 -23
- package/src/index.tsx +36 -28
- package/src/types.ts +8 -8
- package/src/ui/badge.tsx +6 -5
- package/src/ui/button.tsx +9 -8
- package/src/ui/context-menu.tsx +42 -61
- package/src/ui/select.tsx +13 -7
- package/src/ui/slider.tsx +18 -29
- package/dist/types/components/players/DashJsPlayer.d.ts +0 -18
- package/dist/types/components/players/HlsJsPlayer.d.ts +0 -18
- package/dist/types/components/players/MewsWsPlayer/index.d.ts +0 -18
- package/dist/types/components/players/MistPlayer.d.ts +0 -20
- package/dist/types/components/players/MistWebRTCPlayer/index.d.ts +0 -20
- package/dist/types/components/players/NativePlayer.d.ts +0 -19
- package/dist/types/components/players/VideoJsPlayer.d.ts +0 -18
- package/src/components/players/DashJsPlayer.tsx +0 -56
- package/src/components/players/HlsJsPlayer.tsx +0 -56
- package/src/components/players/MewsWsPlayer/index.tsx +0 -56
- package/src/components/players/MistPlayer.tsx +0 -60
- package/src/components/players/MistWebRTCPlayer/index.tsx +0 -59
- package/src/components/players/NativePlayer.tsx +0 -58
- package/src/components/players/VideoJsPlayer.tsx +0 -56
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { cn } from '@livepeer-frameworks/player-core';
|
|
3
|
+
import { Button } from '../ui/button.js';
|
|
4
|
+
|
|
5
|
+
var ThumbnailOverlay = function ThumbnailOverlay(_ref) {
|
|
6
|
+
var thumbnailUrl = _ref.thumbnailUrl,
|
|
7
|
+
onPlay = _ref.onPlay,
|
|
8
|
+
message = _ref.message,
|
|
9
|
+
_ref$showUnmuteMessag = _ref.showUnmuteMessage,
|
|
10
|
+
showUnmuteMessage = _ref$showUnmuteMessag === void 0 ? false : _ref$showUnmuteMessag,
|
|
11
|
+
style = _ref.style,
|
|
12
|
+
className = _ref.className;
|
|
13
|
+
var handleClick = function handleClick(e) {
|
|
14
|
+
e.stopPropagation();
|
|
15
|
+
onPlay === null || onPlay === void 0 || onPlay();
|
|
16
|
+
};
|
|
17
|
+
return jsxs("div", {
|
|
18
|
+
role: "button",
|
|
19
|
+
tabIndex: 0,
|
|
20
|
+
onClick: handleClick,
|
|
21
|
+
onKeyDown: function onKeyDown(event) {
|
|
22
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
23
|
+
event.preventDefault();
|
|
24
|
+
handleClick(event);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
style: style,
|
|
28
|
+
className: cn("fw-player-thumbnail relative flex h-full min-h-[280px] w-full cursor-pointer items-center justify-center overflow-hidden rounded-xl bg-slate-950 text-foreground outline-none transition focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background", className),
|
|
29
|
+
children: [thumbnailUrl && jsx("div", {
|
|
30
|
+
className: "absolute inset-0 bg-cover bg-center",
|
|
31
|
+
style: {
|
|
32
|
+
backgroundImage: "url(".concat(thumbnailUrl, ")")
|
|
33
|
+
}
|
|
34
|
+
}), jsx("div", {
|
|
35
|
+
className: cn("absolute inset-0 bg-slate-950/70", !thumbnailUrl && "bg-gradient-to-br from-slate-900 via-slate-950 to-slate-900")
|
|
36
|
+
}), jsx("div", {
|
|
37
|
+
className: "relative z-10 flex max-w-[320px] flex-col items-center gap-4 px-6 text-center text-sm sm:gap-6",
|
|
38
|
+
children: showUnmuteMessage ? jsxs("div", {
|
|
39
|
+
className: "w-full rounded-lg border border-white/15 bg-black/80 p-4 text-sm text-white shadow-lg backdrop-blur",
|
|
40
|
+
children: [jsxs("div", {
|
|
41
|
+
className: "mb-1 flex items-center justify-center gap-2 text-base font-semibold text-primary",
|
|
42
|
+
children: [jsx("span", {
|
|
43
|
+
"aria-hidden": "true",
|
|
44
|
+
children: "\uD83D\uDD07"
|
|
45
|
+
}), " Click to unmute"]
|
|
46
|
+
}), jsx("p", {
|
|
47
|
+
className: "text-xs text-white/80",
|
|
48
|
+
children: "Stream is playing muted \u2014 tap to enable sound."
|
|
49
|
+
})]
|
|
50
|
+
}) : jsxs(Fragment, {
|
|
51
|
+
children: [jsx(Button, {
|
|
52
|
+
type: "button",
|
|
53
|
+
size: "icon",
|
|
54
|
+
variant: "secondary",
|
|
55
|
+
className: "h-20 w-20 rounded-full bg-primary/90 text-primary-foreground shadow-lg shadow-primary/40 transition hover:bg-primary focus-visible:bg-primary",
|
|
56
|
+
"aria-label": "Play stream",
|
|
57
|
+
children: jsx("svg", {
|
|
58
|
+
viewBox: "0 0 24 24",
|
|
59
|
+
fill: "currentColor",
|
|
60
|
+
className: "ml-0.5 h-8 w-8",
|
|
61
|
+
"aria-hidden": "true",
|
|
62
|
+
children: jsx("path", {
|
|
63
|
+
d: "M8 5v14l11-7z"
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
}), jsxs("div", {
|
|
67
|
+
className: "w-full rounded-lg border border-white/10 bg-black/70 p-5 text-white shadow-inner backdrop-blur",
|
|
68
|
+
children: [jsx("p", {
|
|
69
|
+
className: "text-base font-semibold text-primary",
|
|
70
|
+
children: message !== null && message !== void 0 ? message : "Click to play"
|
|
71
|
+
}), jsx("p", {
|
|
72
|
+
className: "mt-1 text-xs text-white/70",
|
|
73
|
+
children: message ? "Start streaming instantly" : "Jump into the live feed"
|
|
74
|
+
})]
|
|
75
|
+
})]
|
|
76
|
+
})
|
|
77
|
+
})]
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { ThumbnailOverlay as default };
|
|
82
|
+
//# sourceMappingURL=ThumbnailOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThumbnailOverlay.js","sources":["../../../../src/components/ThumbnailOverlay.tsx"],"sourcesContent":["import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\nimport { Button } from \"../ui/button\";\nimport type { ThumbnailOverlayProps } from \"../types\";\n\nconst ThumbnailOverlay: React.FC<ThumbnailOverlayProps> = ({\n thumbnailUrl,\n onPlay,\n message,\n showUnmuteMessage = false,\n style,\n className,\n}) => {\n const handleClick = (e: React.MouseEvent | React.KeyboardEvent) => {\n e.stopPropagation();\n onPlay?.();\n };\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleClick(event);\n }\n }}\n style={style}\n className={cn(\n \"fw-player-thumbnail relative flex h-full min-h-[280px] w-full cursor-pointer items-center justify-center overflow-hidden rounded-xl bg-slate-950 text-foreground outline-none transition focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n className\n )}\n >\n {thumbnailUrl && (\n <div\n className=\"absolute inset-0 bg-cover bg-center\"\n style={{ backgroundImage: `url(${thumbnailUrl})` }}\n />\n )}\n\n <div\n className={cn(\n \"absolute inset-0 bg-slate-950/70\",\n !thumbnailUrl && \"bg-gradient-to-br from-slate-900 via-slate-950 to-slate-900\"\n )}\n />\n\n <div className=\"relative z-10 flex max-w-[320px] flex-col items-center gap-4 px-6 text-center text-sm sm:gap-6\">\n {showUnmuteMessage ? (\n <div className=\"w-full rounded-lg border border-white/15 bg-black/80 p-4 text-sm text-white shadow-lg backdrop-blur\">\n <div className=\"mb-1 flex items-center justify-center gap-2 text-base font-semibold text-primary\">\n <span aria-hidden=\"true\">🔇</span> Click to unmute\n </div>\n <p className=\"text-xs text-white/80\">Stream is playing muted — tap to enable sound.</p>\n </div>\n ) : (\n <>\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"secondary\"\n className=\"h-20 w-20 rounded-full bg-primary/90 text-primary-foreground shadow-lg shadow-primary/40 transition hover:bg-primary focus-visible:bg-primary\"\n aria-label=\"Play stream\"\n >\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"ml-0.5 h-8 w-8\"\n aria-hidden=\"true\"\n >\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n </Button>\n <div className=\"w-full rounded-lg border border-white/10 bg-black/70 p-5 text-white shadow-inner backdrop-blur\">\n <p className=\"text-base font-semibold text-primary\">{message ?? \"Click to play\"}</p>\n <p className=\"mt-1 text-xs text-white/70\">\n {message ? \"Start streaming instantly\" : \"Jump into the live feed\"}\n </p>\n </div>\n </>\n )}\n </div>\n </div>\n );\n};\n\nexport default ThumbnailOverlay;\n"],"names":["ThumbnailOverlay","_ref","thumbnailUrl","onPlay","message","_ref$showUnmuteMessag","showUnmuteMessage","style","className","handleClick","e","stopPropagation","_jsxs","role","tabIndex","onClick","onKeyDown","event","key","preventDefault","cn","_jsx","backgroundImage","concat","children","Button","type","size","variant","viewBox","fill","d"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { cn } from '@livepeer-frameworks/player-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Title/description overlay that appears at the top of the player.
|
|
6
|
+
* Visible on hover or when paused - controlled by parent via isVisible prop.
|
|
7
|
+
*/
|
|
8
|
+
var TitleOverlay = function TitleOverlay(_ref) {
|
|
9
|
+
var title = _ref.title,
|
|
10
|
+
description = _ref.description,
|
|
11
|
+
isVisible = _ref.isVisible,
|
|
12
|
+
className = _ref.className;
|
|
13
|
+
// Don't render if no content
|
|
14
|
+
if (!title && !description) return null;
|
|
15
|
+
return jsxs("div", {
|
|
16
|
+
className: cn("fw-title-overlay absolute inset-x-0 top-0 z-20 pointer-events-none", "bg-gradient-to-b from-black/70 via-black/40 to-transparent", "px-4 py-3 transition-opacity duration-300", isVisible ? "opacity-100" : "opacity-0", className),
|
|
17
|
+
children: [title && jsx("h2", {
|
|
18
|
+
className: "text-white text-sm font-medium truncate max-w-[80%]",
|
|
19
|
+
children: title
|
|
20
|
+
}), description && jsx("p", {
|
|
21
|
+
className: "text-white/70 text-xs mt-0.5 line-clamp-2 max-w-[70%]",
|
|
22
|
+
children: description
|
|
23
|
+
})]
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { TitleOverlay as default };
|
|
28
|
+
//# sourceMappingURL=TitleOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TitleOverlay.js","sources":["../../../../src/components/TitleOverlay.tsx"],"sourcesContent":["import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface TitleOverlayProps {\n title?: string | null;\n description?: string | null;\n isVisible: boolean;\n className?: string;\n}\n\n/**\n * Title/description overlay that appears at the top of the player.\n * Visible on hover or when paused - controlled by parent via isVisible prop.\n */\nconst TitleOverlay: React.FC<TitleOverlayProps> = ({\n title,\n description,\n isVisible,\n className,\n}) => {\n // Don't render if no content\n if (!title && !description) return null;\n\n return (\n <div\n className={cn(\n \"fw-title-overlay absolute inset-x-0 top-0 z-20 pointer-events-none\",\n \"bg-gradient-to-b from-black/70 via-black/40 to-transparent\",\n \"px-4 py-3 transition-opacity duration-300\",\n isVisible ? \"opacity-100\" : \"opacity-0\",\n className\n )}\n >\n {title && <h2 className=\"text-white text-sm font-medium truncate max-w-[80%]\">{title}</h2>}\n {description && (\n <p className=\"text-white/70 text-xs mt-0.5 line-clamp-2 max-w-[70%]\">{description}</p>\n )}\n </div>\n );\n};\n\nexport default TitleOverlay;\n"],"names":["TitleOverlay","_ref","title","description","isVisible","className","_jsxs","cn","_jsx","children"],"mappings":";;;AAUA;;;AAGG;AACH,IAAMA,YAAY,GAAgC,SAA5CA,YAAYA,CAAAC,IAAA,EAKb;AAAA,EAAA,IAJHC,KAAK,GAAAD,IAAA,CAALC,KAAK;IACLC,WAAW,GAAAF,IAAA,CAAXE,WAAW;IACXC,SAAS,GAAAH,IAAA,CAATG,SAAS;IACTC,SAAS,GAAAJ,IAAA,CAATI,SAAS;AAET;AACA,EAAA,IAAI,CAACH,KAAK,IAAI,CAACC,WAAW,EAAE,OAAO,IAAI;EAEvC,OACEG;AACED,IAAAA,SAAS,EAAEE,EAAE,CACX,oEAAoE,EACpE,4DAA4D,EAC5D,2CAA2C,EAC3CH,SAAS,GAAG,aAAa,GAAG,WAAW,EACvCC,SAAS,CACV;eAEAH,KAAK,IAAIM;AAAIH,MAAAA,SAAS,EAAC,qDAAqD;AAAAI,MAAAA,QAAA,EAAEP;AAAK,KAAA,CAAM,EACzFC,WAAW,IACVK,GAAA,CAAA,GAAA,EAAA;AAAGH,MAAAA,SAAS,EAAC,uDAAuD;AAAAI,MAAAA,QAAA,EAAEN;AAAW,KAAA,CAClF;AAAA,GAAA,CACG;AAEV;;;;"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
import { usePlayerController } from '../hooks/usePlayerController.js';
|
|
4
|
+
|
|
5
|
+
// Context holds the full hook return value
|
|
6
|
+
var PlayerContext = /*#__PURE__*/createContext(null);
|
|
7
|
+
/**
|
|
8
|
+
* Provider component that wraps Player and its controls.
|
|
9
|
+
* Calls usePlayerController internally and shares state via context.
|
|
10
|
+
*/
|
|
11
|
+
function PlayerProvider(_ref) {
|
|
12
|
+
var children = _ref.children,
|
|
13
|
+
config = _ref.config;
|
|
14
|
+
var playerController = usePlayerController(config);
|
|
15
|
+
return jsx(PlayerContext.Provider, {
|
|
16
|
+
value: playerController,
|
|
17
|
+
children: children
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Hook to access player context.
|
|
22
|
+
* Must be used within a PlayerProvider.
|
|
23
|
+
*/
|
|
24
|
+
function usePlayerContext() {
|
|
25
|
+
var context = useContext(PlayerContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error("usePlayerContext must be used within a PlayerProvider");
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Hook to optionally access player context.
|
|
33
|
+
* Returns null if not within a PlayerProvider (no error thrown).
|
|
34
|
+
* Use this when component may or may not be within a PlayerProvider.
|
|
35
|
+
*/
|
|
36
|
+
function usePlayerContextOptional() {
|
|
37
|
+
return useContext(PlayerContext);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { PlayerContext, PlayerProvider, usePlayerContext, usePlayerContextOptional };
|
|
41
|
+
//# sourceMappingURL=PlayerContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlayerContext.js","sources":["../../../../src/context/PlayerContext.tsx"],"sourcesContent":["/**\n * PlayerContext\n *\n * React context for sharing PlayerController state across components.\n * Follows the \"context wraps hook\" pattern (same as npm_studio).\n *\n * Usage:\n * ```tsx\n * <PlayerProvider config={{ contentId: 'stream-1', contentType: 'live' }}>\n * <PlayerControls />\n * </PlayerProvider>\n * ```\n */\n\nimport React, { createContext, useContext, type ReactNode } from \"react\";\nimport {\n usePlayerController,\n type UsePlayerControllerConfig,\n type UsePlayerControllerReturn,\n} from \"../hooks/usePlayerController\";\n\n// Context holds the full hook return value\nconst PlayerContext = createContext<UsePlayerControllerReturn | null>(null);\n\nexport interface PlayerProviderProps {\n children: ReactNode;\n /** Configuration for the player controller */\n config: UsePlayerControllerConfig;\n}\n\n/**\n * Provider component that wraps Player and its controls.\n * Calls usePlayerController internally and shares state via context.\n */\nexport function PlayerProvider({ children, config }: PlayerProviderProps) {\n const playerController = usePlayerController(config);\n\n return <PlayerContext.Provider value={playerController}>{children}</PlayerContext.Provider>;\n}\n\n/**\n * Hook to access player context.\n * Must be used within a PlayerProvider.\n */\nexport function usePlayerContext(): UsePlayerControllerReturn {\n const context = useContext(PlayerContext);\n if (!context) {\n throw new Error(\"usePlayerContext must be used within a PlayerProvider\");\n }\n return context;\n}\n\n/**\n * Hook to optionally access player context.\n * Returns null if not within a PlayerProvider (no error thrown).\n * Use this when component may or may not be within a PlayerProvider.\n */\nexport function usePlayerContextOptional(): UsePlayerControllerReturn | null {\n return useContext(PlayerContext);\n}\n\n// Export context for advanced use cases\nexport { PlayerContext };\n\n// Type exports\nexport type { UsePlayerControllerReturn as PlayerContextValue };\nexport type { UsePlayerControllerConfig };\n"],"names":["PlayerContext","createContext","PlayerProvider","_ref","children","config","playerController","usePlayerController","_jsx","Provider","value","usePlayerContext","context","useContext","Error","usePlayerContextOptional"],"mappings":";;;;AAqBA;AACA,IAAMA,aAAa,gBAAGC,aAAa,CAAmC,IAAI;AAQ1E;;;AAGG;SACaC,cAAcA,CAAAC,IAAA,EAA0C;AAAA,EAAA,IAAvCC,QAAQ,GAAAD,IAAA,CAARC,QAAQ;IAAEC,MAAM,GAAAF,IAAA,CAANE,MAAM;AAC/C,EAAA,IAAMC,gBAAgB,GAAGC,mBAAmB,CAACF,MAAM,CAAC;AAEpD,EAAA,OAAOG,GAAA,CAACR,aAAa,CAACS,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,gBAAgB;AAAAF,IAAAA,QAAA,EAAGA;AAAQ,GAAA,CAA0B;AAC7F;AAEA;;;AAGG;SACaO,gBAAgBA,GAAA;AAC9B,EAAA,IAAMC,OAAO,GAAGC,UAAU,CAACb,aAAa,CAAC;EACzC,IAAI,CAACY,OAAO,EAAE;AACZ,IAAA,MAAM,IAAIE,KAAK,CAAC,uDAAuD,CAAC;AAC1E,EAAA;AACA,EAAA,OAAOF,OAAO;AAChB;AAEA;;;;AAIG;SACaG,wBAAwBA,GAAA;EACtC,OAAOF,UAAU,CAACb,aAAa,CAAC;AAClC;;;;"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { slicedToArray as _slicedToArray } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
+
import { MetaTrackManager } from '@livepeer-frameworks/player-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hook for subscribing to real-time metadata from MistServer
|
|
7
|
+
*
|
|
8
|
+
* Uses native MistServer WebSocket protocol for low-latency metadata delivery:
|
|
9
|
+
* - Subtitles/captions
|
|
10
|
+
* - Live scores
|
|
11
|
+
* - Timed events
|
|
12
|
+
* - Chapter markers
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const { isConnected, subscribe } = useMetaTrack({
|
|
17
|
+
* mistBaseUrl: 'https://mist.example.com',
|
|
18
|
+
* streamName: 'pk_...', // playbackId (view key)
|
|
19
|
+
* enabled: true,
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* useEffect(() => {
|
|
23
|
+
* if (!isConnected) return;
|
|
24
|
+
*
|
|
25
|
+
* const unsubscribe = subscribe('1', (event) => {
|
|
26
|
+
* if (event.type === 'subtitle') {
|
|
27
|
+
* setSubtitle(event.data as SubtitleCue);
|
|
28
|
+
* }
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* return unsubscribe;
|
|
32
|
+
* }, [isConnected, subscribe]);
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
function useMetaTrack(options) {
|
|
36
|
+
var mistBaseUrl = options.mistBaseUrl,
|
|
37
|
+
streamName = options.streamName,
|
|
38
|
+
initialSubscriptions = options.subscriptions,
|
|
39
|
+
_options$enabled = options.enabled,
|
|
40
|
+
enabled = _options$enabled === void 0 ? true : _options$enabled;
|
|
41
|
+
var _useState = useState(false),
|
|
42
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
43
|
+
isConnected = _useState2[0],
|
|
44
|
+
setIsConnected = _useState2[1];
|
|
45
|
+
var _useState3 = useState("disconnected"),
|
|
46
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
47
|
+
connectionState = _useState4[0],
|
|
48
|
+
setConnectionState = _useState4[1];
|
|
49
|
+
var _useState5 = useState([]),
|
|
50
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
51
|
+
subscribedTracks = _useState6[0],
|
|
52
|
+
setSubscribedTracks = _useState6[1];
|
|
53
|
+
var managerRef = useRef(null);
|
|
54
|
+
// Create manager instance
|
|
55
|
+
useEffect(function () {
|
|
56
|
+
if (!enabled || !mistBaseUrl || !streamName) {
|
|
57
|
+
if (managerRef.current) {
|
|
58
|
+
managerRef.current.disconnect();
|
|
59
|
+
managerRef.current = null;
|
|
60
|
+
}
|
|
61
|
+
setIsConnected(false);
|
|
62
|
+
setConnectionState("disconnected");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
managerRef.current = new MetaTrackManager({
|
|
66
|
+
mistBaseUrl: mistBaseUrl,
|
|
67
|
+
streamName: streamName,
|
|
68
|
+
subscriptions: initialSubscriptions,
|
|
69
|
+
debug: false
|
|
70
|
+
});
|
|
71
|
+
// Start polling connection state
|
|
72
|
+
var pollState = function pollState() {
|
|
73
|
+
if (managerRef.current) {
|
|
74
|
+
var state = managerRef.current.getState();
|
|
75
|
+
setConnectionState(state);
|
|
76
|
+
setIsConnected(state === "connected");
|
|
77
|
+
setSubscribedTracks(managerRef.current.getSubscribedTracks());
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
var pollInterval = setInterval(pollState, 500);
|
|
81
|
+
// Connect
|
|
82
|
+
managerRef.current.connect();
|
|
83
|
+
pollState();
|
|
84
|
+
return function () {
|
|
85
|
+
clearInterval(pollInterval);
|
|
86
|
+
if (managerRef.current) {
|
|
87
|
+
managerRef.current.disconnect();
|
|
88
|
+
managerRef.current = null;
|
|
89
|
+
}
|
|
90
|
+
setIsConnected(false);
|
|
91
|
+
setConnectionState("disconnected");
|
|
92
|
+
};
|
|
93
|
+
}, [enabled, mistBaseUrl, streamName, initialSubscriptions]);
|
|
94
|
+
/**
|
|
95
|
+
* Subscribe to a meta track
|
|
96
|
+
*/
|
|
97
|
+
var subscribe = useCallback(function (trackId, callback) {
|
|
98
|
+
if (!managerRef.current) {
|
|
99
|
+
return function () {};
|
|
100
|
+
}
|
|
101
|
+
var unsubscribe = managerRef.current.subscribe(trackId, callback);
|
|
102
|
+
setSubscribedTracks(managerRef.current.getSubscribedTracks());
|
|
103
|
+
return function () {
|
|
104
|
+
unsubscribe();
|
|
105
|
+
if (managerRef.current) {
|
|
106
|
+
setSubscribedTracks(managerRef.current.getSubscribedTracks());
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}, []);
|
|
110
|
+
/**
|
|
111
|
+
* Unsubscribe from a meta track
|
|
112
|
+
*/
|
|
113
|
+
var unsubscribe = useCallback(function (trackId, callback) {
|
|
114
|
+
if (managerRef.current) {
|
|
115
|
+
managerRef.current.unsubscribe(trackId, callback);
|
|
116
|
+
setSubscribedTracks(managerRef.current.getSubscribedTracks());
|
|
117
|
+
}
|
|
118
|
+
}, []);
|
|
119
|
+
/**
|
|
120
|
+
* Manually connect
|
|
121
|
+
*/
|
|
122
|
+
var connect = useCallback(function () {
|
|
123
|
+
var _managerRef$current;
|
|
124
|
+
(_managerRef$current = managerRef.current) === null || _managerRef$current === void 0 || _managerRef$current.connect();
|
|
125
|
+
}, []);
|
|
126
|
+
/**
|
|
127
|
+
* Manually disconnect
|
|
128
|
+
*/
|
|
129
|
+
var disconnect = useCallback(function () {
|
|
130
|
+
var _managerRef$current2;
|
|
131
|
+
(_managerRef$current2 = managerRef.current) === null || _managerRef$current2 === void 0 || _managerRef$current2.disconnect();
|
|
132
|
+
}, []);
|
|
133
|
+
/**
|
|
134
|
+
* Update playback time for timed event dispatch
|
|
135
|
+
* Call this on video timeupdate events to keep subtitle/chapter timing in sync
|
|
136
|
+
*/
|
|
137
|
+
var setPlaybackTime = useCallback(function (timeInSeconds) {
|
|
138
|
+
var _managerRef$current3;
|
|
139
|
+
(_managerRef$current3 = managerRef.current) === null || _managerRef$current3 === void 0 || _managerRef$current3.setPlaybackTime(timeInSeconds);
|
|
140
|
+
}, []);
|
|
141
|
+
/**
|
|
142
|
+
* Handle seek event - clears buffered events and resets state
|
|
143
|
+
* Call this on video seeking/seeked events
|
|
144
|
+
*/
|
|
145
|
+
var onSeek = useCallback(function (newTimeInSeconds) {
|
|
146
|
+
var _managerRef$current4;
|
|
147
|
+
(_managerRef$current4 = managerRef.current) === null || _managerRef$current4 === void 0 || _managerRef$current4.onSeek(newTimeInSeconds);
|
|
148
|
+
}, []);
|
|
149
|
+
return {
|
|
150
|
+
isConnected: isConnected,
|
|
151
|
+
connectionState: connectionState,
|
|
152
|
+
subscribedTracks: subscribedTracks,
|
|
153
|
+
subscribe: subscribe,
|
|
154
|
+
unsubscribe: unsubscribe,
|
|
155
|
+
connect: connect,
|
|
156
|
+
disconnect: disconnect,
|
|
157
|
+
setPlaybackTime: setPlaybackTime,
|
|
158
|
+
onSeek: onSeek
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { useMetaTrack };
|
|
163
|
+
//# sourceMappingURL=useMetaTrack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMetaTrack.js","sources":["../../../../src/hooks/useMetaTrack.ts"],"sourcesContent":["import { useEffect, useState, useRef, useCallback } from \"react\";\nimport { MetaTrackManager, type MetaTrackEvent } from \"@livepeer-frameworks/player-core\";\nimport type { UseMetaTrackOptions } from \"../types\";\n\nexport interface UseMetaTrackReturn {\n /** Whether connected to MistServer WebSocket */\n isConnected: boolean;\n /** Connection state */\n connectionState: \"disconnected\" | \"connecting\" | \"connected\" | \"reconnecting\";\n /** List of subscribed track IDs */\n subscribedTracks: string[];\n /** Subscribe to a meta track */\n subscribe: (trackId: string, callback: (event: MetaTrackEvent) => void) => () => void;\n /** Unsubscribe from a meta track */\n unsubscribe: (trackId: string, callback: (event: MetaTrackEvent) => void) => void;\n /** Manually connect */\n connect: () => void;\n /** Manually disconnect */\n disconnect: () => void;\n /** Update playback time for timed event dispatch (call on video timeupdate) */\n setPlaybackTime: (timeInSeconds: number) => void;\n /** Handle seek event (call on video seeking/seeked) */\n onSeek: (newTimeInSeconds: number) => void;\n}\n\n/**\n * Hook for subscribing to real-time metadata from MistServer\n *\n * Uses native MistServer WebSocket protocol for low-latency metadata delivery:\n * - Subtitles/captions\n * - Live scores\n * - Timed events\n * - Chapter markers\n *\n * @example\n * ```tsx\n * const { isConnected, subscribe } = useMetaTrack({\n * mistBaseUrl: 'https://mist.example.com',\n * streamName: 'pk_...', // playbackId (view key)\n * enabled: true,\n * });\n *\n * useEffect(() => {\n * if (!isConnected) return;\n *\n * const unsubscribe = subscribe('1', (event) => {\n * if (event.type === 'subtitle') {\n * setSubtitle(event.data as SubtitleCue);\n * }\n * });\n *\n * return unsubscribe;\n * }, [isConnected, subscribe]);\n * ```\n */\nexport function useMetaTrack(options: UseMetaTrackOptions): UseMetaTrackReturn {\n const { mistBaseUrl, streamName, subscriptions: initialSubscriptions, enabled = true } = options;\n\n const [isConnected, setIsConnected] = useState(false);\n const [connectionState, setConnectionState] = useState<\n \"disconnected\" | \"connecting\" | \"connected\" | \"reconnecting\"\n >(\"disconnected\");\n const [subscribedTracks, setSubscribedTracks] = useState<string[]>([]);\n const managerRef = useRef<MetaTrackManager | null>(null);\n\n // Create manager instance\n useEffect(() => {\n if (!enabled || !mistBaseUrl || !streamName) {\n if (managerRef.current) {\n managerRef.current.disconnect();\n managerRef.current = null;\n }\n setIsConnected(false);\n setConnectionState(\"disconnected\");\n return;\n }\n\n managerRef.current = new MetaTrackManager({\n mistBaseUrl,\n streamName,\n subscriptions: initialSubscriptions,\n debug: false,\n });\n\n // Start polling connection state\n const pollState = () => {\n if (managerRef.current) {\n const state = managerRef.current.getState();\n setConnectionState(state);\n setIsConnected(state === \"connected\");\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n };\n\n const pollInterval = setInterval(pollState, 500);\n\n // Connect\n managerRef.current.connect();\n pollState();\n\n return () => {\n clearInterval(pollInterval);\n if (managerRef.current) {\n managerRef.current.disconnect();\n managerRef.current = null;\n }\n setIsConnected(false);\n setConnectionState(\"disconnected\");\n };\n }, [enabled, mistBaseUrl, streamName, initialSubscriptions]);\n\n /**\n * Subscribe to a meta track\n */\n const subscribe = useCallback(\n (trackId: string, callback: (event: MetaTrackEvent) => void): (() => void) => {\n if (!managerRef.current) {\n return () => {};\n }\n\n const unsubscribe = managerRef.current.subscribe(trackId, callback);\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n\n return () => {\n unsubscribe();\n if (managerRef.current) {\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n };\n },\n []\n );\n\n /**\n * Unsubscribe from a meta track\n */\n const unsubscribe = useCallback((trackId: string, callback: (event: MetaTrackEvent) => void) => {\n if (managerRef.current) {\n managerRef.current.unsubscribe(trackId, callback);\n setSubscribedTracks(managerRef.current.getSubscribedTracks());\n }\n }, []);\n\n /**\n * Manually connect\n */\n const connect = useCallback(() => {\n managerRef.current?.connect();\n }, []);\n\n /**\n * Manually disconnect\n */\n const disconnect = useCallback(() => {\n managerRef.current?.disconnect();\n }, []);\n\n /**\n * Update playback time for timed event dispatch\n * Call this on video timeupdate events to keep subtitle/chapter timing in sync\n */\n const setPlaybackTime = useCallback((timeInSeconds: number) => {\n managerRef.current?.setPlaybackTime(timeInSeconds);\n }, []);\n\n /**\n * Handle seek event - clears buffered events and resets state\n * Call this on video seeking/seeked events\n */\n const onSeek = useCallback((newTimeInSeconds: number) => {\n managerRef.current?.onSeek(newTimeInSeconds);\n }, []);\n\n return {\n isConnected,\n connectionState,\n subscribedTracks,\n subscribe,\n unsubscribe,\n connect,\n disconnect,\n setPlaybackTime,\n onSeek,\n };\n}\n\nexport default useMetaTrack;\n"],"names":["useMetaTrack","options","mistBaseUrl","streamName","initialSubscriptions","subscriptions","_options$enabled","enabled","_useState","useState","_useState2","_slicedToArray","isConnected","setIsConnected","_useState3","_useState4","connectionState","setConnectionState","_useState5","_useState6","subscribedTracks","setSubscribedTracks","managerRef","useRef","useEffect","current","disconnect","MetaTrackManager","debug","pollState","state","getState","getSubscribedTracks","pollInterval","setInterval","connect","clearInterval","subscribe","useCallback","trackId","callback","unsubscribe","_managerRef$current","_managerRef$current2","setPlaybackTime","timeInSeconds","_managerRef$current3","onSeek","newTimeInSeconds","_managerRef$current4"],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { slicedToArray as _slicedToArray } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
+
import { QualityMonitor } from '@livepeer-frameworks/player-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hook to monitor video playback quality
|
|
7
|
+
*
|
|
8
|
+
* Tracks:
|
|
9
|
+
* - Buffer health (seconds ahead)
|
|
10
|
+
* - Stall count
|
|
11
|
+
* - Frame drop rate
|
|
12
|
+
* - Estimated bitrate
|
|
13
|
+
* - Latency (live streams)
|
|
14
|
+
* - Composite quality score (0-100)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const { quality, isMonitoring } = usePlaybackQuality({
|
|
19
|
+
* videoElement,
|
|
20
|
+
* enabled: true,
|
|
21
|
+
* thresholds: { minScore: 60 },
|
|
22
|
+
* onQualityDegraded: (q) => console.log('Quality dropped:', q.score),
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* return <div>Quality: {quality?.score ?? '--'}</div>;
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function usePlaybackQuality(options) {
|
|
29
|
+
var videoElement = options.videoElement,
|
|
30
|
+
_options$enabled = options.enabled,
|
|
31
|
+
enabled = _options$enabled === void 0 ? true : _options$enabled,
|
|
32
|
+
_options$sampleInterv = options.sampleInterval,
|
|
33
|
+
sampleInterval = _options$sampleInterv === void 0 ? 500 : _options$sampleInterv,
|
|
34
|
+
thresholds = options.thresholds,
|
|
35
|
+
onQualityDegraded = options.onQualityDegraded;
|
|
36
|
+
var _useState = useState(null),
|
|
37
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
38
|
+
quality = _useState2[0],
|
|
39
|
+
setQuality = _useState2[1];
|
|
40
|
+
var _useState3 = useState(false),
|
|
41
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
42
|
+
isMonitoring = _useState4[0],
|
|
43
|
+
setIsMonitoring = _useState4[1];
|
|
44
|
+
var monitorRef = useRef(null);
|
|
45
|
+
// Create/update monitor instance
|
|
46
|
+
useEffect(function () {
|
|
47
|
+
monitorRef.current = new QualityMonitor({
|
|
48
|
+
sampleInterval: sampleInterval,
|
|
49
|
+
thresholds: thresholds,
|
|
50
|
+
onQualityDegraded: onQualityDegraded,
|
|
51
|
+
onSample: setQuality
|
|
52
|
+
});
|
|
53
|
+
return function () {
|
|
54
|
+
var _monitorRef$current;
|
|
55
|
+
(_monitorRef$current = monitorRef.current) === null || _monitorRef$current === void 0 || _monitorRef$current.stop();
|
|
56
|
+
monitorRef.current = null;
|
|
57
|
+
};
|
|
58
|
+
}, [sampleInterval, thresholds, onQualityDegraded]);
|
|
59
|
+
// Start/stop monitoring based on videoElement and enabled state
|
|
60
|
+
useEffect(function () {
|
|
61
|
+
if (!enabled || !videoElement || !monitorRef.current) {
|
|
62
|
+
var _monitorRef$current2;
|
|
63
|
+
(_monitorRef$current2 = monitorRef.current) === null || _monitorRef$current2 === void 0 || _monitorRef$current2.stop();
|
|
64
|
+
setIsMonitoring(false);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
monitorRef.current.start(videoElement);
|
|
68
|
+
setIsMonitoring(true);
|
|
69
|
+
return function () {
|
|
70
|
+
var _monitorRef$current3;
|
|
71
|
+
(_monitorRef$current3 = monitorRef.current) === null || _monitorRef$current3 === void 0 || _monitorRef$current3.stop();
|
|
72
|
+
setIsMonitoring(false);
|
|
73
|
+
};
|
|
74
|
+
}, [videoElement, enabled]);
|
|
75
|
+
/**
|
|
76
|
+
* Get current quality snapshot
|
|
77
|
+
*/
|
|
78
|
+
var getCurrentQuality = useCallback(function () {
|
|
79
|
+
var _monitorRef$current$g, _monitorRef$current4;
|
|
80
|
+
return (_monitorRef$current$g = (_monitorRef$current4 = monitorRef.current) === null || _monitorRef$current4 === void 0 ? void 0 : _monitorRef$current4.getCurrentQuality()) !== null && _monitorRef$current$g !== void 0 ? _monitorRef$current$g : null;
|
|
81
|
+
}, []);
|
|
82
|
+
/**
|
|
83
|
+
* Get rolling average quality
|
|
84
|
+
*/
|
|
85
|
+
var getAverageQuality = useCallback(function () {
|
|
86
|
+
var _monitorRef$current$g2, _monitorRef$current5;
|
|
87
|
+
return (_monitorRef$current$g2 = (_monitorRef$current5 = monitorRef.current) === null || _monitorRef$current5 === void 0 ? void 0 : _monitorRef$current5.getAverageQuality()) !== null && _monitorRef$current$g2 !== void 0 ? _monitorRef$current$g2 : null;
|
|
88
|
+
}, []);
|
|
89
|
+
/**
|
|
90
|
+
* Get quality history
|
|
91
|
+
*/
|
|
92
|
+
var getHistory = useCallback(function () {
|
|
93
|
+
var _monitorRef$current$g3, _monitorRef$current6;
|
|
94
|
+
return (_monitorRef$current$g3 = (_monitorRef$current6 = monitorRef.current) === null || _monitorRef$current6 === void 0 ? void 0 : _monitorRef$current6.getHistory()) !== null && _monitorRef$current$g3 !== void 0 ? _monitorRef$current$g3 : [];
|
|
95
|
+
}, []);
|
|
96
|
+
/**
|
|
97
|
+
* Reset stall counters
|
|
98
|
+
*/
|
|
99
|
+
var resetStallCounters = useCallback(function () {
|
|
100
|
+
var _monitorRef$current7;
|
|
101
|
+
(_monitorRef$current7 = monitorRef.current) === null || _monitorRef$current7 === void 0 || _monitorRef$current7.resetStallCounters();
|
|
102
|
+
}, []);
|
|
103
|
+
/**
|
|
104
|
+
* Get total stall time
|
|
105
|
+
*/
|
|
106
|
+
var getTotalStallMs = useCallback(function () {
|
|
107
|
+
var _monitorRef$current$g4, _monitorRef$current8;
|
|
108
|
+
return (_monitorRef$current$g4 = (_monitorRef$current8 = monitorRef.current) === null || _monitorRef$current8 === void 0 ? void 0 : _monitorRef$current8.getTotalStallMs()) !== null && _monitorRef$current$g4 !== void 0 ? _monitorRef$current$g4 : 0;
|
|
109
|
+
}, []);
|
|
110
|
+
return {
|
|
111
|
+
/** Current quality metrics */
|
|
112
|
+
quality: quality,
|
|
113
|
+
/** Whether monitoring is active */
|
|
114
|
+
isMonitoring: isMonitoring,
|
|
115
|
+
/** Get current quality snapshot */
|
|
116
|
+
getCurrentQuality: getCurrentQuality,
|
|
117
|
+
/** Get rolling average quality */
|
|
118
|
+
getAverageQuality: getAverageQuality,
|
|
119
|
+
/** Get quality history */
|
|
120
|
+
getHistory: getHistory,
|
|
121
|
+
/** Reset stall counters */
|
|
122
|
+
resetStallCounters: resetStallCounters,
|
|
123
|
+
/** Get total stall time in ms */
|
|
124
|
+
getTotalStallMs: getTotalStallMs
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export { usePlaybackQuality };
|
|
129
|
+
//# sourceMappingURL=usePlaybackQuality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlaybackQuality.js","sources":["../../../../src/hooks/usePlaybackQuality.ts"],"sourcesContent":["import { useEffect, useState, useRef, useCallback } from \"react\";\nimport { QualityMonitor, type PlaybackQuality } from \"@livepeer-frameworks/player-core\";\nimport type { UsePlaybackQualityOptions } from \"../types\";\n\n/**\n * Hook to monitor video playback quality\n *\n * Tracks:\n * - Buffer health (seconds ahead)\n * - Stall count\n * - Frame drop rate\n * - Estimated bitrate\n * - Latency (live streams)\n * - Composite quality score (0-100)\n *\n * @example\n * ```tsx\n * const { quality, isMonitoring } = usePlaybackQuality({\n * videoElement,\n * enabled: true,\n * thresholds: { minScore: 60 },\n * onQualityDegraded: (q) => console.log('Quality dropped:', q.score),\n * });\n *\n * return <div>Quality: {quality?.score ?? '--'}</div>;\n * ```\n */\nexport function usePlaybackQuality(options: UsePlaybackQualityOptions) {\n const {\n videoElement,\n enabled = true,\n sampleInterval = 500,\n thresholds,\n onQualityDegraded,\n } = options;\n\n const [quality, setQuality] = useState<PlaybackQuality | null>(null);\n const [isMonitoring, setIsMonitoring] = useState(false);\n const monitorRef = useRef<QualityMonitor | null>(null);\n\n // Create/update monitor instance\n useEffect(() => {\n monitorRef.current = new QualityMonitor({\n sampleInterval,\n thresholds,\n onQualityDegraded,\n onSample: setQuality,\n });\n\n return () => {\n monitorRef.current?.stop();\n monitorRef.current = null;\n };\n }, [sampleInterval, thresholds, onQualityDegraded]);\n\n // Start/stop monitoring based on videoElement and enabled state\n useEffect(() => {\n if (!enabled || !videoElement || !monitorRef.current) {\n monitorRef.current?.stop();\n setIsMonitoring(false);\n return;\n }\n\n monitorRef.current.start(videoElement);\n setIsMonitoring(true);\n\n return () => {\n monitorRef.current?.stop();\n setIsMonitoring(false);\n };\n }, [videoElement, enabled]);\n\n /**\n * Get current quality snapshot\n */\n const getCurrentQuality = useCallback((): PlaybackQuality | null => {\n return monitorRef.current?.getCurrentQuality() ?? null;\n }, []);\n\n /**\n * Get rolling average quality\n */\n const getAverageQuality = useCallback((): PlaybackQuality | null => {\n return monitorRef.current?.getAverageQuality() ?? null;\n }, []);\n\n /**\n * Get quality history\n */\n const getHistory = useCallback((): PlaybackQuality[] => {\n return monitorRef.current?.getHistory() ?? [];\n }, []);\n\n /**\n * Reset stall counters\n */\n const resetStallCounters = useCallback(() => {\n monitorRef.current?.resetStallCounters();\n }, []);\n\n /**\n * Get total stall time\n */\n const getTotalStallMs = useCallback((): number => {\n return monitorRef.current?.getTotalStallMs() ?? 0;\n }, []);\n\n return {\n /** Current quality metrics */\n quality,\n /** Whether monitoring is active */\n isMonitoring,\n /** Get current quality snapshot */\n getCurrentQuality,\n /** Get rolling average quality */\n getAverageQuality,\n /** Get quality history */\n getHistory,\n /** Reset stall counters */\n resetStallCounters,\n /** Get total stall time in ms */\n getTotalStallMs,\n };\n}\n\nexport default usePlaybackQuality;\n"],"names":["usePlaybackQuality","options","videoElement","_options$enabled","enabled","_options$sampleInterv","sampleInterval","thresholds","onQualityDegraded","_useState","useState","_useState2","_slicedToArray","quality","setQuality","_useState3","_useState4","isMonitoring","setIsMonitoring","monitorRef","useRef","useEffect","current","QualityMonitor","onSample","_monitorRef$current","stop","_monitorRef$current2","start","_monitorRef$current3","getCurrentQuality","useCallback","_monitorRef$current$g","_monitorRef$current4","getAverageQuality","_monitorRef$current$g2","_monitorRef$current5","getHistory","_monitorRef$current$g3","_monitorRef$current6","resetStallCounters","_monitorRef$current7","getTotalStallMs","_monitorRef$current$g4","_monitorRef$current8"],"mappings":";;;;AAIA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACG,SAAUA,kBAAkBA,CAACC,OAAkC,EAAA;AACnE,EAAA,IACEC,YAAY,GAKVD,OAAO,CALTC,YAAY;IAAAC,gBAAA,GAKVF,OAAO,CAJTG,OAAO;AAAPA,IAAAA,OAAO,GAAAD,gBAAA,KAAA,MAAA,GAAG,IAAI,GAAAA,gBAAA;IAAAE,qBAAA,GAIZJ,OAAO,CAHTK,cAAc;AAAdA,IAAAA,cAAc,GAAAD,qBAAA,KAAA,MAAA,GAAG,GAAG,GAAAA,qBAAA;IACpBE,UAAU,GAERN,OAAO,CAFTM,UAAU;IACVC,iBAAiB,GACfP,OAAO,CADTO,iBAAiB;AAGnB,EAAA,IAAAC,SAAA,GAA8BC,QAAQ,CAAyB,IAAI,CAAC;IAAAC,UAAA,GAAAC,cAAA,CAAAH,SAAA,EAAA,CAAA,CAAA;AAA7DI,IAAAA,OAAO,GAAAF,UAAA,CAAA,CAAA,CAAA;AAAEG,IAAAA,UAAU,GAAAH,UAAA,CAAA,CAAA,CAAA;AAC1B,EAAA,IAAAI,UAAA,GAAwCL,QAAQ,CAAC,KAAK,CAAC;IAAAM,UAAA,GAAAJ,cAAA,CAAAG,UAAA,EAAA,CAAA,CAAA;AAAhDE,IAAAA,YAAY,GAAAD,UAAA,CAAA,CAAA,CAAA;AAAEE,IAAAA,eAAe,GAAAF,UAAA,CAAA,CAAA,CAAA;AACpC,EAAA,IAAMG,UAAU,GAAGC,MAAM,CAAwB,IAAI,CAAC;AAEtD;AACAC,EAAAA,SAAS,CAAC,YAAK;AACbF,IAAAA,UAAU,CAACG,OAAO,GAAG,IAAIC,cAAc,CAAC;AACtCjB,MAAAA,cAAc,EAAdA,cAAc;AACdC,MAAAA,UAAU,EAAVA,UAAU;AACVC,MAAAA,iBAAiB,EAAjBA,iBAAiB;AACjBgB,MAAAA,QAAQ,EAAEV;AACX,KAAA,CAAC;AAEF,IAAA,OAAO,YAAK;AAAA,MAAA,IAAAW,mBAAA;AACV,MAAA,CAAAA,mBAAA,GAAAN,UAAU,CAACG,OAAO,MAAA,IAAA,IAAAG,mBAAA,KAAA,MAAA,IAAlBA,mBAAA,CAAoBC,IAAI,EAAE;MAC1BP,UAAU,CAACG,OAAO,GAAG,IAAI;IAC3B,CAAC;EACH,CAAC,EAAE,CAAChB,cAAc,EAAEC,UAAU,EAAEC,iBAAiB,CAAC,CAAC;AAEnD;AACAa,EAAAA,SAAS,CAAC,YAAK;IACb,IAAI,CAACjB,OAAO,IAAI,CAACF,YAAY,IAAI,CAACiB,UAAU,CAACG,OAAO,EAAE;AAAA,MAAA,IAAAK,oBAAA;AACpD,MAAA,CAAAA,oBAAA,GAAAR,UAAU,CAACG,OAAO,MAAA,IAAA,IAAAK,oBAAA,KAAA,MAAA,IAAlBA,oBAAA,CAAoBD,IAAI,EAAE;MAC1BR,eAAe,CAAC,KAAK,CAAC;AACtB,MAAA;AACF,IAAA;AAEAC,IAAAA,UAAU,CAACG,OAAO,CAACM,KAAK,CAAC1B,YAAY,CAAC;IACtCgB,eAAe,CAAC,IAAI,CAAC;AAErB,IAAA,OAAO,YAAK;AAAA,MAAA,IAAAW,oBAAA;AACV,MAAA,CAAAA,oBAAA,GAAAV,UAAU,CAACG,OAAO,MAAA,IAAA,IAAAO,oBAAA,KAAA,MAAA,IAAlBA,oBAAA,CAAoBH,IAAI,EAAE;MAC1BR,eAAe,CAAC,KAAK,CAAC;IACxB,CAAC;AACH,EAAA,CAAC,EAAE,CAAChB,YAAY,EAAEE,OAAO,CAAC,CAAC;AAE3B;;AAEG;AACH,EAAA,IAAM0B,iBAAiB,GAAGC,WAAW,CAAC,YAA6B;IAAA,IAAAC,qBAAA,EAAAC,oBAAA;IACjE,OAAA,CAAAD,qBAAA,IAAAC,oBAAA,GAAOd,UAAU,CAACG,OAAO,cAAAW,oBAAA,KAAA,MAAA,GAAA,MAAA,GAAlBA,oBAAA,CAAoBH,iBAAiB,EAAE,MAAA,IAAA,IAAAE,qBAAA,KAAA,MAAA,GAAAA,qBAAA,GAAI,IAAI;EACxD,CAAC,EAAE,EAAE,CAAC;AAEN;;AAEG;AACH,EAAA,IAAME,iBAAiB,GAAGH,WAAW,CAAC,YAA6B;IAAA,IAAAI,sBAAA,EAAAC,oBAAA;IACjE,OAAA,CAAAD,sBAAA,IAAAC,oBAAA,GAAOjB,UAAU,CAACG,OAAO,cAAAc,oBAAA,KAAA,MAAA,GAAA,MAAA,GAAlBA,oBAAA,CAAoBF,iBAAiB,EAAE,MAAA,IAAA,IAAAC,sBAAA,KAAA,MAAA,GAAAA,sBAAA,GAAI,IAAI;EACxD,CAAC,EAAE,EAAE,CAAC;AAEN;;AAEG;AACH,EAAA,IAAME,UAAU,GAAGN,WAAW,CAAC,YAAwB;IAAA,IAAAO,sBAAA,EAAAC,oBAAA;IACrD,OAAA,CAAAD,sBAAA,IAAAC,oBAAA,GAAOpB,UAAU,CAACG,OAAO,cAAAiB,oBAAA,KAAA,MAAA,GAAA,MAAA,GAAlBA,oBAAA,CAAoBF,UAAU,EAAE,MAAA,IAAA,IAAAC,sBAAA,KAAA,MAAA,GAAAA,sBAAA,GAAI,EAAE;EAC/C,CAAC,EAAE,EAAE,CAAC;AAEN;;AAEG;AACH,EAAA,IAAME,kBAAkB,GAAGT,WAAW,CAAC,YAAK;AAAA,IAAA,IAAAU,oBAAA;AAC1C,IAAA,CAAAA,oBAAA,GAAAtB,UAAU,CAACG,OAAO,MAAA,IAAA,IAAAmB,oBAAA,KAAA,MAAA,IAAlBA,oBAAA,CAAoBD,kBAAkB,EAAE;EAC1C,CAAC,EAAE,EAAE,CAAC;AAEN;;AAEG;AACH,EAAA,IAAME,eAAe,GAAGX,WAAW,CAAC,YAAa;IAAA,IAAAY,sBAAA,EAAAC,oBAAA;IAC/C,OAAA,CAAAD,sBAAA,IAAAC,oBAAA,GAAOzB,UAAU,CAACG,OAAO,cAAAsB,oBAAA,KAAA,MAAA,GAAA,MAAA,GAAlBA,oBAAA,CAAoBF,eAAe,EAAE,MAAA,IAAA,IAAAC,sBAAA,KAAA,MAAA,GAAAA,sBAAA,GAAI,CAAC;EACnD,CAAC,EAAE,EAAE,CAAC;EAEN,OAAO;AACL;AACA9B,IAAAA,OAAO,EAAPA,OAAO;AACP;AACAI,IAAAA,YAAY,EAAZA,YAAY;AACZ;AACAa,IAAAA,iBAAiB,EAAjBA,iBAAiB;AACjB;AACAI,IAAAA,iBAAiB,EAAjBA,iBAAiB;AACjB;AACAG,IAAAA,UAAU,EAAVA,UAAU;AACV;AACAG,IAAAA,kBAAkB,EAAlBA,kBAAkB;AAClB;AACAE,IAAAA,eAAe,EAAfA;GACD;AACH;;;;"}
|