vmolsa / webrtc-native

WebRTC for NodeJS
MIT License
169 stars 96 forks source link

node js server can't forward the boardcast stream to client? #22

Open kevinkindom opened 8 years ago

kevinkindom commented 8 years ago

Hi, i have A peer and B peer, A peer provide a stream transport to webrtc-native server, and i want B peer get stream from nodejs server and play it.

but B peer in windows 7, i have a black screen. and the mediastream readystate is muted?

if in ubuntu 14.04.1, the nodejs server will be crash.

my node version is 0.12.7, it's webrtc-native bug? or my usage is wrong?

vmolsa commented 8 years ago

Hi, I updated the module. is it working now? For now on linux it's getting segfault when the app is closin g but that segfault is coming from chromium and only happens on exit.

webrtc::AudioMixerManagerLinuxALSA::CloseSpeaker()
kevinkindom commented 8 years ago

Hi, is updated binary file? i update from http://cide.cc:8080/webrtc/Ubuntu-14.04/x64/v0.12.x/webrtc.node, but still crash.

there is my crash log:

Listening on 4080
boardcast stream: { onended: undefined,
  onremovetrack: undefined,
  onaddtrack: undefined,
  id: 'bB46PEzQrxXbmkMG9yajkf7hiLaGIjtvexBw',
  ended: true }
board set remote success
WARNING: no real random source present!
0: SIGSEGV [0x7f42a50bb30d] clone
1: SIGSEGV [0x7f42a538e182] function()
2: SIGSEGV [0x7f42a45f0fd9] function()
3: SIGSEGV [0x7f42a4561372] function()
4: SIGSEGV [0x7f42a45f0769] function()
5: SIGSEGV [0x7f42a455e868] function()
6: SIGSEGV [0x7f42a45ba56f] function()
7: SIGSEGV [0x7f42a45cb143] function()
8: SIGSEGV [0x7f42a45d979b] function()
9: SIGSEGV [0x7f42a45d96fa] function()
10: SIGSEGV [0x7f42a45d6993] function()
11: SIGSEGV [0x7f42a45b7758] function()
12: SIGSEGV [0x7f42a45d5842] function()
13: SIGSEGV [0x7f42a45d4ee4] function()
14: SIGSEGV [0x7f42a45d4dba] function()
Segmentation fault (core dumped)
vmolsa commented 8 years ago
npm install webrtc-native

Is working now? if not then the path is webrtc.node

kevinkindom commented 8 years ago

Yes, i reinstall it, but still crash.

Listening on 4080
boardcast stream: { stream: 
   { onended: undefined,
     onremovetrack: undefined,
     onaddtrack: undefined,
     id: 'JmzWiQArM4y9bjF8254qSYInVRSBmDIxdQPE',
     ended: true } }
board set remote success
0: SIGSEGV [0x1914b100740e] function()
1: SIGSEGV [0x7d9a91] function()
2: SIGSEGV [0x7b8e02] v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&))
3: SIGSEGV [0x7f90803cb156] function()
4: SIGSEGV [0x7f90803d1914] function()
5: SIGSEGV [0x7f90803db51b] function()
6: SIGSEGV [0x7f90803db436] function()
7: SIGSEGV [0x7f90803db310] function()
8: SIGSEGV [0x7f9081a7dfce] std::string::compare(char const*) const
Segmentation fault (core dumped)
kevinkindom commented 8 years ago

this is my test code, hope that helps.

server code node pageage install npm install ws express ejs

var fs = require('fs');
var server = require('http').createServer();
var url = require('url');
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server: server })
var express = require('express');
var ejs = require('ejs');
var app = express();
var webRTC = require('webrtc-native');
var port = 4080;

app.engine('.html', ejs.__express);
app.set('view engine', 'html');

app.get('/boardcast', function(req, res){
  res.render('boardcast');
});

app.get('/client', function(req, res){
  res.render('client');
});

var STREAM = null;
var boardcast = null;
var client = null;

var socket_format = function(evt_name, data){
  return JSON.stringify({name: evt_name, data: data});
}

function setLocalSDP(p, callback){
    if(p.iceGatheringState != 'complete'){
        setTimeout(function(){
            setLocalSDP(p, callback);
        }, 10);
    }else{
        callback && callback();
    }
}

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    var data = JSON.parse(message);

    switch(data.name){
      case 'boardcast local description':
        var boardcastSDP = new webRTC.RTCSessionDescription(JSON.parse(data.data));

        // create boardcast peer
        boardcast = new webRTC.RTCPeerConnection(null);
        boardcast.onaddstream = function(stream){
          STREAM = stream;
          console.log('boardcast stream:', stream);
        }

        boardcast.setRemoteDescription(boardcastSDP, function(){
          console.log('board set remote success');
          boardcast.createAnswer(function(answerSDP){
            boardcast.setLocalDescription(answerSDP, function(){
              ws.send(socket_format('boardcast remote description', answerSDP));
            })
          })
        }, function(err){
          console.log('board set remote fail:', err);
        });
        break;

      case 'client connect':
        // create client peer
        client = new webRTC.RTCPeerConnection(null, {audio: true, video: true});
        client.addStream(STREAM);
        client.createOffer(function(SDP){
          client.setLocalDescription(SDP, function(){
            setLocalSDP(client, function(){
              var answerSDP = JSON.stringify(client.localDescription);
              ws.send(socket_format('client remote description', answerSDP));
            });
          }, function(){

          })
        });
        break;

      case 'client local description':
        var clientRemoteSDP = new webRTC.RTCSessionDescription(data.data);
        client.setRemoteDescription(clientRemoteSDP, function(){
          console.log('client done');
          console.log('video track:', STREAM.getVideoTracks());
          ws.send(socket_format('server client done'));
        }, function(err){
          console.log('client error', err);
        })
        break;
    }
  });

  ws.send(socket_format('join', 'welcome to join!'));
});

