Video Deliver Solution -- Whats your thoughts?
Posted: Thu Aug 29, 2024 2:31 pm
This video delivery solution is compiling videochunks into a stream, you make the chunks with ffmpeg
ffmpeg
Folder name for video chunks: video_segments
it contains a bunch of ts files (those are the chunks) and a file named index.m3u8. That is the file we load into the web player.
A simple webplayer I found somewhere, webplayer.html (can be locally hosted as it fetches from evernode instance).
Replace localhost with your evernode ipv4:port !
index.js
package.json
start.sh
Dockerfile
This is a standalone video worker. The idea is to have a lot of these and rotate them, that's the load balancer I'm still trying to figure out!
So far I got the rotation working well, so when running through the load balancer you get a chunk from a list of nodes (which should distribute the load between all the nodes in the rotation list).
Thoughts?
ffmpeg
Code: Select all
ffmpeg -i "path to videoname.mp4" -codec: copy -start_number 0 -hls_time 6 -hls_list_size 0 -f hls index.m3u8
it contains a bunch of ts files (those are the chunks) and a file named index.m3u8. That is the file we load into the web player.
A simple webplayer I found somewhere, webplayer.html (can be locally hosted as it fetches from evernode instance).
Replace localhost with your evernode ipv4:port !
Code: Select all
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HLS Video Stream</title>
<link href="https://vjs.zencdn.net/7.11.4/video-js.css" rel="stylesheet" />
</head>
<body>
<video
id="my-video"
class="video-js vjs-default-skin"
controls
preload="auto"
width="640"
height="264"
data-setup='{}'>
<source src="https://localhost:36525/index.m3u8" type="application/x-mpegURL">
Your browser does not support the video tag.
</video>
<script src="https://vjs.zencdn.net/7.11.4/video.js"></script>
</body>
</html>
Code: Select all
const http = require('http');
const fs = require('fs');
const path = require('path');
const videoDir = path.join(__dirname, 'video_segments');
// Function to create and start a server on a specific port
function createServer(port) {
const server = http.createServer((req, res) => {
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Range');
// Handle OPTIONS method (CORS preflight)
if (req.method === 'OPTIONS') {
res.writeHead(204);
res.end();
return;
}
const filePath = path.join(videoDir, req.url);
fs.stat(filePath, (err, stats) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
return;
}
if (stats.isDirectory()) {
res.writeHead(403, { 'Content-Type': 'text/plain' });
res.end('403 Forbidden');
return;
}
let contentType = 'video/mp4';
if (filePath.endsWith('.m3u8')) {
contentType = 'application/x-mpegURL';
} else if (filePath.endsWith('.mp4')) {
contentType = 'video/mp4';
}
res.writeHead(200, { 'Content-Type': contentType });
const readStream = fs.createReadStream(filePath);
readStream.on('error', (streamErr) => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Internal Server Error');
});
readStream.pipe(res);
});
});
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
}
// Start the server on port rangee 36525-36535
for (let port = 36525; port <= 36535; port++) {
createServer(port);
}
Code: Select all
{
"name": "evernode-vod-solution",
"version": "1.0.0",
"description": "Evernode VOD solution",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Code: Select all
#!/bin/sh
# Run vod
/usr/bin/node /usr/local/bin/hotpocket/vod &
# Set the HotPocket binary as the entry point.
# $@ is used to pass all the commandline arguments fed to this script into hpcore.
/usr/local/bin/hotpocket/hpcore $@
Code: Select all
FROM evernode/sashimono:hp.latest-ubt.20.04-njs.20
RUN mkdir -p /usr/local/bin/hotpocket/vod
RUN mkdir -p /usr/local/bin/hotpocket/vod/video_segments
COPY / /usr/local/bin/hotpocket/vod
COPY /video_segments /usr/local/bin/hotpocket/vod/video_segments
COPY start.sh /usr/local/bin/hotpocket/start.sh
RUN chmod +x /usr/local/bin/hotpocket/start.sh
ENTRYPOINT ["/usr/local/bin/hotpocket/start.sh"]
EXPOSE 36525-36535
This is a standalone video worker. The idea is to have a lot of these and rotate them, that's the load balancer I'm still trying to figure out!
So far I got the rotation working well, so when running through the load balancer you get a chunk from a list of nodes (which should distribute the load between all the nodes in the rotation list).
Thoughts?