-
Notifications
You must be signed in to change notification settings - Fork 12
/
PlayerViewer.js
153 lines (143 loc) · 6.28 KB
/
PlayerViewer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { useEffect, useMemo, useRef, useState } from "react";
import Lottie from "lottie-react";
import animationData from "../../../static/animations/wait_for_HLS_animation.json";
import stoppedHLSSnimationData from "../../../static/animations/stopped_HLS_animation.json";
import Hls from "hls.js";
import useIsMobile from "../../../hooks/useIsMobile";
import useIsTab from "../../../hooks/useIsTab";
import { useMediaQuery } from "react-responsive";
import { useMeetingAppContext } from "../../../MeetingAppContextDef";
import { Constants, useMeeting } from "@videosdk.live/react-sdk";
export async function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
const PlayerViewer = () => {
const { afterMeetingJoinedHLSState } = useMeetingAppContext();
const { hlsUrls, hlsState } = useMeeting();
const playerRef = useRef();
const isMobile = useIsMobile();
const isTab = useIsTab();
const isLGDesktop = useMediaQuery({ minWidth: 1024, maxWidth: 1439 });
const isXLDesktop = useMediaQuery({ minWidth: 1440 });
const playHls = useMemo(() => {
return (
hlsUrls.playbackHlsUrl &&
(hlsState == Constants.hlsEvents.HLS_PLAYABLE ||
hlsState == Constants.hlsEvents.HLS_STOPPING)
);
}, [hlsUrls, hlsState]);
const lottieSize = isMobile
? 180
: isTab
? 180
: isLGDesktop
? 240
: isXLDesktop
? 240
: 160;
useEffect(() => {
if (playHls) {
if (Hls.isSupported()) {
const hls = new Hls({
maxLoadingDelay: 1, // max video loading delay used in automatic start level selection
defaultAudioCodec: "mp4a.40.2", // default audio codec
maxBufferLength: 0, // If buffer length is/become less than this value, a new fragment will be loaded
maxMaxBufferLength: 1, // Hls.js will never exceed this value
startLevel: 0, // Start playback at the lowest quality level
startPosition: -1, // set -1 playback will start from intialtime = 0
maxBufferHole: 0.001, // 'Maximum' inter-fragment buffer hole tolerance that hls.js can cope with when searching for the next fragment to load.
highBufferWatchdogPeriod: 0, // if media element is expected to play and if currentTime has not moved for more than highBufferWatchdogPeriod and if there are more than maxBufferHole seconds buffered upfront, hls.js will jump buffer gaps, or try to nudge playhead to recover playback.
nudgeOffset: 0.05, // In case playback continues to stall after first playhead nudging, currentTime will be nudged evenmore following nudgeOffset to try to restore playback. media.currentTime += (nb nudge retry -1)*nudgeOffset
nudgeMaxRetry: 1, // Max nb of nudge retries before hls.js raise a fatal BUFFER_STALLED_ERROR
maxFragLookUpTolerance: 0.1, // This tolerance factor is used during fragment lookup.
liveSyncDurationCount: 1, // if set to 3, playback will start from fragment N-3, N being the last fragment of the live playlist
abrEwmaFastLive: 1, // Fast bitrate Exponential moving average half-life, used to compute average bitrate for Live streams.
abrEwmaSlowLive: 3, // Slow bitrate Exponential moving average half-life, used to compute average bitrate for Live streams.
abrEwmaFastVoD: 1, // Fast bitrate Exponential moving average half-life, used to compute average bitrate for VoD streams
abrEwmaSlowVoD: 3, // Slow bitrate Exponential moving average half-life, used to compute average bitrate for VoD streams
maxStarvationDelay: 1, // ABR algorithm will always try to choose a quality level that should avoid rebuffering
});
let player = document.querySelector("#hlsPlayer");
hls.loadSource(hlsUrls.playbackHlsUrl);
hls.attachMedia(player);
hls.on(Hls.Events.MANIFEST_PARSED, function () {});
hls.on(Hls.Events.ERROR, function (err) {
console.log(err);
});
} else {
if (typeof playerRef.current?.play === "function") {
playerRef.current.src = hlsUrls.playbackHlsUrl;
playerRef.current.play();
}
// console.error("HLS is not supported");
}
}
}, [playHls]);
return (
<div
className={`h-full w-full ${
playHls ? "bg-gray-800" : "bg-gray-750"
} relative overflow-hidden rounded-lg`}
>
{playHls ? (
<div className="flex flex-col items-center justify-center absolute top-0 left-0 bottom-0 right-0">
<video
ref={playerRef}
id="hlsPlayer"
autoPlay={true}
controls
style={{ width: "100%", height: "100%" }}
playsinline
playsInline
muted={true}
playing
onError={(err) => {
console.log(err, "hls video error");
}}
></video>
</div>
) : (
<div className="flex h-full w-full items-center justify-center">
<div className="flex flex-col items-center justify-center absolute top-0 left-0 bottom-0 right-0">
<div
style={{
height: lottieSize,
width: lottieSize,
}}
>
<Lottie
animationData={
afterMeetingJoinedHLSState === "STOPPED"
? stoppedHLSSnimationData
: animationData
}
rendererSettings={{
preserveAspectRatio: "xMidYMid slice",
}}
loop={afterMeetingJoinedHLSState === "STOPPED" ? false : true}
autoPlay={true}
style={{
height: "100%",
width: "100%",
}}
/>
</div>
<p className="text-white text-center font-semibold text-2xl mt-0">
{afterMeetingJoinedHLSState === "STOPPED"
? "Host has stopped the live streaming."
: "Waiting for host to start live stream."}
</p>
{afterMeetingJoinedHLSState !== "STOPPED" && (
<p className="text-white text-center font-semibold text-2xl">
Meanwhile, take a few deep breaths.
</p>
)}
</div>
</div>
)}
</div>
);
};
export default PlayerViewer;