Video viewer!
This commit is contained in:
parent
b5af5a2be1
commit
8137a82bd1
2 changed files with 86 additions and 1 deletions
61
index.js
61
index.js
|
@ -35,12 +35,62 @@ if (!directory) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const videoFormats = ["mp4", "mkv"]
|
||||||
|
|
||||||
app.use(express.static(directory))
|
app.use(express.static(directory))
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log("Now listening on PORT: " + PORT)
|
console.log("Now listening on PORT: " + PORT)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.get("/watch/*", (req, res) => {
|
||||||
|
res.setHeader("Content-Type", "text/html")
|
||||||
|
|
||||||
|
var video = req.params[0]
|
||||||
|
var absPath = path.join(directory, video)
|
||||||
|
|
||||||
|
var html = fs.readFileSync(path.join(__dirname, 'resources/watch.html')).toString()
|
||||||
|
|
||||||
|
html = html.replaceAll("{VID_PATH}", video)
|
||||||
|
|
||||||
|
var vidTitle = video.substring(video.lastIndexOf('/') + 1, video.lastIndexOf('.'))
|
||||||
|
|
||||||
|
var vidStats = fs.statSync(absPath)
|
||||||
|
|
||||||
|
html = html.replaceAll("{TITLE}", vidTitle)
|
||||||
|
|
||||||
|
html = html.replaceAll("{VID_INFO}", `Size: ${humanFileSize(vidStats.size)}`)
|
||||||
|
|
||||||
|
html = html.replaceAll("{BACK}", "/" + video.substring(0, video.lastIndexOf("/")))
|
||||||
|
|
||||||
|
res.send(html)
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get("/video/*", (req, res) => {
|
||||||
|
var video = req.params[0]
|
||||||
|
var vidPath = path.join(directory, video)
|
||||||
|
|
||||||
|
const range = req.headers.range
|
||||||
|
const videoPath = vidPath;
|
||||||
|
const videoSize = fs.statSync(videoPath).size
|
||||||
|
const chunkSize = 1 * 1e6;
|
||||||
|
const start = Number(range.replace(/\D/g, ""))
|
||||||
|
const end = Math.min(start + chunkSize, videoSize - 1)
|
||||||
|
const contentLength = end - start + 1;
|
||||||
|
const headers = {
|
||||||
|
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
|
||||||
|
"Accept-Ranges": "bytes",
|
||||||
|
"Content-Length": contentLength,
|
||||||
|
"Content-Type": "video/mkv"
|
||||||
|
}
|
||||||
|
res.writeHead(206, headers)
|
||||||
|
const stream = fs.createReadStream(videoPath, {
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
})
|
||||||
|
stream.pipe(res)
|
||||||
|
})
|
||||||
|
|
||||||
app.get("/*", (req, res) => {
|
app.get("/*", (req, res) => {
|
||||||
var file = req.params[0]
|
var file = req.params[0]
|
||||||
var absPath = path.join(directory, file)
|
var absPath = path.join(directory, file)
|
||||||
|
@ -76,11 +126,22 @@ app.get("/*", (req, res) => {
|
||||||
|
|
||||||
var dirs = []
|
var dirs = []
|
||||||
|
|
||||||
|
var ogFolder = file
|
||||||
|
|
||||||
for (let index = 0; index < dirContents.length; index++) {
|
for (let index = 0; index < dirContents.length; index++) {
|
||||||
const file = dirContents[index];
|
const file = dirContents[index];
|
||||||
|
var userPath = path.join(ogFolder, file)
|
||||||
|
|
||||||
var fileStats = fs.statSync(path.join(absPath, file))
|
var fileStats = fs.statSync(path.join(absPath, file))
|
||||||
|
|
||||||
if (!fileStats.isDirectory()) {
|
if (!fileStats.isDirectory()) {
|
||||||
|
var fileExtension = file.substring(file.lastIndexOf('.') + 1, )
|
||||||
|
if (videoFormats.includes(fileExtension)) {
|
||||||
|
res.write(`<li><a href="/watch/${userPath}">${file}</a> | ${humanFileSize(fileStats.size)}</li>`)
|
||||||
|
} else {
|
||||||
res.write(`<li><a href="./${file}">${file}</a> | ${humanFileSize(fileStats.size)}</li>`)
|
res.write(`<li><a href="./${file}">${file}</a> | ${humanFileSize(fileStats.size)}</li>`)
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dirs.push(file)
|
dirs.push(file)
|
||||||
}
|
}
|
||||||
|
|
24
resources/watch.html
Normal file
24
resources/watch.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://violets-purgatory.dev/style.css">
|
||||||
|
|
||||||
|
|
||||||
|
<title>{TITLE}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>{TITLE}</h1>
|
||||||
|
<p><a href="{BACK}">Back</a></p>
|
||||||
|
<p>{VID_INFO}</p>
|
||||||
|
<div class="fadediv">
|
||||||
|
<video src="/proxy/8080/video/{VID_PATH}" width="100%" controls></video>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in a new issue