@kkcompany/player 2.25.0-canary.23 → 2.25.0-canary.25

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.
@@ -0,0 +1,120 @@
1
+ import { a as load, c as setPlaybackRate, d as syncPlaybackState, f as syncTextTrack, o as seek, s as setAudioTrack, t as getMediaTime, u as subscribePlaybackState } from "./mediaBindings-CoY60lQw.mjs";
2
+ import { t as loadPlayer_default } from "./loadPlayer-CQdGA3Te.mjs";
3
+ import { n as selectVideoResolution } from "./adaptation-BcTsh-wx.mjs";
4
+ import { useEffect, useLayoutEffect, useRef, useState } from "react";
5
+ import { jsx } from "@emotion/react/jsx-runtime";
6
+
7
+ //#region src/util/multiRef.js
8
+ const multiRef = (...refs) => (element) => {
9
+ if (element) refs.forEach((ref) => {
10
+ if (ref && "current" in ref) ref.current = element;
11
+ else ref?.(element);
12
+ });
13
+ };
14
+ var multiRef_default = multiRef;
15
+
16
+ //#endregion
17
+ //#region src/Video.js
18
+ const baseVideoStyle = {
19
+ objectFit: "contain",
20
+ width: "100%",
21
+ maxHeight: "100%",
22
+ "&:fullscreen": {
23
+ position: "absolute",
24
+ top: 0,
25
+ left: 0,
26
+ bottom: 0,
27
+ right: 0
28
+ },
29
+ "~ .shaka-text-container": {
30
+ position: "absolute",
31
+ height: "100%",
32
+ width: "100%"
33
+ }
34
+ };
35
+ const emptyArray = [];
36
+ const Video = ({ source, playbackState: targetState, currentTime: targetTime, playbackRate, videoResolution, audioTrack = {}, textTracks = emptyArray, textTrack, liveResume, iOSFullscreenDetectThreshold, plugins = [], shaka, bitmovin, license, validationHost, videoRef, playerRef, onPlayerLoaded, onPlaybackStateChange, onBlockedAutoplay, onPlaylogFired, ...videoAttributes }) => {
37
+ const handlers = useRef();
38
+ handlers.current = {
39
+ onPlaybackStateChange,
40
+ onBlockedAutoplay
41
+ };
42
+ const videoContainer = useRef();
43
+ const videoElement = useRef();
44
+ const [playbackState, setPlaybackState] = useState("");
45
+ const [player, setPlayer] = useState();
46
+ useEffect(() => {
47
+ const loadTask = loadPlayer_default(videoElement.current, {
48
+ container: videoContainer.current,
49
+ source,
50
+ shaka,
51
+ bitmovin
52
+ }).then((basePlayer) => {
53
+ setPlayer(basePlayer);
54
+ onPlayerLoaded?.(basePlayer);
55
+ if (playerRef) playerRef.curret = basePlayer;
56
+ return basePlayer;
57
+ });
58
+ const offPlaybackState = subscribePlaybackState(videoElement.current, (event, state) => {
59
+ handlers.current.onPlaybackStateChange?.(event, state);
60
+ requestAnimationFrame(() => setPlaybackState(state));
61
+ }, { iOSFullscreenDetectThreshold });
62
+ return () => {
63
+ offPlaybackState();
64
+ loadTask.then((currentPlayer) => currentPlayer?.destroy());
65
+ };
66
+ }, []);
67
+ useEffect(() => {
68
+ if (source && (source.length > 0 || source.src || source.hls || source.dash) && player?.isAlive()) Promise.resolve(false).then(() => load(videoElement.current, {
69
+ player,
70
+ plugins,
71
+ startTime: targetTime
72
+ }, source)).catch((error) => console.warn(error));
73
+ if ((!source || source.length === 0) && player) {
74
+ player.unload();
75
+ player.lastSrc = "";
76
+ }
77
+ }, [player, source]);
78
+ useLayoutEffect(() => {
79
+ if (player?.isAlive()) syncPlaybackState(videoElement.current, {
80
+ player,
81
+ plugins,
82
+ liveResume
83
+ }, targetState)?.catch((error) => {
84
+ handlers.current.onBlockedAutoplay?.(error);
85
+ });
86
+ }, [player && targetState]);
87
+ useEffect(() => {
88
+ const { currentTime } = getMediaTime(videoElement.current, {
89
+ player,
90
+ plugins
91
+ });
92
+ if (player?.isAlive() && Math.abs(currentTime - targetTime) > .5) seek(videoElement.current, {
93
+ player,
94
+ plugins
95
+ }, targetTime);
96
+ }, [player && targetTime]);
97
+ useEffect(() => {
98
+ setPlaybackRate(videoElement.current, { player }, playbackRate);
99
+ }, [playbackRate, playbackState === "playing"]);
100
+ useEffect(() => {
101
+ if (player) selectVideoResolution(videoElement.current, { player }, videoResolution);
102
+ }, [videoResolution, player]);
103
+ useEffect(() => setAudioTrack(videoElement.current, { player }, audioTrack), [videoElement.current?.readyState >= 2 && audioTrack.label, audioTrack.language]);
104
+ useEffect(() => {
105
+ if (textTracks?.length > 0 || textTrack) return syncTextTrack(videoElement.current, { player }, textTracks?.length > 0 ? { textTracks } : textTrack);
106
+ }, [videoElement.current?.readyState >= 2 && textTracks, textTrack]);
107
+ return /* @__PURE__ */ jsx("div", {
108
+ ref: videoContainer,
109
+ css: { video: baseVideoStyle },
110
+ children: /* @__PURE__ */ jsx("video", {
111
+ ref: multiRef_default(videoRef, videoElement),
112
+ playsInline: true,
113
+ ...videoAttributes
114
+ })
115
+ });
116
+ };
117
+ var Video_default = Video;
118
+
119
+ //#endregion
120
+ export { multiRef_default as n, Video_default as t };
@@ -0,0 +1,74 @@
1
+ import { h as mimeTypes, m as getSource, x as isSafari } from "./mediaBindings-CoY60lQw.mjs";
2
+
3
+ //#region src/util/net.js
4
+ const timeoutError = () => /* @__PURE__ */ new Error("request timeout");
5
+ /**
6
+ * @param {URL|RequestInfo} url
7
+ * @param {RequestInit} options
8
+ * @param {{responseType: 'json'|'text'}}
9
+ */
10
+ const retryRequest = (url, options = {}, { responseType = "json", timeout = 6, retryTimes = 6 } = {}) => new Promise((resolve, reject) => {
11
+ setTimeout(() => reject(timeoutError()), timeout * 1e3);
12
+ fetch(url, options).then((response) => resolve(response[responseType]?.() || response)).catch(reject);
13
+ }).catch((error) => {
14
+ console.log(error);
15
+ if (retryTimes > 0) return retryRequest(url, options, {
16
+ timeout,
17
+ retryTimes: retryTimes - 1
18
+ });
19
+ return error;
20
+ });
21
+
22
+ //#endregion
23
+ //#region src/playerCore/adaptation.js
24
+ const matchAll = (input, pattern) => {
25
+ const flags = [
26
+ pattern.global && "g",
27
+ pattern.ignoreCase && "i",
28
+ pattern.multiline && "m"
29
+ ].filter(Boolean).join("");
30
+ const clone = new RegExp(pattern, flags);
31
+ return Array.from((function* () {
32
+ let matched = true;
33
+ while (1) {
34
+ matched = clone.exec(input);
35
+ if (!matched) return;
36
+ yield matched;
37
+ }
38
+ })());
39
+ };
40
+ const rewriteUrls = (manifest, sourceUrl) => manifest.replace(/((#EXT-X-MEDIA:.*URI=")([^"]*))|((#EXT-X-STREAM-INF.*\n)(.*)(?=\n))/g, (...matches) => [
41
+ matches[2],
42
+ matches[5],
43
+ new URL(matches[3] || matches[6], sourceUrl)
44
+ ].filter(Boolean).join(""));
45
+ const filterHlsManifestQualities = (originalManifest, filter) => {
46
+ if (!filter) return;
47
+ const manifest = `${originalManifest}\n`;
48
+ const profiles = matchAll(manifest, /RESOLUTION=(\d+)x(\d+)/g).map(([, width, height]) => ({
49
+ width: +width,
50
+ height: +height
51
+ }));
52
+ const allowed = filter(profiles) || profiles;
53
+ const newManifest = manifest.replace(/#EXT-X-STREAM-INF.*RESOLUTION=(\d+)x(\d+).*\n.*\n/g, (item, width, height) => allowed.some((p) => p.width === +width && p.height === +height) ? item : "");
54
+ return newManifest !== manifest && newManifest;
55
+ };
56
+ const meetRestriction = (quality, { minHeight, maxHeight } = {}) => !(quality.height < minHeight || quality.height > maxHeight);
57
+ const selectHlsQualities = async (source, restrictions = {}) => {
58
+ if (!isSafari() || !(restrictions.minHeight || restrictions.maxHeight)) return source;
59
+ const selected = getSource(source, { preferManifestType: "hls" });
60
+ if (!(selected?.type.toLowerCase() === mimeTypes.hls)) return source;
61
+ const filtered = filterHlsManifestQualities(await retryRequest(selected.src, {}, { responseType: "text" }), (items) => items.filter((item) => meetRestriction(item, restrictions)));
62
+ if (filtered) return {
63
+ ...selected,
64
+ src: `data:application/x-mpegURL,${encodeURI(rewriteUrls(filtered, selected.src))}`
65
+ };
66
+ return source;
67
+ };
68
+ const selectVideoResolution = (_media, { player }, restrictions) => {
69
+ player.preferredSettings.videoResolution = restrictions;
70
+ player.configure("abr.restrictions", restrictions);
71
+ };
72
+
73
+ //#endregion
74
+ export { selectVideoResolution as n, selectHlsQualities as t };