srs/trunk/research/players/homepage.html
Jason-JP-Yang d887d2b867 Addition Features: Custom Homepage and WHEP player
1. DVR record apply support regex, for usage: please enter
    config file -dvr_apply and start regex with /^xxx$/
2. Add custom homepage for player, enter the url
    localhost:8080/players/homepage.html to access
3. Add WHEP player, enter the url localhost:8080/players/whep_itp.html
4. Convert Files Format from CRLF to LF (Windows to Linux)

* Known Issues:
1. There is a unsmooth swup between hompage and player page, Swup.js
    will be used to fix this issue in the future.
2025-05-13 23:35:28 +08:00

330 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NPL ITP Intranet Livestream Channel</title>
<link rel="stylesheet" type="text/css" href="css/homepage_main.css" />
<script type="text/javascript" src="js/anime.js"></script>
<script type="text/javascript" src="js/jquery-1.12.2.min.js"></script>
<script type="text/javascript" src="js/adapter-7.4.0.min.js"></script>
<script type="text/javascript" src="js/srs.sdk.js"></script>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<script type="text/javascript" src="js/srs.page.js"></script>
</head>
<body>
<div class="preloader">
<h2 class="ml13 ml13-1">NPL ITP</h2>
<h2 class="ml13 ml13-2">Intranet Livestream Channel</h2>
<h3 id="status">Connecting to the SRS Server ...</h3>
<div id="loader">Loading...</div>
</div>
<style>
/*=============== PRELOADER STYLE ===============*/
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300..700&display=swap');
:root {
/*========== Colors ==========*/
/*Color mode HSL(hue, saturation, lightness)*/
--background-color: rgb(255, 255, 255);
--preloader-background-color: rgb(255, 255, 255);
--preloader-text-color: hsl(210, 30%, 10%);
--secondary-color: hsl(0, 0%, 65%);
/*========== Font and typography ==========*/
/*.5rem = 8px | 1rem = 16px ...*/
--body-font: "Quicksand", sans-serif;
--second-font: Serif;
--h3-font-size: 1rem;
/*========== z index ==========*/
--z-tooltip: 10;
--z-fixed: 100;
}
@media (max-width: 650px) {
.ml13 {
font-size: 3.3rem !important;
/* Adjust this value as needed */
}
}
@media (max-width: 410px) {
.ml13 {
font-size: 2.2rem !important;
/* Adjust this value as needed */
}
}
@media (max-width: 310px) {
.ml13 {
font-size: 1.5rem !important;
/* Adjust this value as needed */
}
}
.preloader {
display: flex;
flex-direction: column;
/* Tailwind 'gap-4' is 1rem */
align-items: center;
justify-content: center;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100vw;
height: 100vh;
/* 'h-screen' is 100% of the viewport height */
background-color: var(--preloader-background-color);
z-index: 1100;
/* 'z-[1100]' sets the z-index */
transform: translateY(0);
margin: 0;
padding: 0;
}
#preload_logo {
width: 90%;
margin-bottom: -2rem;
/* Tailwind 'mb-4' is 1rem */
}
.ml13 {
font-size: 5rem;
/* text-transform: uppercase; */
color: var(--preloader-text-color);
letter-spacing: -1px;
font-weight: 1000;
font-family: var(--second-font);
text-align: center;
margin: 0;
}
.ml13 .word {
display: inline-flex;
flex-wrap: wrap;
white-space: nowrap;
}
.ml13 .letter {
display: inline-block;
line-height: 1em;
}
.preloader #status {
font-size: 2.2rem;
color: var(--secondary-color);
font-family: var(--body-font);
font-weight: 400;
text-align: center;
margin-top: 3rem;
/* Tailwind 'mt-8' is 2rem */
}
#loader {
width: 250px;
height: 50px;
line-height: 50px;
text-align: center;
position: absolute;
bottom: 5%;
left: 50%;
transform: translate(-50%, -50%);
font-family: helvetica, arial, sans-serif;
font-size: 1rem;
text-transform: uppercase;
font-weight: 900;
color: var(--preloader-text-color);
letter-spacing: 0.2em;
&::before,
&::after {
content: "";
display: block;
width: 15px;
height: 15px;
background: var(--preloader-text-color);
position: absolute;
animation: load 0.7s infinite alternate ease-in-out;
}
&::before {
top: 0;
}
&::after {
bottom: 0;
}
}
@keyframes load {
0% {
left: 0;
height: 30px;
width: 15px;
}
50% {
height: 8px;
width: 40px;
}
100% {
left: 235px;
height: 30px;
width: 15px;
}
}
</style>
<script>
/*=============== PRELOADER ANIMATION ===============*/
for (i = 1; i <= 2; i++) {
var textWrapper = document.querySelector('.ml13.ml13-' + i);
console.log(textWrapper);
// Split text into words
var words = textWrapper.textContent.trim().split(' ');
// Clear the existing content
textWrapper.innerHTML = '';
// Wrap each word and its letters in spans
words.forEach(function (word) {
var wordSpan = document.createElement('span');
wordSpan.classList.add('word');
wordSpan.innerHTML = word.replace(/\S/g, "<span class='letter'>$&</span>");
textWrapper.appendChild(wordSpan);
textWrapper.appendChild(document.createTextNode(' ')); // Add space between words
});
}
var animation = anime.timeline({ loop: true })
.add({
targets: '.ml13 .letter',
translateY: [40, 0],
translateZ: 0,
opacity: [0, 1],
filter: ['blur(5px)', 'blur(0px)'], // Starting from blurred to unblurred
easing: "easeOutExpo",
duration: 1400,
delay: (el, i) => 300 + 30 * i,
}).add({
targets: '.ml13 .letter',
translateY: [0, -40],
opacity: [1, 0],
filter: ['blur(0px)', 'blur(5px)'], // Ending from unblurred to blurred
easing: "easeInExpo",
duration: 1200,
delay: (el, i) => 100 + 30 * i,
changeComplete: onLoopComplete
});
countdownEnd = false;
refeshHtml = false;
function onLoopComplete() {
if (countdownEnd) {
if (refeshHtml) {
// Emit an event to notify that the preloader is hidden
const event = new Event('preloaderHidden');
document.dispatchEvent(event);
} else {
hidePreloader(); // Call hidePreloader after the animation completes
animation.pause();
}
}
}
function showPreloader() {
countdownEnd = false;
var preloader = document.querySelector('.preloader');
// 重置preloader位置和透明度
preloader.style.transform = 'translateY(100%)';
preloader.style.opacity = '1';
preloader.style.display = 'flex';
// 从下至上动画
anime({
targets: preloader,
translateY: ['100%', '0%'],
duration: 2000,
easing: 'easeOutExpo',
complete: function () {
// 动画完成后开始循环动画
animation.play();
}
});
document.body.style.overflowY = 'hidden';
}
function hidePreloader() {
var preloader = document.querySelector('.preloader');
anime({
targets: preloader,
translateY: ['0%', '100%'],
duration: 2000,
easing: 'easeOutExpo',
complete: function () {
preloader.style.display = 'none'; // Hide the preloader after animation
}
});
}
</script>
<nav>
<div class="logo">
<div class="logo-box">
<img src="./img/school_logo.png" alt="Logo">
</div>
<span>NPL ITP Intranet Channel</span>
</div>
<button class="nav-button">首页</button>
</nav>
<main>
<div class="hero-section">
<h1>内联网人人都可以用的超低延迟直播服务</h1>
<p class="subtitle">借助SRS服务和WebRTC连接协议随时观看直播</p>
<div class="join-container">
<div class="code-box">
<input type="text" id="code-input" required="required">
<span id="code-span">Enter the Stream Code</span>
</div>
<button class="join-button">Enter</button>
</div>
</div>
</main>
<script>
document.querySelector('.join-button').addEventListener('click', function () {
var url = "whep_itp.html?vhost=__defaultVhost__&app=live&server=localhost&port=8080&autostart=true&schema=http&stream=" + document.querySelector('#code-input').value;
console.log(url)
showPreloader();
history.pushState({}, '', url);
fetch(url)
.then(response => response.text())
.then(html => {
// 添加离开动画
countdownEnd = true;
refeshHtml = true;
document.addEventListener('preloaderHidden', function () {
window.location.href = url;
});
});
});
window.addEventListener('load', function () {
countdownEnd = true;
});
</script>
</body>
</html>