server.on('request', app);
server.listen(port, function () { console.log('Listening on ' + server.address().port) });

boardcast html

var video = document.getElementById('video');
var peer = null;
var ws = new WebSocket('ws://localhost:4080');
var wsCallbacks = {};

function socket_format(evt_name, data){
  return JSON.stringify({name: evt_name, data: data});
}

function setLocalSDP(p, callback){
    if(peer.iceGatheringState != 'complete'){
        window.setTimeout(function(){
            setLocalSDP(p, callback);
        }, 10);
    }else{
        callback && callback();
    }
}

navigator.webkitGetUserMedia({audio: true, video: true}, function(stream){
    var blob_url = URL.createObjectURL(stream);
    video.src = blob_url;
    video.play();

    peer = new window.webkitRTCPeerConnection(null);
    peer.addStream(stream);
    peer.createOffer(function(SDP){
        peer.setLocalDescription(SDP, function(){
            setLocalSDP(peer, function(){
                var sd = JSON.stringify(peer.localDescription.toJSON());
                ws.send(socket_format('boardcast local description', sd));
            });
        }, function(){})
    });
}, function(){});

wsCallbacks['join'] = function(data){
    console.log('server say:', data);
}

wsCallbacks['boardcast remote description'] = function(remoteSDP){
    var objectRemoteSDP = JSON.parse(remoteSDP);
    peer.setRemoteDescription(new RTCSessionDescription(objectRemoteSDP), function(){
        console.log('all done!');
    }, function(err){
        console.log('boardcast setremote sdp fail:', err);
    })
}

ws.onmessage = function(data){
    var socket_data = JSON.parse(data.data);

    wsCallbacks[socket_data.name] && wsCallbacks[socket_data.name](socket_data['data']);
}

and client html

var video = document.getElementById('client');
var peer = new webkitRTCPeerConnection(null);
var ws = new WebSocket('ws://localhost:4080');
var wsCallbacks = {};

function socket_format(evt_name, data){
  return JSON.stringify({name: evt_name, data: data});
}

peer.onaddstream = function(evt){
    // client side play the stream
    video.autoplay = true;
    var blob_url = URL.createObjectURL(evt.stream);
    video.src = blob_url;
}

wsCallbacks['join'] = function(data){
    console.log('server say:', data);

    ws.send(socket_format('client connect'));
}

wsCallbacks['client remote description'] = function(SDP){
    var objectRemoteSDP = JSON.parse(SDP);
    peer.setRemoteDescription(new RTCSessionDescription(objectRemoteSDP), function(){
        peer.createAnswer(function(answerSDP){
            peer.setLocalDescription(answerSDP, function(){
                ws.send(socket_format('client local description', answerSDP));
            }, function(){});
        });
    });
}

wsCallbacks['server client done'] = function(){
    console.log('client all done!');
}

ws.onmessage = function(data){
    var socket_data = JSON.parse(data.data);

    wsCallbacks[socket_data.name] && wsCallbacks[socket_data.name](socket_data['data']);
}
vmolsa commented 8 years ago

Thanks! :) btw setting WebRTC.setDebug(true) gives you lot of messages but last 10 lines shows that what was going on before sigsegv..

You are setting STREAM in

boardcast.onaddstream = function(stream){
          STREAM = stream;

And reusing it in

case 'client connect':
   // create client peer
   client = new webRTC.RTCPeerConnection(null, {audio: true, video: true});
   client.addStream(STREAM);

During that time STREAM loses reference. For now until i fix that reference you could use something like.

case 'client connect':
  // create client peer
  client = new webRTC.RTCPeerConnection(null, {audio: true, video: true});
  boardcast.getRemoteStreams().forEach(function(stream) {
    client.addStream(stream);
  });
kevinkindom commented 8 years ago

wow, when i setting WebRTC.setDebug(true), i got many logs, but the logs can't help me...

and, i update my code, it still crash :(

my code success run in your environment?

vmolsa commented 8 years ago

Hi, I created example with using headq-rtc and video streaming is working with webrtc-native.

npm install headq-rtc
cd node_modules/headq-rtc/examples/broadcast/
npm install
node server.js

Example is giving wrong url. correct one is http://localhost:8080/examples/broadcast

shahraship commented 8 years ago

+1