Files
okiiparty/index.html
2025-09-13 11:16:34 +05:30

141 lines
3.5 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Okiiparty</title>
<link href="https://vjs.zencdn.net/8.23.3/video-js.css" rel="stylesheet" />
<style>
* {padding:0; margin: 0}
body {background: black}
video {
width: 100%;
height: 100%;
object-fit: content;
}
.banner {
padding: 1rem;
margin: 1rem;
outline: .1rem solid #fefefe;
border-radius: 1rem;
backdrop-filter: blur(10px) brightness(60%);
box-sizing: border-box;
color: #eee;
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 4;
font-family: monospace;
font-size: 1rem;
abbr {
text-decoration: none;
}
}
.video-js {
position: revert;
width: 100%;
height: 100%;
font-size: 1.5rem;
}
.hide {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
</style>
</head>
<body>
<div class="banner">
<abbr title="Okiiparty - Made with ❤️ for pookie">
The stream is muted because autoplay requires audio to be switched off. Please unmute the stream and I will disappear.
</abbr>
</div>
<video
id="video"
class="video-js"
controls
preload="auto"
muted
data-setup="{}"
>
<source src="/stream/stream.m3u8" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script src="https://vjs.zencdn.net/8.23.3/video.min.js"></script>
<script>
const loc = window.location;
let proto = loc.protocol == "https:" ? "wss:" : "ws:";
let host = loc.host;
const video = videojs("video");
let wsUri = `${proto}//${host}/broker`;
const socket = new WebSocket(wsUri);
const banner = document.querySelector(".banner");
let requestedWait = false
const broadcast = message => socket.send(JSON.stringify(message));
const broadcastSeek = () => broadcast({ action: "seek", time: video.currentTime() })
const broadcastPlay = () => broadcast({action: "play"});
const broadcastPause = () => broadcast({action: "pause"});
// Oneshot block for event propagatation
function stepOverEvent(eventType, listener, stepFunction) {
video.off(eventType, listener)
stepFunction(video)
video.on(eventType, () => { video.on(eventType, listener) })
}
socket.addEventListener("message", (event) => {
let message = JSON.parse(event.data)
if (message.action == "play") { stepOverEvent("play", broadcastPlay, video => { video.play() }) }
if (message.action == "pause") { stepOverEvent("pause", broadcastPause, video => { video.pause() }) }
if (message.action == "seek") { stepOverEvent("seeked", broadcastSeek, video => { video.currentTime(message.time) }) }
if (message.action == "wait") {
if (!video.paused()) { video.pause() }
video.controls(false)
}
if (message.action == "canplay") { video.controls(true) }
})
video.on("play", broadcastPlay)
video.on("pause", broadcastPause)
video.on("seeked", broadcastSeek)
video.on("waiting", () => {
requestedWait = true
broadcast({action: "wait"})
video.controls(false)
})
video.on("canplay", () => {
if (!requestedWait) { return }
broadcast({action: "canplay"})
video.controls(true)
requestedWait = false
})
video.on("volumechange", () => {
banner.classList.add('hide');
})
</script>
</body>
</html>