2016-11-23 6 views
2

В настоящее время я работаю над проектом, который загружает торрент и, в то время как он загружается, передает его на видеопроигрыватель html5. Ограничения моего проекта не позволяют мне использовать peerflix или webtorrent. В настоящее время я использую модуль torrent-stream. Мой код находится в node.js и pug. Это выглядит следующим образом:Как передать текущую загрузку видео в html5-плеер с 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) 

На данный момент это начинает работать. Как только я загружу страницу, обещание выполнится и начнет загружать торрент. Как только первый бит данных из потока отправляется через поток на .on ('open'), начнется воспроизведение видео. Игрок показывает, что в видео добавляется больше информации, поскольку загружается больше, но она никогда не будет воспроизводиться за исходными данными, которые были отправлены. Есть ли способ сказать игроку, что больше данных идет, а не вырезать второе, это делается, читая его начальный кусок, который был отправлен? Любые советы полезны и заблаговременно!

+0

@Aks - torrent-stream –

+0

@ Вот почему я использую torrent-поток. Это положил торрент в порядок, поскольку он загружает – pbie42

+0

Да, мой плохой! Не знал этого. Я удалил свой предыдущий комментарий, поскольку он бесполезен здесь. Мне жаль, что я не могу помочь тебе сейчас. Возьмите свой вопрос, это интересно, и я попробую через несколько часов – Aks

ответ

1

Вы можете попробовать это:

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, чтобы получить требуемый диапазон байтов, потому что он тщательно протестирована и обрабатывает нечетные случаи края. Я также запускаю торрент-загрузку сразу после запуска сервера. Это связано с тем, что браузеры часто делают несколько запросов для одного и того же аудио/видеофайла только с разными байтовыми диапазонами, поэтому запуск нового потока торрентов по каждому запросу для этого файла не очень эффективен.