webcam displayed on LAN not to the internet

1.3k views Asked by At

OK, this is not due to a dumb mistake: I have forwarded the port and there is no firewall in between. I try to make the "live streaming" section of jsmpeg (https://github.com/phoboslab/jsmpeg) to work on the Internet. To get the webcam stream on my webpage I modify "stream-server.js"

if( process.argv.length < 3 ) {
 console.log(
  'Usage: \n' +
  'node stream-server.js <secret> [<stream-port> <websocket-port>]'
 );
 process.exit();
}

var STREAM_SECRET = process.argv[2],
 STREAM_PORT = process.argv[3] || 8082,
 WEBSOCKET_PORT = process.argv[4] || 8084,
 STREAM_MAGIC_BYTES = 'jsmp'; // Must be 4 bytes

var width = 320,
 height = 240;

// Websocket Server
var socketServer = new (require('ws').Server)({port: WEBSOCKET_PORT});
socketServer.on('connection', function(socket) {
 // Send magic bytes and video size to the newly connected socket
 // struct { char magic[4]; unsigned short width, height;}
 var streamHeader = new Buffer(8);
 streamHeader.write(STREAM_MAGIC_BYTES);
 streamHeader.writeUInt16BE(width, 4);
 streamHeader.writeUInt16BE(height, 6);
 socket.send(streamHeader, {binary:true});

 console.log( 'New WebSocket Connection ('+socketServer.clients.length+' total)' );
 
 socket.on('close', function(code, message){
  console.log( 'Disconnected WebSocket ('+socketServer.clients.length+' total)' );
 });
});

socketServer.broadcast = function(data, opts) {
 for( var i in this.clients ) {
  if (this.clients[i].readyState == 1) {
   this.clients[i].send(data, opts);
  }
  else {
   console.log( 'Error: Client ('+i+') not connected.' );
  }
 }
};


// HTTP Server to accept incomming MPEG Stream
var streamServer = require('http').createServer( function(request, response) {
 var params = request.url.substr(1).split('/');

 if( params[0] == STREAM_SECRET ) {
  width = (params[1] || 320)|0;
  height = (params[2] || 240)|0;
  
  console.log(
   'Stream Connected: ' + request.socket.remoteAddress + 
   ':' + request.socket.remotePort + ' size: ' + width + 'x' + height
  );
  request.on('data', function(data){
   socketServer.broadcast(data, {binary:true});
  });
 }
 else {
  console.log(
   'Failed Stream Connection: '+ request.socket.remoteAddress + 
   request.socket.remotePort + ' - wrong secret.'
  );
  response.end();
 }
}).listen(STREAM_PORT);

console.log('Listening for MPEG Stream on http://127.0.0.1:'+STREAM_PORT+'/<secret>/<width>/<height>');
console.log('Awaiting WebSocket connections on ws://127.0.0.1:'+WEBSOCKET_PORT+'/');

var servi = require('servi'),  // include the servi library
 app = new servi(false);  // servi instance

// configure the server's behavior:
app.port(8080);      // port number to run the server on
app.serveFiles("public");   // serve all static HTML files from /public
app.start(); 
console.log("Listening for new clients on port 8080");
<!DOCTYPE html>
<html>
<head>
 <meta name="viewport" content="width=320, initial-scale=1"/>
 <title>jsmpeg streaming webcam</title>
 <style type="text/css">
  body {
   background: white;
   text-align: center;
   margin-top: 10%;
  }
  #videoCanvas {
   /* Always stretch the canvas to 640x480, regardless of its
   internal size. */
   width: 640px;
   height: 480px;
  }
 </style>
</head>
<body>
<h1>
 The Canvas size specified 
</h1>
 <!-- The Canvas size specified here is the "initial" internal resolution. jsmpeg will
  change this internal resolution to whatever the source provides. The size the
  canvas is displayed on the website is dictated by the CSS style.
 -->
 <canvas id="videoCanvas" width="640" height="480">
  <p>
   Please use a browser that supports the Canvas Element, like
   <a href="http://www.google.com/chrome">Chrome</a>,
   <a href="http://www.mozilla.com/firefox/">Firefox</a>,
   <a href="http://www.apple.com/safari/">Safari</a> or Internet Explorer 10
  </p>
 </canvas>
 <script type="text/javascript" src="jsmpg.js"></script>
 <script type="text/javascript">
  // Show loading notice
  var canvas = document.getElementById('videoCanvas');
  var ctx = canvas.getContext('2d');
  ctx.fillStyle = '#444';
  ctx.fillText('Loading...', canvas.width/2-30, canvas.height/3);

  // Setup the WebSocket connection and start the player
  var client = new WebSocket( 'ws://192.168.1.15:8084/' );
  var player = new jsmpeg(client, {canvas:canvas});
 </script>
</body>
</html>

The "index.html" is included in a "public" folder.

Then I start ffmpeg with:

`ffmpeg -s 640x480 -f video4linux2 -i /dev/video0 -f mpeg1video -b:v 800k -r 30 http://192.168.1.15:8082/1693/640/480/`

When I open, on any station of the lan, url 192.168.1.x:8080 I get the webcam streaming on my page "jsmpeg streaming webcam"; but if use the public ip 41.142.x.y:8080 from outside the local network (using 3G) I get the page (with the h1 line "The Canvas size specified") but no video it just says in the frame "loading". I do not understand why it works locally and not globally. Why the page is streaming on the internet but not the webcam? Thanks for your help!

1

There are 1 answers

0
Vicorente On

in the client side, you should change this:

var client = 'ws://'+document.location.hostname+':8084/';
var player = new JSMpeg.Player(client, {canvas: canvas});

The way you were doing this was with the static ip 192.168.1.15. When it gets to the client, he doesn't know who this ip is.

I have not tested it, but I'm pretty sure the NAT will translate the ip addresses...