yt backend
This commit is contained in:
parent
e9e798ebae
commit
bfc7956f8c
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
metadata
|
||||
videos
|
||||
videos
|
||||
videos.json
|
8
getvideos.py
Normal file
8
getvideos.py
Normal file
@ -0,0 +1,8 @@
|
||||
from yt_dlp import YoutubeDL
|
||||
from json import dump
|
||||
|
||||
with YoutubeDL() as ydl:
|
||||
info = ydl.extract_info("ytsearch500:mmd", download=False, process=False)
|
||||
info["entries"] = list(info["entries"])
|
||||
with open("videos.json", "w") as f:
|
||||
dump(info, f)
|
56
index.js
56
index.js
@ -2,7 +2,6 @@ var express = require("express");
|
||||
require("express-async-errors");
|
||||
var morgan = require("morgan");
|
||||
var fs = require("fs/promises");
|
||||
var getVideoLength = v => require('video-length')(v, {bin: "mediainfo"});
|
||||
|
||||
var app = module.exports.app = express();
|
||||
app.set("env", process.env.NODE_ENV || "production");
|
||||
@ -11,8 +10,6 @@ module.exports.server = app.listen(process.env.PORT || 8080, process.env.ADDR);
|
||||
|
||||
app.use(morgan(`:date[iso] :remote-addr :method :url ":req[user-agent]" :referrer`));
|
||||
|
||||
app.use("/videos/", express.static("videos"));
|
||||
|
||||
app.get("/playlist", async (req, res) => {
|
||||
res.send(await getPlaylist());
|
||||
});
|
||||
@ -35,22 +32,12 @@ async function getPlaylist() {
|
||||
}
|
||||
|
||||
async function generatePlaylist() {
|
||||
var videofiles = await fs.readdir("videos");
|
||||
|
||||
var videos = [];
|
||||
|
||||
for (let name of videofiles) {
|
||||
let metadata = await getMetadata(name);
|
||||
if (!metadata.duration) {
|
||||
console.warn("missing duration:", name);
|
||||
continue;
|
||||
};
|
||||
videos.push({
|
||||
name,
|
||||
duration: metadata.duration,
|
||||
source: metadata.source || inferSource(name)
|
||||
});
|
||||
}
|
||||
var videos = JSON.parse(await fs.readFile("videos.json", "utf8")).entries;
|
||||
videos = videos.map(v => ({
|
||||
id: v.id,
|
||||
duration: v.duration,
|
||||
title: v.title
|
||||
}));
|
||||
|
||||
shuffle(videos);
|
||||
|
||||
@ -61,37 +48,6 @@ async function generatePlaylist() {
|
||||
}
|
||||
}
|
||||
|
||||
async function getMetadata(video) {
|
||||
var videopath = `videos/${video}`;
|
||||
var metadatapath = `metadata/${video}.json`;
|
||||
try {
|
||||
var metadata = JSON.parse(await fs.readFile(metadatapath, "utf8"));
|
||||
} catch (error) {
|
||||
var metadata = {
|
||||
duration: null
|
||||
};
|
||||
try {
|
||||
metadata.duration = await getVideoLength(videopath);
|
||||
} catch(error) {
|
||||
console.error("get video length:", error.message);
|
||||
};
|
||||
await fs.writeFile(metadatapath, JSON.stringify(metadata));
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
function inferSource(name) {
|
||||
var youtube_id = name.match(/\[([A-Za-z0-9_-]{11})\]/);
|
||||
if (youtube_id)
|
||||
return `https://www.youtube.com/watch?v=${youtube_id[1]}`;
|
||||
|
||||
var niconico_id = name.match(/\[(sm\d+)\]/);
|
||||
if (niconico_id)
|
||||
return `https://www.nicovideo.jp/watch/${niconico_id[1]}`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function shuffle(array) {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
|
11
package-lock.json
generated
11
package-lock.json
generated
@ -8,7 +8,6 @@
|
||||
"express": "^4.18.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"morgan": "^1.10.0",
|
||||
"video-length": "^2.0.6",
|
||||
"ws": "^8.14.2"
|
||||
}
|
||||
},
|
||||
@ -655,11 +654,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/video-length": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/video-length/-/video-length-2.0.6.tgz",
|
||||
"integrity": "sha512-vPh0n39/3q2Gdzv93w745bjfNg+DFvhpKCr0GH2ZVYuPCXXYUGmy0fgmJOpk9btiZmAZsBrX/xhwb2tmyEoyBw=="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.14.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
|
||||
@ -1157,11 +1151,6 @@
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
|
||||
},
|
||||
"video-length": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/video-length/-/video-length-2.0.6.tgz",
|
||||
"integrity": "sha512-vPh0n39/3q2Gdzv93w745bjfNg+DFvhpKCr0GH2ZVYuPCXXYUGmy0fgmJOpk9btiZmAZsBrX/xhwb2tmyEoyBw=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.14.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
|
||||
|
@ -3,7 +3,6 @@
|
||||
"express": "^4.18.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"morgan": "^1.10.0",
|
||||
"video-length": "^2.0.6",
|
||||
"ws": "^8.14.2"
|
||||
}
|
||||
}
|
||||
|
@ -53,30 +53,19 @@
|
||||
<div id="ytplayer"></div>
|
||||
<script>
|
||||
(onload = onresize = () => {
|
||||
ytplayer.width = Math.min(innerWidth, 16/9 * innerHeight);
|
||||
ytplayer.height = Math.min(innerHeight, 9/16 * innerWidth);
|
||||
ytplayer.style.width = Math.min(innerWidth, 16/9 * innerHeight) + "px";
|
||||
ytplayer.style.height = Math.min(innerHeight, 9/16 * innerWidth) + "px";
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
<template id="mousie_template">
|
||||
<div class="mousie">
|
||||
<div class="mousie_pointer">🮰</div>
|
||||
<div class="mousie_talk"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
var player;
|
||||
|
||||
function initializePlayer(ytid, position) {
|
||||
function initializePlayer(id, position) {
|
||||
initializePlayer = () => console.warn("player already initialized");
|
||||
return new Promise(function (resolve, reject) {
|
||||
player = new YT.Player('ytplayer', {
|
||||
videoId: ytid,
|
||||
width: ytplayer.width,
|
||||
height: ytplayer.height,
|
||||
videoId: id,
|
||||
width: "1920",
|
||||
height: "1080",
|
||||
playerVars: {
|
||||
'playsinline': 1,
|
||||
"autoplay": 1,
|
||||
@ -109,15 +98,15 @@
|
||||
}
|
||||
|
||||
async function sync(force) {
|
||||
var {ytid, position} = await nowPlaying();
|
||||
var {id, position} = await nowPlaying();
|
||||
|
||||
if (!player) {
|
||||
await initializePlayer(ytid, position);
|
||||
await initializePlayer(id, position);
|
||||
}
|
||||
|
||||
if (player.getVideoData().video_id != ytid) {
|
||||
if (player.getVideoData().video_id != id) {
|
||||
console.debug("change video");
|
||||
player.loadVideoById(ytid, position);
|
||||
player.loadVideoById(id, position);
|
||||
player.playVideo();
|
||||
}
|
||||
|
||||
@ -139,9 +128,6 @@
|
||||
if (!playlist || Date.now() > playlist.timestamp + playlist.totalDuration*1000) {
|
||||
playlist = await fetch("playlist").then(res => res.json());
|
||||
}
|
||||
|
||||
playlist.videos = playlist.videos.filter(v => v.source.includes('youtube'));//tmp
|
||||
|
||||
for (var i = 0, pastDurations = 0; i < playlist.videos.length; i++) {
|
||||
var video = playlist.videos[i];
|
||||
var videoDurationMs = video.duration * 1000;
|
||||
@ -152,8 +138,7 @@
|
||||
}
|
||||
return {
|
||||
position: (Date.now() - pastDurations - playlist.timestamp) / 1000,
|
||||
source: video.source,
|
||||
ytid: video.source.split('?v=')[1]
|
||||
id: video.id
|
||||
};
|
||||
}
|
||||
|
||||
@ -161,7 +146,17 @@
|
||||
|
||||
</script>
|
||||
|
||||
<script> // mousies
|
||||
|
||||
|
||||
|
||||
<template id="mousie_template">
|
||||
<div class="mousie">
|
||||
<div class="mousie_pointer">🮰</div>
|
||||
<div class="mousie_talk"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
var ws;
|
||||
(function createWs() {
|
||||
ws = new WebSocket(location.href.replace('http','ws'));
|
||||
@ -204,11 +199,11 @@
|
||||
};
|
||||
})();
|
||||
|
||||
onmousemove = evt => {
|
||||
onmousemove = ({pageX, pageY}) => {
|
||||
if (ws.readyState != WebSocket.OPEN) return;
|
||||
var {left, top, width, height} = ytplayer.getBoundingClientRect();
|
||||
var x = (4096 * evt.pageX / width) - (4096 * left / width);
|
||||
var y = (4096 * evt.pageY / height) - (4096 * top / height);
|
||||
var x = (4096 * pageX / width) - (4096 * left / width);
|
||||
var y = (4096 * pageY / height) - (4096 * top / height);
|
||||
var b = new ArrayBuffer(4);
|
||||
var dv = new DataView(b);
|
||||
dv.setInt16(0, x, false);
|
||||
@ -268,7 +263,7 @@
|
||||
oncontextmenu = evt => {
|
||||
evt.preventDefault();
|
||||
nowPlaying().then(v => {
|
||||
if (v.source) open(v.source, "_blank");
|
||||
open(`https://www.youtube.com/watch?v=${v.id}`, "_blank");
|
||||
});
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user