Tl; Dr - Pertanyaan:
Apa cara yang tepat untuk menangani streaming file video ke pemutar video html5 dengan Node.js sehingga kontrol video terus berfungsi?
Saya pikir itu ada hubungannya dengan cara penanganan header. Berikut informasi latar belakangnya. Kode ini agak panjang, namun cukup mudah.
Streaming file video kecil ke video HTML5 dengan Node itu mudah
Saya belajar cara melakukan streaming file video kecil ke pemutar video HTML5 dengan sangat mudah. Dengan pengaturan ini, kontrol bekerja tanpa ada pekerjaan di pihak saya, dan video mengalir dengan sempurna. Salinan yang berfungsi dari kode yang berfungsi sepenuhnya dengan video contoh ada di sini, untuk diunduh di Google Documents .
Klien:
<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);
Tetapi metode ini terbatas pada file berukuran <1GB.
Streaming file video (ukuran apa saja) dengan fs.createReadStream
Dengan memanfaatkan fs.createReadStream()
, server dapat membaca file dalam aliran daripada membaca semuanya ke dalam memori sekaligus. Ini terdengar seperti cara yang tepat untuk melakukan sesuatu, dan sintaksnya sangat sederhana:
Cuplikan 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);
});
Ini mengalirkan video dengan baik! Tetapi kontrol video tidak lagi berfungsi.
writeHead()
kode itu berkomentar, tetapi di sana jika itu membantu. Haruskah saya menghapusnya agar cuplikan kode lebih mudah dibaca?