如何使用node.js将当前正在下载的videostream传输到html5播放器?

我目前正在下载一个项目,下载一个洪stream,而下载时,它stream到一个HTML5video播放器。 我的项目的限制不让我使用peerflix或webtorrent。 我目前正在使用torrent-stream模块。 我的代码是在node.js和帕格。 具体如下:

server.js

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); }); }); }); } }); 

index.pug

 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) 

目前这开始工作。 一旦我加载页面承诺将执行,并开始下载洪stream。 一旦来自torrent的第一位数据通过.on('open')stream发送,video将开始播放。 播放器显示更多的信息正在被添加到video中,因为下载的video更多,但它永远不会播放已发送的初始数据。 有什么方法可以告诉玩家更多的数据来了,而不是把第二块数据删除,读取它发送的初始块? 任何build议是有益的,并提前谢谢你!

你可以试试这个:

 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); }); } }); 

我正在使用range-parser来获取请求的字节范围,因为它经过了全面的testing,并处理奇怪的边缘情况。 我也在服务器启动时立即启动torrent下载。 这是因为浏览器通常会对同一个audio/video文件提出多个请求,只是字节范围不同,所以在每个文件请求上启动一个新的torrentstream并不是非常有效。