upd
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
/* eslint-disable no-empty */
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@@ -6,16 +8,17 @@ import {
|
||||
Config,
|
||||
AllSettings,
|
||||
PixelStreaming,
|
||||
LatencyTestResults,
|
||||
} from "@epicgames-ps/lib-pixelstreamingfrontend-ue5.3";
|
||||
import { Trans } from "react-i18next";
|
||||
import LoaderIcon from "./icons/LoaderIcon";
|
||||
|
||||
export interface PixelStreamingWrapperProps {
|
||||
initialSettings?: Partial<AllSettings>;
|
||||
onVideoInitialized?: () => void;
|
||||
}
|
||||
|
||||
export const PixelStreamingWrapper = ({
|
||||
initialSettings,
|
||||
onVideoInitialized,
|
||||
}: PixelStreamingWrapperProps) => {
|
||||
// A reference to parent div element that the Pixel Streaming library attaches into:
|
||||
const videoParent = useRef<HTMLDivElement>(null);
|
||||
@@ -24,10 +27,10 @@ export const PixelStreamingWrapper = ({
|
||||
const [pixelStreaming, setPixelStreaming] = useState<PixelStreaming>();
|
||||
|
||||
// A boolean state variable that determines if the Click to play overlay is shown:
|
||||
const [clickToPlayVisible, setClickToPlayVisible] = useState<boolean>(false);
|
||||
const [videoInitialized, setVideoInitialized] = useState<boolean>(false);
|
||||
const videoInitializedRef = useRef<boolean>();
|
||||
videoInitializedRef.current = videoInitialized;
|
||||
const [clickToPlayVisible, setClickToPlayVisible] = useState(false);
|
||||
|
||||
const [latencyTestResult, setLatencyTestResult] =
|
||||
useState<LatencyTestResults>();
|
||||
|
||||
// Run on component mount:
|
||||
useEffect(() => {
|
||||
@@ -38,132 +41,93 @@ export const PixelStreamingWrapper = ({
|
||||
videoElementParent: videoParent.current,
|
||||
});
|
||||
|
||||
streaming.addEventListener("videoInitialized", () => {
|
||||
setVideoInitialized(true);
|
||||
});
|
||||
|
||||
// register a playStreamRejected handler to show Click to play overlay if needed:
|
||||
streaming.addEventListener("playStreamRejected", () => {
|
||||
setClickToPlayVisible(true);
|
||||
});
|
||||
|
||||
streaming.addEventListener("videoInitialized", () => {
|
||||
onVideoInitialized && onVideoInitialized();
|
||||
});
|
||||
|
||||
streaming.addEventListener("latencyTestResult", (e) => {
|
||||
setLatencyTestResult(e.data.latencyTimings);
|
||||
// console.log("Data", e.data.latencyTimings);
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
streaming.requestLatencyTest();
|
||||
}, 500);
|
||||
|
||||
// Save the library instance into component state so that it can be accessed later:
|
||||
setPixelStreaming(streaming);
|
||||
|
||||
document.getElementById("hiddenInput")?.remove();
|
||||
document.getElementById("editTextButton")?.remove();
|
||||
|
||||
setTimeout(() => {
|
||||
if (!videoInitializedRef.current) {
|
||||
window.location.reload();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
// Clean up on component unmount:
|
||||
return () => {
|
||||
try {
|
||||
streaming.disconnect();
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative w-screen h-screen">
|
||||
<div className="w-full h-[100svh]" ref={videoParent} />
|
||||
{!videoInitialized && (
|
||||
<div className="absolute top-0 left-0 w-full h-full flex justify-center items-center gap-4">
|
||||
<LoaderIcon className="animate-spin w-8 h-8" />
|
||||
<Trans i18nKey="streamBuffering">Буферизация потока</Trans>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
ref={videoParent}
|
||||
/>
|
||||
{clickToPlayVisible && (
|
||||
<div className="absolute top-0 left-0 w-full h-full flex justify-center items-center z-10 bg-[#131317]">
|
||||
<div className="flex flex-col justify-center items-center w-[400px] p-10 space-y-10 rounded-lg">
|
||||
<div className="space-y-4 text-center">
|
||||
<p className="text-4xl font-gilroy">
|
||||
<Trans i18nKey="demoStarted">Демонстрация начата</Trans>
|
||||
</p>
|
||||
<p className="text-[#C5C7CE]">
|
||||
<Trans i18nKey="clickToContinue">
|
||||
Нажмите, чтобы продолжить
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
pixelStreaming?.play();
|
||||
setClickToPlayVisible(false);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
width="88"
|
||||
height="88"
|
||||
viewBox="0 0 88 88"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g filter="url(#filter0_b_0_1121)">
|
||||
<path
|
||||
d="M55.6667 43.9999L34.6668 57.9999L34.6668 30L55.6667 43.9999Z"
|
||||
fill="#F2F2F2"
|
||||
stroke="#F2F2F2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<rect
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
width="87"
|
||||
height="87"
|
||||
rx="43.5"
|
||||
stroke="url(#paint0_linear_0_1121)"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter
|
||||
id="filter0_b_0_1121"
|
||||
x="-20"
|
||||
y="-20"
|
||||
width="128"
|
||||
height="128"
|
||||
filterUnits="userSpaceOnUse"
|
||||
colorInterpolationFilters="sRGB"
|
||||
>
|
||||
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
||||
<feGaussianBlur in="BackgroundImageFix" stdDeviation="10" />
|
||||
<feComposite
|
||||
in2="SourceAlpha"
|
||||
operator="in"
|
||||
result="effect1_backgroundBlur_0_1121"
|
||||
/>
|
||||
<feBlend
|
||||
mode="normal"
|
||||
in="SourceGraphic"
|
||||
in2="effect1_backgroundBlur_0_1121"
|
||||
result="shape"
|
||||
/>
|
||||
</filter>
|
||||
<linearGradient
|
||||
id="paint0_linear_0_1121"
|
||||
x1="88"
|
||||
y1="-2.6226e-06"
|
||||
x2="2.6226e-06"
|
||||
y2="88"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#BC75FF" />
|
||||
<stop offset="1" stopColor="#798FFF" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
color: "#fff",
|
||||
}}
|
||||
onClick={() => {
|
||||
pixelStreaming?.play();
|
||||
setClickToPlayVisible(false);
|
||||
}}
|
||||
>
|
||||
<div>Click to play</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="absolute bottom-0 left-0 p-4 text-white text-xs bg-black">
|
||||
{latencyTestResult &&
|
||||
Object.entries(latencyTestResult).map(([key, value], i) => {
|
||||
if (
|
||||
[
|
||||
"EncodeMs",
|
||||
"CaptureToSendMs",
|
||||
"latencyExcludingDecode",
|
||||
"networkLatency",
|
||||
"testStartTimeMs",
|
||||
].includes(key)
|
||||
)
|
||||
return (
|
||||
<div key={i}>
|
||||
{key}: {value}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user