Last active
January 17, 2019 15:19
-
-
Save ezirmusitua/e9565d96245a370f212bfd401e2e2e81 to your computer and use it in GitHub Desktop.
[Local video server] Simplest node video player running in localhost #node #javascript #tools #video
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const path = require('path'); | |
const http = require('http'); | |
function createServer(videoRepoPath) { | |
return http.createServer((req, res) => { | |
if (/video\/.*\/view/gi.test(req.url)) { | |
console.log(req.url, req.url.split('/')); | |
const [, , video] = req.url.split('/'); | |
const ext = path.extname(video); | |
res.setHeader('Content-Type', 'text/html; charset=utf-8'); | |
res.write(`<html> | |
<body> | |
<video controls width="100%"> | |
<source src="/video/${video}" type="video/${ext.slice(1)}" > | |
</video> | |
</body> | |
</html>`); | |
return res.end(); | |
} | |
if (/video\/.*/gi.test(req.url)) { | |
const [, , video] = req.url.split('/'); | |
const ext = path.extname(video); | |
const abspath = decodeURIComponent(path.join(videoRepoPath, video)); | |
const stat = fs.statSync(abspath); | |
const videoSize = stat.size; | |
const range = req.headers.range; | |
if (range) { | |
const parts = range.replace(/bytes=/, '').split('-'); | |
const start = parseInt(parts[0], 10); | |
const end = parts[1] ? parseInt(parts[1], 10) : videoSize - 1; | |
const chunkSize = (end - start) + 1 | |
const fileChunk = fs.createReadStream(abspath, {start, end}) | |
const headers = { | |
'Content-Range': `bytes ${start}-${end}/${videoSize}`, | |
'Accept-Range': 'bytes', | |
'Content-Length': chunkSize, | |
'Content-Type': `video/${ext.slice(1)}` | |
}; | |
res.writeHead(206, headers); | |
fileChunk.pipe(res); | |
} else { | |
const headers = { | |
'Content-Length': videoSize, | |
'Content-Type': `video/${ext.slice(1)}` | |
}; | |
fs.createReadStream(abspath).pipe(res); | |
} | |
} else { | |
const videos = fs.readdirSync(videoRepoPath); | |
const videosStr = videos.filter((video) => fs.statSync(path.join(videoRepoPath, video)).isFile()) | |
.map((v) => `<a style="font-size: 16px; margin-bottom: 12px;" href="/video/${v}/view" style="font-size: 20px; color: rgba(2, 3, 44, 0.87); margin-bottom: 16px;"> | |
${v} | |
</a>`) | |
.join('\n'); | |
res.setHeader('Content-Type', 'text/html; charset=utf-8'); | |
res.write(`<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1" /> | |
<title>${videoRepoPath}</title> | |
</head> | |
<body style="margin: 0"> | |
<article style="padding: 64px 40px; display: flex; flex-direction: column;"> | |
<h2>${videoRepoPath}</h2> | |
${videosStr} | |
</article> | |
</body> | |
</html>`); | |
return res.end(); | |
} | |
}); | |
} | |
function getRepoPath() { | |
const repoPath = process.argv[2]; | |
if (!repoPath) return __dirname; | |
return repoPath; | |
} | |
function main() { | |
const imageViewer = createServer(getRepoPath()); | |
console.info('Server listening on: 0.0.0.0:8080'); | |
imageViewer.listen({ host: '0.0.0.0', port: 8080 }); | |
} | |
main(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment