mafintosh / torrent-stream

The low level streaming torrent engine that peerflix uses
MIT License
1.94k stars 227 forks source link

Question: Piping stream to a HTTP server #145

Closed tsoernes closed 8 years ago

tsoernes commented 8 years ago

I'm trying to launch torrent-stream and download the biggest video file in a torrent, piping it to a HTTP server in order to play the video in an external video player. I've gotten this far:

function launchTorrentStream (torrentFilePath) {
  var http = require('http')
  var torrentStream = require('torrent-stream')
  var fs = require("fs");
  var engine = torrentStream(fs.readFileSync(torrentFilePath))

  engine.on('ready', function() {
    var biggestIdx = 0
    for (var i = 1 ; i < engine.files.length; i++) {
      if (engine.files[i].length > engine.files[biggestIdx].length) {
        biggestIdx = i
      }
    }
    var stream = engine.files[biggestIdx].createReadStream();
    var server = http.createServer(function (req, res) {
      stream.pipe(res);
    });
    server.listen(config.port, 'localhost');  // start
    var url = 'http://localhost:' + config.port + '/' + biggestIdx
    console.log(engine.files[biggestIdx].name + ' available at ' + url)
  });
}

But I can't figure what URL the file would be available at. Neither http://localhost:8888/<biggestIndex> or http://localhost:8888/MyVideo.mkv or just http://localhost:8888 works. What decides the path, the HTTP server or the torrent-stream?

mafintosh commented 8 years ago

What is config.port set to?

mafintosh commented 8 years ago

According to your example any url will work.

tsoernes commented 8 years ago

It's set to 8888, like in the example. I've tried both VLC and MPC-HC at the URLs above, but there is no response.

If I use the same torrentfile, url (localhost) and port in Web-Torrent and it's build in HTTP-server, it works, so I don't think there is problem with the torrent-file or a firewall or something.

mafintosh commented 8 years ago

if you're piping it to a media player you need to set a content type res.setHeader('Content-Type', 'video/mp4') if it's an mp4 file and you should create the stream every time there is a request - not just once

tsoernes commented 8 years ago
var stream = engine.files[biggestIdx].createReadStream();
    var server = http.createServer(function (req, res) {
      res.setHeader('Content-Type', 'video/mkv')
      stream.pipe(res);
    })
    server.listen(config.port, 'localhost');  // start
    server.on('request', function (req, res) {
      stream.pipe(res);
    })

I tried the above, but no luck. What am I missing? I can see MPC-HC sending requests to the server.

mafintosh commented 8 years ago

You need to create the stream everytime a request is made

function (req, res) {
  var stream = engine.files[biggestIdx].createReadStream()
  ...
  stream.pipe(res)
}
tsoernes commented 8 years ago

Hmm, I tried that in addition to trying both video/mkv and video/mp4.

engine.on('ready', function() {
    var biggestIdx = 0
    for (var i = 1 ; i < engine.files.length; i++) {
      if (engine.files[i].length > engine.files[biggestIdx].length) {
        biggestIdx = i
      }
    }
    var stream = engine.files[biggestIdx].createReadStream();
    var server = http.createServer(function (req, res) {
      res.setHeader('Content-Type', 'video/mp4')
      stream.pipe(res);
    })
    server.listen(config.port, 'localhost');  // start
    server.on('request', function (req, res) {
      stream = engine.files[biggestIdx].createReadStream()
      res.setHeader('Content-Type', 'video/mp4')
      stream.pipe(res);
    })
  })
mafintosh commented 8 years ago

You are attaching two request handlers in your example. You should only have one.

tsoernes commented 8 years ago

No success, did I get it right?

function launchTorrentStream (torrentFilePath) {
  var engine = torrentStream(fs.readFileSync(torrentFilePath))

  engine.on('ready', function() {
    var biggestIdx = 0
    for (var i = 1 ; i < engine.files.length; i++) {
      if (engine.files[i].length > engine.files[biggestIdx].length) {
        biggestIdx = i
      }
    }
    var server = http.createServer(function (req, res) {
      var stream = engine.files[biggestIdx].createReadStream()
      res.setHeader('Content-Type', 'video/mp4')
      stream.pipe(res)
    })
    server.listen(config.port, 'localhost');
  })
}
mafintosh commented 8 years ago

Yep. That looks right to me. If it still doesn't work I'd suggest adding some console.log's to your request handler to try to figure out whats wrong