Tl; Dr - La domanda:
Qual è il modo giusto per gestire lo streaming di un file video su un lettore video html5 con Node.js in modo che i controlli video continuino a funzionare?
Io penso che abbia a che fare con il modo in cui le intestazioni vengono gestiti. Comunque, ecco le informazioni di base. Il codice è un po ' lungo, tuttavia, è piuttosto semplice.
Lo streaming di piccoli file video in video HTML5 con Node è facile
Ho imparato a trasmettere in streaming piccoli file video a un lettore video HTML5 molto facilmente. Con questa configurazione, i controlli funzionano senza alcun intervento da parte mia e il video viene riprodotto in modo impeccabile. Una copia funzionante del codice completamente funzionante con video di esempio è qui, per il download su Google Docs .
Cliente:
<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);
Ma questo metodo è limitato ai file di dimensioni inferiori a 1 GB.
Streaming di file video (di qualsiasi dimensione) con estensione fs.createReadStream
Utilizzando fs.createReadStream(), il server può leggere il file in un flusso invece di leggerlo tutto in memoria in una volta. Sembra il modo giusto di fare le cose e la sintassi è estremamente semplice:
Snippet del server:
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);
});
Questo riproduce il video perfettamente! Ma i controlli video non funzionano più.
writeHead()codice commentato, ma nel caso fosse utile. Devo rimuoverlo per rendere più leggibile lo snippet di codice?