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()
код прокомментированным, но на тот случай, если это поможет. Следует ли мне удалить это, чтобы сделать фрагмент кода более читабельным?