Tl; Dr - Pytanie:
Jaki jest właściwy sposób obsługi przesyłania strumieniowego pliku wideo do odtwarzacza wideo HTML5 za pomocą Node.js, aby elementy sterujące wideo nadal działały?
Myślę , że ma to związek ze sposobem obsługi nagłówków. W każdym razie, oto podstawowe informacje. Kod jest trochę długi, jednak jest dość prosty.
Przesyłanie strumieniowe małych plików wideo do wideo HTML5 za pomocą Node jest łatwe
Nauczyłem się, jak bardzo łatwo przesyłać strumieniowo małe pliki wideo do odtwarzacza wideo HTML5. W tej konfiguracji elementy sterujące działają bez żadnej pracy z mojej strony, a strumień wideo jest bezbłędny. Kopia robocza w pełni działającego kodu z przykładowym filmem jest tutaj do pobrania w Dokumentach Google .
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>
Serwer:
// 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);
Ale ta metoda jest ograniczona do plików o rozmiarze <1 GB.
Przesyłanie strumieniowe (dowolnego rozmiaru) plików wideo w formacie fs.createReadStream
Wykorzystując fs.createReadStream()
, serwer może odczytać plik w strumieniu, zamiast wczytywać go w całości do pamięci naraz. Brzmi to jak właściwy sposób robienia rzeczy, a składnia jest niezwykle prosta:
Fragment serwera:
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);
});
To dobrze przesyła wideo! Ale sterowanie wideo już nie działa.
writeHead()
kod skomentowany, ale na wszelki wypadek to pomoże. Czy powinienem to usunąć, aby fragment kodu był bardziej czytelny?