@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.
- package/CHANGELOG.md +4 -0
- package/dist/StallReload-BFlQRphx.mjs +717 -0
- package/dist/Video-CMbK-cxg.mjs +120 -0
- package/dist/adaptation-BcTsh-wx.mjs +74 -0
- package/dist/api-2BOrEA5d.mjs +1057 -0
- package/dist/debugUtil-IF7p5TSI.mjs +23 -0
- package/dist/events-B3vI3Srm.mjs +16 -0
- package/dist/fixDashManifest-CJ63KKaA.mjs +56 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +3 -10148
- package/dist/loadPlayer-CQdGA3Te.mjs +1560 -0
- package/dist/loadScript-Ct19kU9g.mjs +13 -0
- package/dist/mediaBindings-CoY60lQw.mjs +542 -0
- package/dist/modules.d.mts +51 -0
- package/dist/modules.mjs +631 -2201
- package/dist/playerCore/index.d.mts +3 -0
- package/dist/playerCore/index.mjs +4 -0
- package/dist/plugins/index.d.mts +2 -0
- package/dist/plugins/index.mjs +3 -0
- package/dist/reactEntry.d.mts +20 -0
- package/dist/reactEntry.mjs +6339 -0
- package/dist/util-B2YBSBjR.mjs +29 -0
- package/package.json +24 -19
- package/dist/core.mjs +0 -3075
- package/dist/index.d.ts +0 -18
- package/dist/index.js +0 -20938
- package/dist/modules.d.ts +0 -89
- package/dist/plugins.d.ts +0 -5
- package/dist/plugins.mjs +0 -1105
- package/dist/react.d.ts +0 -178
- package/dist/react.mjs +0 -13061
|
@@ -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 };
|