Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clappr player. #316

Merged
merged 18 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions p2p-media-loader-demo/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -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},
i-zolotarenko marked this conversation as resolved.
Show resolved Hide resolved
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
},
};
20 changes: 12 additions & 8 deletions p2p-media-loader-demo/index.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/clappr@latest"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/clappr/clappr-level-selector-plugin@latest/dist/level-selector.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/shaka-player.compiled.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/clappr/dash-shaka-playback@latest/dist/dash-shaka-playback.external.js"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
3 changes: 1 addition & 2 deletions p2p-media-loader-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
196 changes: 118 additions & 78 deletions p2p-media-loader-demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<Player | undefined>(
localStorage.player
);
const [url, setUrl] = useState<string>(localStorage.streamUrl);
const [streamUrl, setStreamUrl] = useState<string>(localStorage.streamUrl);
const shakaInstance = useRef<shaka.Player>();
const hlsInstance = useRef<Hls>();
const containerRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -91,7 +91,7 @@ function App() {
}

if (!shakaEngine.current) {
shakaEngine.current = new ShakaEngine(shakaLib, { onSegmentLoaded });
shakaEngine.current = new ShakaEngine(window.shaka, { onSegmentLoaded });
}

useEffect(() => {
Expand All @@ -106,20 +106,79 @@ function App() {
setPlayerType("hls-dplayer");
}
if (!localStorage.streamUrl) {
localStorage.streamUrl = streamUrl.live2;
setUrl(streamUrl.live2);
localStorage.streamUrl = streamUrls.hlsLive2;
setStreamUrl(streamUrls.hlsLive2);
}

createNewPlayer();
}, [playerType]);

const setPlayerToWindow = (player: DPlayer | ShakaPlayer | Hls) => {
(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 = hlsEngine.current!;
const hls = new Hls({
...engine.getConfig(),
});
engine.initHlsJsEvents(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 = shakaEngine.current!;
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;
},
},
},
});
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(
() => clapprPlayer.core.getCurrentPlayback()?._hls
),
},
},
plugins: [window.LevelSelector],
});
setPlayerToWindow(clapprPlayer);
};

const initShakaDPlayer = (url: string) => {
const engine = shakaEngine.current;
if (!engine) return;

const player = new DPlayer({
container: containerRef.current,
video: {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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 = () => {
Expand All @@ -219,26 +253,32 @@ 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);
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;
}
};
Expand All @@ -247,11 +287,11 @@ function App() {
switch (playerType) {
case "hls-dplayer":
case "hlsjs":
hlsInstance.current?.loadSource(url);
hlsInstance.current?.loadSource(streamUrl);
break;
case "shaka-player":
case "shaka-dplayer":
shakaInstance.current?.load(url).catch(() => undefined);
shakaInstance.current?.load(streamUrl).catch(() => undefined);
break;
}
};
Expand All @@ -277,10 +317,10 @@ function App() {
})}
</select>
<select
value={url}
value={streamUrl}
onChange={(event) => onVideoUrlChange(event.target.value)}
>
{Object.entries(streamUrl).map(([name, url]) => {
{Object.entries(streamUrls).map(([name, url]) => {
return (
<option key={name} value={url}>
{name}
Expand All @@ -299,7 +339,7 @@ function App() {
ref={containerRef}
id="player-container"
style={{ width: 1000 }}
></div>
/>
</div>
{!!playerType && ["hlsjs", "shaka-player"].includes(playerType) && (
<video ref={videoRef} controls muted style={{ width: 800 }} />
Expand Down
1 change: 1 addition & 0 deletions p2p-media-loader-demo/src/declarations.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
declare module "mux.js";
declare module "shaka-player";
declare module "@clappr/player";
Loading