2016-11-23 1 views
2

Ich arbeite gerade an einem Projekt, das einen Torrent herunterlädt und während des Downloads in einen html5-Videoplayer streamt. Die Einschränkungen meines Projekts lassen mich nicht Peerflix oder WebTorrent verwenden. Ich verwende derzeit das Torrent-Stream-Modul. Mein Code ist in node.js und mug. Es ist wie folgt:Wie streame ich das aktuelle Video auf html5 player mit 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) 

Im Moment diese Arbeit beginnt. Sobald ich die Seite geladen habe, wird das Versprechen ausgeführt und der Torrent wird heruntergeladen. Sobald das erste Bit der Daten vom Torrent durch den Stream auf dem .on ('open') gesendet wird, beginnt das Video zu spielen. Der Player zeigt an, dass dem Video mehr Informationen hinzugefügt werden, wenn mehr heruntergeladen wird. Es wird jedoch nie über die ursprünglichen Daten hinaus gespielt, die gesendet wurden. Gibt es eine Möglichkeit, dem Spieler zu sagen, dass mehr Daten kommen und nicht, dass die Sekunde abgeschnitten wird, wenn der erste Teil, der gesendet wurde, gelesen wird? Jeder Rat ist hilfreich und danke im Voraus!

+0

@Aks - torrent-stream –

+0

@Aks deshalb verwende ich torrent-stream. Es ist der Torrent in Ordnung, wie es – pbie42

+0

Download Yeah, mein Schlechter! Habe ich nicht gewusst. Ich habe meinen vorherigen Kommentar gelöscht, weil er hier nicht gebraucht wird. Es tut mir leid, dass ich dir jetzt nicht helfen kann. Upvoting Ihre Frage, es ist interessant, und ich werde versuchen, in einigen Stunden – Aks

Antwort

1

Sie können dies ausprobieren:

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

ich range-parser bin mit den angeforderten Bytebereich zu bekommen, weil sie und Griffe ungerade Rand Fällen throughly getestet wird. Ich starte auch den Torrent-Download sofort beim Hochfahren des Servers. Dies liegt daran, dass Browser oft mehrere Anforderungen für dieselbe Audio-/Videodatei nur mit unterschiedlichen Byte-Bereichen stellen, so dass das Starten eines neuen Torrent-Streams bei jeder Anfrage für diese Datei nicht sehr effizient ist.

Verwandte Themen