Javascript 如何使用node.js将当前下载的视频流式传输到html5播放器?
我目前正在做一个项目,下载一个torrent,并在下载时将其流式传输到html5视频播放器。我的项目的限制不允许我使用peerflix或webtorrent。我目前正在使用torrent stream模块。我的代码在node.js和pug中。详情如下: server.jsJavascript 如何使用node.js将当前下载的视频流式传输到html5播放器?,javascript,node.js,html,express,video-streaming,Javascript,Node.js,Html,Express,Video Streaming,我目前正在做一个项目,下载一个torrent,并在下载时将其流式传输到html5视频播放器。我的项目的限制不允许我使用peerflix或webtorrent。我目前正在使用torrent stream模块。我的代码在node.js和pug中。详情如下: server.js var uri = 'magnet:?xt=urn:btih:11a2ac68a11634e980f265cb1433c599d017a759'; var engine = torrentStream(uri);
var uri = 'magnet:?xt=urn:btih:11a2ac68a11634e980f265cb1433c599d017a759';
var engine = torrentStream(uri);
let engineGo = function () {
return new Promise(function (resolve, reject) {
var engine = torrentStream(uri);
engine.on('ready', function() {
engine.files.forEach(function(file) {
if (file.name.substr(file.name.length - 3) == 'mkv' || file.name.substr(file.name.length - 3) == 'mp4') {
console.log('filename:', file.name);
var stream = file.createReadStream();
var writable = fs.createWriteStream(file.name);
stream.pipe(writable);
engine.on('download', function () {
console.log(file.name);
console.log(engine.swarm.downloaded / file.length * 100 + "%");
resolve(file);
});
}
});
});
});
}
app.get('*', function (req, res) {
if (req.url != "/Guardians.of.the.Galaxy.2014.1080p.BluRay.x264.YIFY.mp4") {
var rpath = __dirname + '/views/index.pug';
fs.readFile(rpath, 'utf8', function (err, str) {
var fn = pug.compile(str, { filename: rpath, pretty: true});
res.writeHead(200, { "Content-Type": "text/html" });
res.write(fn());
res.end();
});
} else {
engineGo().then(function (result) {
var filer = path.resolve(__dirname,result.name);
fs.stat(filer, function(err, stats) {
if (err) {
if (err.code === 'ENOENT') {
// 404 Error if file not found
return res.sendStatus(404);
}
res.end(err);
}
var range = req.headers.range;
if (!range) {
// 416 Wrong range
return res.sendStatus(416);
}
var positions = range.replace(/bytes=/, "").split("-");
var start = parseInt(positions[0], 10);
var total = stats.size;
var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
'Connection': 'keep-alive',
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
var stream = fs.createReadStream(filer, { start: start, end: end })
.on("open", function() {
stream.pipe(res);
}).on("data", function (data) {
console.log(data);
}).on("error", function(err) {
res.end(err);
});
});
});
}
});
哈巴狗
doctype
html
title
|Welcome
body
video(id='video' src="http://localhost:8888/Guardians.of.the.Galaxy.2014.1080p.BluRay.x264.YIFY.mp4" type="video/mp4" controls)
在这一刻,这开始起作用。一旦我加载页面,承诺将执行并开始下载torrent。一旦来自torrent的第一位数据通过.on('open')上的流发送,视频将开始播放。播放机显示,随着更多信息的下载,视频中会添加更多信息,但它不会播放超过发送的初始数据。有没有什么方法可以告诉玩家更多的数据即将到来,而不是在读取发送的初始数据块时立即删除?任何建议都是有帮助的,请提前感谢 您可以尝试以下方法:
const path = require('path');
const parseRange = require('range-parser');
const engine = torrentStream('magnet:?xt=urn:btih:11a2ac68a11634e980f265cb1433c599d017a759');
const getTorrentFile = new Promise(function (resolve, reject) {
engine.on('ready', function() {
engine.files.forEach(function (file, idx) {
const ext = path.extname(file.name).slice(1);
if (ext === 'mkv' || ext === 'mp4') {
file.ext = ext;
resolve(file);
}
});
});
});
app.use('*', function (req, res) {
if (req.url != '/Guardians.of.the.Galaxy.2014.1080p.BluRay.x264.YIFY.mp4') {
res.setHeader('Content-Type', 'text/html');
if (req.method !== 'GET') return res.end();
var rpath = __dirname + '/views/index.pug';
fs.readFile(rpath, 'utf8', function (err, str) {
var fn = pug.compile(str, { filename: rpath, pretty: true});
res.end(fn());
});
} else {
res.setHeader('Accept-Ranges', 'bytes');
getTorrentFile.then(function (file) {
res.setHeader('Content-Length', file.length);
res.setHeader('Content-Type', `video/${file.ext}`);
const ranges = parseRange(file.length, req.headers.range, { combine: true });
if (ranges === -1) {
// 416 Requested Range Not Satisfiable
res.statusCode = 416;
return res.end();
} else if (ranges === -2 || ranges.type !== 'bytes' || ranges.length > 1) {
// 200 OK requested range malformed or multiple ranges requested, stream entire video
if (req.method !== 'GET') return res.end();
return file.createReadStream().pipe(res);
} else {
// 206 Partial Content valid range requested
const range = ranges[0];
res.statusCode = 206;
res.setHeader('Content-Length', 1 + range.end - range.start);
res.setHeader('Content-Range', `bytes ${range.start}-${range.end}/${file.length}`);
if (req.method !== 'GET') return res.end();
return file.createReadStream(range).pipe(res);
}
}).catch(function (e) {
console.error(e);
res.end(e);
});
}
});
我使用它来获取请求的字节范围,因为它经过全面测试并处理奇数边缘情况。我也会在服务器启动时立即启动torrent下载。这是因为浏览器通常会对同一个音频/视频文件发出多个请求,但请求的字节范围不同,因此在每次请求该文件时启动新的torrent流不是很有效。@Aks-torrent-stream@Aks这就是我使用torrent stream的原因。下载的时候把激流整理好了是啊,我的错!我不知道这个。我删除了我以前的评论,因为它在这里没用。很抱歉,我现在帮不了你。投票表决你的问题,这很有趣,我会尝试一些hours@Aks非常感谢你的帮助!