Tl; Dr - Die Frage:
Was ist der richtige Weg, um eine Videodatei mit Node.js auf einen HTML5-Videoplayer zu streamen, damit die Videosteuerelemente weiterhin funktionieren?
Ich denke , das hat damit zu tun, wie die Header behandelt werden. Wie auch immer, hier sind die Hintergrundinformationen. Der Code ist etwas langwierig, aber ziemlich einfach.
Das Streamen kleiner Videodateien zu HTML5-Videos mit Node ist einfach
Ich habe gelernt, wie man sehr einfach kleine Videodateien auf einen HTML5-Videoplayer streamen kann. Mit diesem Setup funktionieren die Steuerelemente ohne meinerseits und die Videostreams funktionieren einwandfrei. Eine Arbeitskopie des voll funktionsfähigen Codes mit Beispielvideo steht hier zum Download in Google Text & Tabellen zur Verfügung .
Klient:
<html>
<title>Welcome</title>
<body>
<video controls>
<source src="movie.mp4" type="video/mp4"/>
<source src="movie.webm" type="video/webm"/>
<source src="movie.ogg" type="video/ogg"/>
<!-- fallback -->
Your browser does not support the <code>video</code> element.
</video>
</body>
</html>
Server:
// Declare Vars & Read Files
var fs = require('fs'),
http = require('http'),
url = require('url'),
path = require('path');
var movie_webm, movie_mp4, movie_ogg;
// ... [snip] ... (Read index page)
fs.readFile(path.resolve(__dirname,"movie.mp4"), function (err, data) {
if (err) {
throw err;
}
movie_mp4 = data;
});
// ... [snip] ... (Read two other formats for the video)
// Serve & Stream Video
http.createServer(function (req, res) {
// ... [snip] ... (Serve client files)
var total;
if (reqResource == "/movie.mp4") {
total = movie_mp4.length;
}
// ... [snip] ... handle two other formats for the video
var range = req.headers.range;
var positions = range.replace(/bytes=/, "").split("-");
var start = parseInt(positions[0], 10);
var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
var chunksize = (end - start) + 1;
if (reqResource == "/movie.mp4") {
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
res.end(movie_mp4.slice(start, end + 1), "binary");
}
// ... [snip] ... handle two other formats for the video
}).listen(8888);
Diese Methode ist jedoch auf Dateien mit einer Größe von <1 GB beschränkt.
Streaming von Videodateien (beliebiger Größe) mit fs.createReadStream
Durch die Verwendung fs.createReadStream()
kann der Server die Datei in einem Stream lesen, anstatt alles auf einmal in den Speicher einzulesen. Das klingt nach der richtigen Vorgehensweise, und die Syntax ist äußerst einfach:
Server-Snippet:
movieStream = fs.createReadStream(pathToFile);
movieStream.on('open', function () {
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
// This just pipes the read stream to the response object (which goes
//to the client)
movieStream.pipe(res);
});
movieStream.on('error', function (err) {
res.end(err);
});
Dies überträgt das Video ganz gut! Die Videosteuerung funktioniert jedoch nicht mehr.
writeHead()
Code kommentiert, aber für den Fall, dass es hilft. Sollte ich das entfernen, um das Code-Snippet besser lesbar zu machen?