Tl; Dr - Питання:
Яким є правильний спосіб обробки потокового відеофайлу на відеопрогравач html5 за допомогою Node.js, щоб елементи керування відео продовжували працювати?
Я думаю, це пов’язано з тим, як обробляються заголовки. У будь-якому випадку, ось довідкова інформація. Код трохи довгий, однак, він досить простий.
Потокове передавання невеликих відеофайлів на відео HTML5 за допомогою Node легко
Я навчився дуже легко передавати невеликі відеофайли у відеоплеєр HTML5. При такому налаштуванні елементи управління працюють без жодної роботи з мого боку, а відеопотік ідеально. Тут можна завантажити робочу копію повністю працюючого коду із зразком відео для завантаження з Google Docs .
Клієнт:
<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>
Сервер:
// 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);
Але цей метод обмежений файлами розміром менше 1 Гб.
Потокове передавання (будь-якого розміру) відеофайлів за допомогою fs.createReadStream
Використовуючи fs.createReadStream()
, сервер може читати файл у потоці, а не читати його все в пам’ять одночасно. Це звучить як правильний спосіб робити щось, а синтаксис надзвичайно простий:
Фрагмент сервера:
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);
});
Це потокове відео просто чудово! Але елементи керування відео більше не працюють.
writeHead()
код прокоментованим, але там на випадок, якщо це допоможе. Чи слід видаляти це, щоб зробити фрагмент коду більш читабельним?