130 lines
4.1 KiB
HTML
130 lines
4.1 KiB
HTML
<!DOCTYPE html><html><head>
|
|
<meta name="og:title" content="Quest VRChat Video Server" />
|
|
<meta name="og:description" content="Import YouTube videos and get short link for Quest VRChat" />
|
|
<title>Quest VRChat Video Server</title>
|
|
<style>
|
|
|
|
#url_input {
|
|
width: 320px;
|
|
}
|
|
#alias_input {
|
|
width: 64px;
|
|
}
|
|
|
|
#server_output {
|
|
max-height: 160px;
|
|
white-space: pre;
|
|
overflow-y: scroll;
|
|
font-family: monospace;
|
|
border: 1px gray solid;
|
|
padding: 3px;
|
|
}
|
|
|
|
table, th, td {
|
|
border: 1px black solid;
|
|
border-collapse: collapse;
|
|
padding: 3px;
|
|
}
|
|
|
|
</style>
|
|
</head><body>
|
|
<h1>Quest VRChat Video Server</h1>
|
|
<div>Import YouTube videos onto this server to...</div>
|
|
<ul>
|
|
<li>Make the videos work for your friends on Quest (allow untrusted URLs)</li>
|
|
<li><b>NEW:</b> Get memorable short URLs that you can type in Quest!</li>
|
|
</ul>
|
|
<p>
|
|
<div>Just paste a YouTube video URL here: <input id="url_input" type="text" placeholder="https://www.youtube.com/watch?v=dQw4w9WgXcQ" /></label></div>
|
|
<div>and optionally type a short memorable alias for it: <input id="alias_input" type="text" placeholder="rick" maxlength="32" /></div>
|
|
<div>and click <input id="submit_button" type="submit" />!</div>
|
|
</p>
|
|
<p id="server_output"></p>
|
|
<p><b>NEW:</b> Watch YouTube on Quest WITHOUT PC friends or memorized URLs with <a href="https://www.u2b.cx/">u2b.cx</a>!</p>
|
|
|
|
<script>
|
|
var url_input = document.getElementById("url_input");
|
|
var alias_input = document.getElementById("alias_input");
|
|
var submit_button = document.getElementById("submit_button");
|
|
var server_output = document.getElementById("server_output");
|
|
submit_button.onclick = function() {
|
|
url_input.disabled = true;
|
|
alias_input.disabled = true;
|
|
submit_button.disabled = true;
|
|
server_output.innerText = '';
|
|
var ws = new WebSocket(`${location.protocol.replace('http','ws')}//${location.host}/w?url=${encodeURIComponent(url_input.value)}&alias=${encodeURIComponent(alias_input.value)}`);
|
|
function print(html) {
|
|
server_output.innerHTML += html + '\n';
|
|
server_output.scrollTop = server_output.scrollHeight;
|
|
}
|
|
ws.onerror = function (event) {
|
|
print(`<span style="color: red">WebSocket connection failed</span>`);
|
|
};
|
|
ws.onmessage = function (evt) {
|
|
console.log(evt.data)
|
|
print(evt.data);
|
|
};
|
|
ws.onclose = function () {
|
|
url_input.value = "";
|
|
alias_input.value = "";
|
|
url_input.disabled = false;
|
|
alias_input.disabled = false;
|
|
submit_button.disabled = false;
|
|
loadList();
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<h2>Videos</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Short links</th>
|
|
<th></th>
|
|
<th>File name</th>
|
|
<th>Duration</th>
|
|
<th>Size</th>
|
|
<th>Date added</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="tbody">
|
|
</tbody>
|
|
|
|
</table>
|
|
<script>
|
|
var tbody = document.getElementById("tbody");
|
|
|
|
function loadList() {
|
|
fetch("/api/list").then(res => res.json()).then(list => {
|
|
tbody.innerHTML = '';
|
|
list.forEach((file, index) => {
|
|
var url = `${location.origin}/v/${encodeURIComponent(file.name)}`;
|
|
var row = tbody.insertRow(0);
|
|
row.insertCell().innerText = [index, ...file.aliases||[]].map(x => `${location.origin}/${x}`).join('\n');
|
|
row.insertCell().innerHTML = `<button title="Copy URL" onclick="navigator.clipboard.writeText('${url}')">📋</button>`;
|
|
row.insertCell().innerHTML = `<a href="${url}">${file.name}</a>`;
|
|
row.insertCell().innerHTML = `<span title="${file.duration} seconds">${formatDuration(file.duration)}</span>`;
|
|
row.insertCell().innerHTML = `<span title="${file.size} bytes">${formatBytes(file.size)}</span>`
|
|
row.insertCell().innerHTML = `<span title="${file.mtime}">${new Date(file.mtime).toLocaleString()}</span>`;
|
|
});
|
|
});
|
|
}
|
|
|
|
loadList();
|
|
|
|
function formatDuration(seconds) {
|
|
var d = new Date(0);
|
|
d.setSeconds(seconds);
|
|
var hms = d.toISOString().substring(11, 19);
|
|
if (hms.startsWith("00:")) hms = hms.substring(3);
|
|
return hms;
|
|
}
|
|
|
|
function formatBytes(bytes) {
|
|
if (bytes == 0) return "0 B";
|
|
var e = Math.floor(Math.log(bytes) / Math.log(1000));
|
|
return (bytes / Math.pow(1000, e)).toFixed(2) + ' ' + ' KMGTP'.charAt(e) + 'B';
|
|
}
|
|
|
|
</script>
|
|
</body></html> |