diff --git a/p2p-media-loader-demo/.eslintrc.cjs b/p2p-media-loader-demo/.eslintrc.cjs
index ff95cbca..688f40c4 100644
--- a/p2p-media-loader-demo/.eslintrc.cjs
+++ b/p2p-media-loader-demo/.eslintrc.cjs
@@ -1,17 +1,18 @@
module.exports = {
- env: {es2020: true},
- extends: ["../.eslintrc.common.cjs", "plugin:react-hooks/recommended"],
- parser: "@typescript-eslint/parser",
- parserOptions: {
- ecmaVersion: "latest",
- sourceType: "module",
- project: "tsconfig.json",
- tsconfigRootDir: __dirname,
- },
- plugins: ["react-refresh"],
- rules: {
- "react-refresh/only-export-components": "warn",
- "@typescript-eslint/ban-ts-comment": 0,
- "react-hooks/exhaustive-deps": 0
- },
+ env: {es2020: true},
+ extends: ["../.eslintrc.common.cjs", "plugin:react-hooks/recommended"],
+ parser: "@typescript-eslint/parser",
+ parserOptions: {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ project: "tsconfig.json",
+ tsconfigRootDir: __dirname,
+ },
+ plugins: ["react-refresh"],
+ rules: {
+ "react-refresh/only-export-components": "warn",
+ "@typescript-eslint/ban-ts-comment": 0,
+ "react-hooks/exhaustive-deps": 0,
+ "@typescript-eslint/no-explicit-any": 0
+ },
};
diff --git a/p2p-media-loader-demo/index.html b/p2p-media-loader-demo/index.html
index 7e6449b6..fccca772 100644
--- a/p2p-media-loader-demo/index.html
+++ b/p2p-media-loader-demo/index.html
@@ -1,12 +1,16 @@
-
-
-
+
+
+
Vite + React + TS
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/p2p-media-loader-demo/package.json b/p2p-media-loader-demo/package.json
index 94839827..7c5730b0 100644
--- a/p2p-media-loader-demo/package.json
+++ b/p2p-media-loader-demo/package.json
@@ -18,8 +18,7 @@
"p2p-media-loader-hlsjs": "workspace:*",
"p2p-media-loader-shaka": "workspace:*",
"react": "^18.2.0",
- "react-dom": "^18.2.0",
- "shaka-player": "^4.3.7"
+ "react-dom": "^18.2.0"
},
"devDependencies": {
"@types/dplayer": "^1.25.2",
diff --git a/p2p-media-loader-demo/src/App.tsx b/p2p-media-loader-demo/src/App.tsx
index 18b3c620..5603ce7b 100644
--- a/p2p-media-loader-demo/src/App.tsx
+++ b/p2p-media-loader-demo/src/App.tsx
@@ -3,56 +3,56 @@ import { Engine as HlsJsEngine } from "p2p-media-loader-hlsjs";
import { Engine as ShakaEngine } from "p2p-media-loader-shaka";
import Hls from "hls.js";
import DPlayer from "dplayer";
-import shakaLib from "shaka-player";
import muxjs from "mux.js";
import debug from "debug";
window.muxjs = muxjs;
-
const players = [
"hlsjs",
"hls-dplayer",
+ "hls-clappr",
"shaka-dplayer",
"shaka-player",
+ "shaka-clappr",
] as const;
type Player = (typeof players)[number];
type ShakaPlayer = shaka.Player;
type ExtendedWindow = Window & { videoPlayer?: { destroy?: () => void } };
-const streamUrl = {
- bigBunnyBuck: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
- byteRangeVideo:
+const streamUrls = {
+ hlsBigBunnyBuck: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
+ hlsByteRangeVideo:
"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8",
- live: "https://fcc3ddae59ed.us-west-2.playback.live-video.net/api/video/v1/us-west-2.893648527354.channel.DmumNckWFTqz.m3u8",
- advancedVideo:
+ hlsAdvancedVideo:
"https://devstreaming-cdn.apple.com/videos/streaming/examples/adv_dv_atmos/main.m3u8",
- advancedVideo2:
+ hlsAdvancedVideo2:
"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8",
- advancedVideo3:
+ hlsAdvancedVideo3:
"https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/master.m3u8",
- advancedVideo4:
+ hlsAdvancedVideo4:
"https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8",
- basicExample:
+ hlsBasicExample:
"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8",
- bigBunnyBuckDash: "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd",
- live2: "https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8",
+ hlsLive1:
+ "https://fcc3ddae59ed.us-west-2.playback.live-video.net/api/video/v1/us-west-2.893648527354.channel.DmumNckWFTqz.m3u8",
+ hlsLive2:
+ "https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8",
live2OnlyLevel4:
"https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/level_4.m3u8",
- dashLiveWithSeparateVideoAudio:
- "https://livesim.dashif.org/livesim/testpic_2s/Manifest.mpd",
- mss: "https://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest",
audioOnly:
"https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/a1/prog_index.m3u8",
- dash1:
- "http://dash.akamaized.net/dash264/TestCases/1a/qualcomm/1/MultiRate.mpd",
- dash2: "http://dash.akamaized.net/dash264/TestCases/5b/nomor/6.mpd",
+ bigBunnyBuckDash: "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd",
+ dashLiveBigBunnyBuck:
+ "https://livesim.dashif.org/livesim/testpic_2s/Manifest.mpd",
+ dashVODBigBunnyBuck:
+ "https://dash.akamaized.net/dash264/TestCases/5b/nomor/6.mpd",
};
function App() {
const [playerType, setPlayerType] = useState(
localStorage.player
);
- const [url, setUrl] = useState(localStorage.streamUrl);
+ const [streamUrl, setStreamUrl] = useState(localStorage.streamUrl);
const shakaInstance = useRef();
const hlsInstance = useRef();
const containerRef = useRef(null);
@@ -91,7 +91,8 @@ function App() {
}
if (!shakaEngine.current) {
- shakaEngine.current = new ShakaEngine(shakaLib, { onSegmentLoaded });
+ ShakaEngine.setGlobalSettings();
+ shakaEngine.current = new ShakaEngine(window.shaka, { onSegmentLoaded });
}
useEffect(() => {
@@ -106,10 +107,9 @@ function App() {
setPlayerType("hls-dplayer");
}
if (!localStorage.streamUrl) {
- localStorage.streamUrl = streamUrl.live2;
- setUrl(streamUrl.live2);
+ localStorage.streamUrl = streamUrls.hlsLive2;
+ setStreamUrl(streamUrls.hlsLive2);
}
-
createNewPlayer();
}, [playerType]);
@@ -117,9 +117,68 @@ function App() {
(window as unknown as ExtendedWindow).videoPlayer = player;
};
- const initShakaDPlayer = (url: string) => {
+ const initHlsJsPlayer = (url: string) => {
+ if (!videoRef.current) return;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const engine = shakaEngine.current!;
+ const engine = hlsEngine.current!;
+ const hls = new Hls({
+ ...engine.getConfig(),
+ });
+ engine.setHls(hls);
+ hls.attachMedia(videoRef.current);
+ hls.loadSource(url);
+ hlsInstance.current = hls;
+ setPlayerToWindow(hls);
+ };
+
+ const initHlsDPlayer = (url: string) => {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const engine = hlsEngine.current!;
+ const player = new DPlayer({
+ container: containerRef.current,
+ video: {
+ url,
+ type: "customHls",
+ customType: {
+ customHls: (video: HTMLVideoElement) => {
+ const hls = new Hls({
+ ...engine.getConfig(),
+ liveSyncDurationCount: 7,
+ });
+ engine.setHls(hls);
+ hls.loadSource(video.src);
+ hls.attachMedia(video);
+ hlsInstance.current = hls;
+ },
+ },
+ },
+ });
+ player.play();
+ setPlayerToWindow(player);
+ };
+
+ const initHlsClapprPlayer = (url: string) => {
+ const engine = hlsEngine.current;
+ if (!engine) return;
+
+ const clapprPlayer: any = new window.Clappr.Player({
+ parentId: "#player-container",
+ source: url,
+ playback: {
+ hlsjsConfig: {
+ ...engine.getConfig(),
+ },
+ },
+ plugins: [window.LevelSelector],
+ });
+ engine.initClapprPlayer(clapprPlayer);
+ setPlayerToWindow(clapprPlayer);
+ };
+
+ const initShakaDPlayer = (url: string) => {
+ const engine = shakaEngine.current;
+ if (!engine) return;
+
const player = new DPlayer({
container: containerRef.current,
video: {
@@ -129,7 +188,8 @@ function App() {
customHlsOrDash: (video: HTMLVideoElement) => {
video.autoplay = true;
const src = video.src;
- const shakaPlayer = new shakaLib.Player(video);
+ const shakaPlayer = new window.shaka.Player();
+ shakaPlayer.attach(video);
const onError = (error: { code: number }) => {
// eslint-disable-next-line no-console
console.error("Error code", error.toString(), "object", error);
@@ -149,11 +209,10 @@ function App() {
};
const initShakaPlayer = (url: string) => {
- if (!videoRef.current) return;
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const engine = shakaEngine.current!;
+ const engine = shakaEngine.current;
+ if (!videoRef.current || !engine) return;
- const player = new shakaLib.Player(videoRef.current);
+ const player = new window.shaka.Player(videoRef.current);
const onError = (error: { code: unknown }) => {
// eslint-disable-next-line no-console
console.error("Error code", error.code, "object", error);
@@ -167,44 +226,19 @@ function App() {
setPlayerToWindow(player);
};
- const initHlsJsPlayer = (url: string) => {
- if (!videoRef.current) return;
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const engine = hlsEngine.current!;
- const hls = new Hls({
- ...engine.getConfig(),
- });
- engine.initHlsJsEvents(hls);
- hls.attachMedia(videoRef.current);
- hls.loadSource(url);
- hlsInstance.current = hls;
- setPlayerToWindow(hls);
- };
+ const initShakaClapprPlayer = (url: string) => {
+ const engine = shakaEngine.current;
+ if (!engine) return;
- const initHlsDPlayer = (url: string) => {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const engine = hlsEngine.current!;
- const player = new DPlayer({
- container: containerRef.current,
- video: {
- url,
- type: "customHls",
- customType: {
- customHls: (video: HTMLVideoElement) => {
- const hls = new Hls({
- ...engine.getConfig(),
- liveSyncDurationCount: 7,
- });
- engine.initHlsJsEvents(hls);
- hls.loadSource(video.src);
- hls.attachMedia(video);
- hlsInstance.current = hls;
- },
- },
+ const clapprPlayer = new window.Clappr.Player({
+ parentId: "#player-container",
+ source: url,
+ plugins: [window.DashShakaPlayback, window.LevelSelector],
+ shakaOnBeforeLoad: (shakaPlayerInstance: any) => {
+ engine.initShakaPlayer(shakaPlayerInstance);
},
});
- player.play();
- setPlayerToWindow(player);
+ setPlayerToWindow(clapprPlayer);
};
const destroyAndWindowPlayer = () => {
@@ -219,26 +253,36 @@ function App() {
destroyAndWindowPlayer();
};
- const onVideoUrlChange = (url: string) => {
- localStorage.streamUrl = url;
- setUrl(url);
+ const onVideoUrlChange = (streamUrl: string) => {
+ localStorage.streamUrl = streamUrl;
+ setStreamUrl(streamUrl);
};
const createNewPlayer = () => {
setHttpLoadedGlob(0);
setP2PLoadedGlob(0);
+
+ (window as unknown as ExtendedWindow).videoPlayer?.destroy?.();
+ hlsInstance.current?.destroy();
+ void shakaInstance.current?.destroy();
switch (playerType) {
case "hls-dplayer":
- initHlsDPlayer(url);
+ initHlsDPlayer(streamUrl);
break;
case "hlsjs":
- initHlsJsPlayer(url);
+ initHlsJsPlayer(streamUrl);
+ break;
+ case "hls-clappr":
+ initHlsClapprPlayer(streamUrl);
break;
case "shaka-dplayer":
- initShakaDPlayer(url);
+ initShakaDPlayer(streamUrl);
break;
case "shaka-player":
- initShakaPlayer(url);
+ initShakaPlayer(streamUrl);
+ break;
+ case "shaka-clappr":
+ initShakaClapprPlayer(streamUrl);
break;
}
};
@@ -247,11 +291,13 @@ function App() {
switch (playerType) {
case "hls-dplayer":
case "hlsjs":
- hlsInstance.current?.loadSource(url);
+ case "hls-clappr":
+ hlsInstance.current?.loadSource(streamUrl);
break;
case "shaka-player":
case "shaka-dplayer":
- shakaInstance.current?.load(url).catch(() => undefined);
+ case "shaka-clappr":
+ shakaInstance.current?.load(streamUrl).catch(() => undefined);
break;
}
};
@@ -277,10 +323,10 @@ function App() {
})}