Giter Site home page Giter Site logo

rtcpeerconnection's Introduction

RTCPeerConnection

What is this?

A tiny browser module that normalizes and simplifies the API for WebRTC peer connections.

It gives us a cleaner (cross-browser) way to handle offer/answer and is based on an event emitter.

If you're not using browserify or you want AMD support use rtcpeerconnection.bundle.js.

Installing

npm install rtcpeerconnection

How to use it

Instantiation

Instantiation takes the same options as a normal peer connection constructor:

var PeerConnection = require('rtcpeerconnection');


// init it like a normal peer connection object
// passing in ice servers/constraints the initial server config
// also takes a couple other options:
// debug: true (to log out all emitted events)
var pc = new PeerConnection({config servers as usual}, {constraints as to regular PC});

Events

Unlike stock Peer Connections this inherits from a generic event emitter. Powered by WildEmitter which has a very familiar API if you're used to node.js/jQuery/Backbone but also includes a wildcard handler so you can easily debug events. Just do emitter.on('*') to log them out or whatnot.

But instead of doing pc.onicecandidate = function () {} on a peer connection you listen for events like this:

// ice candidates
pc.on('ice', function (candidate) {
    // it's your job to send these to someone
    connection.send('ice', candidate);
});

// you can listen for end of candidates (not particularly useful)
pc.on('endOfCandidates', function () {
    // no more ice candidates
});

// remote stream added
pc.on('addStream', function (event) {
    // do something with event.stream
    // probably attach it to a <video> element
    // and play it.
});

// remote stream removed
pc.on('removeStream', function (event) {
    // remote stream removed
    // now you could hide/disable removed video
});

// you can chose to listen for events for 
// offers and answers instead, if you prefer 
pc.on('answer', function (err, answer) { ... });
pc.on('offer', function (err, offer) { ... });

// on peer connection close
pc.on('close', function () { ... });

Methods

Note that all callbacks follow the "error first" convention. Meaning, rather than pass a success and fail callback, you pass a single callback.

If there is an error, the first argument passed to the callback will be a truthy value (the error itself).

The whole offer/answer cycle looks like this:

// assumptions
var pc = new PeerConnection(config, constraints);
var connection = new RealTimeConnection(); // could be socket.io or whatever


// create an offer
pc.offer(function (err, offer) {
    if (!err) connection.send('offer', offer)
});

// you can also optionally pass in constraints
// when creating an offer.
pc.offer(
    {
        offerToReceiveAudio: true,
        offerToReceiveVideo: false
    }, 
    function (err, offer) {
        if (!err) connection.send('offer', offer);
    }
);

// when you recieve an offer, you can answer
// with various options
connection.on('offer', function (offer) {
    // let the peerconnection handle the offer
    // by calling handleOffer
    pc.handleOffer(offer, function (err) {
        if (err) {
            // handle error
            return;
        }

        // you can just call answer
        pc.answer(function (err, answer) {
            if (!err) connection.send('answer', answer);
        });

        // you can call answer with contstraints
        pc.answer(MY_CONSTRAINTS, function (err, answer) {
            if (!err) connection.send('answer', answer);
        });    

        // or you can use one of the shortcuts answers

        // for video only
        pc.answerVideoOnly(function (err, answer) { ... });

        // and audio only
        pc.answerAudioOnly(function (err, answer) { ... });
    }); 
});

// when you get an answer, you just call
// handleAnswer
connection.on('answer', function (answer) {
    pc.handleAnswer(answer);
});

// the only other thing you have to do is listen, transmit, and process ice candidates

// you have to send them when generated
pc.on('ice', function (candidate) {
    connection.send('ice', candidate);
});

// process incoming ones
connection.on('ice', function (candidate) {
    pc.processIce(candidate);
});

That's it!

More

If you want higher level functionality look at SimpleWebRTC that uses this library.

License

MIT

Credits

If you like this, follow: @HenrikJoreteg on twitter.

rtcpeerconnection's People

Contributors

eiriksm avatar fippo avatar henrikjoreteg avatar itsazzad avatar jensengar avatar kenny-house avatar legastero avatar tgabi333 avatar tommoor avatar wpp avatar xdumaine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rtcpeerconnection's Issues

a method to confirm connection

Thanks for the library.

Is there a direct way to find out if a connection is closed or not?

Also, if the close event has been called, is it safe to assume the connection is completely dead and needs to be started again?

transport-info with two content elements causes "callback already called" error

<iq xmlns="jabber:client" from="[email protected]" id="..." to="[email protected]/balcony" type="set">
  <jingle xmlns="urn:xmpp:jingle:1" action="transport-info" initiator="[email protected]" sid="...">
    <content creator="initiator" name="audio">
      <transport xmlns="urn:xmpp:jingle:transports:ice-udp:1">
        <gathering-complete>
        </gathering-complete>
      </transport>
    </content>
    <content creator="initiator" name="video">
      <transport xmlns="urn:xmpp:jingle:transports:ice-udp:1">
        <gathering-complete>
        </gathering-complete>
      </transport>
    </content>
  </jingle>
</iq>

At https://github.com/otalk/RTCPeerConnection/blob/master/rtcpeerconnection.js#L327 we call the callback provided to processIce but this is in a forEach on contents

Callback called twice

in _answer, if assumeSetLocalSuccess is true, but the call to setLocalDescription calls the error callback, the callback to _answer is called twice.

The code breaks when running in node

I'm trying to use the package with node.js unsuccessfully.
The code fails in traceablepeerconnection package (version 1.1.5 - latest)

after running these lines:

var PeerConnection = require('rtcpeerconnection');
var pc = new PeerConnection();

you receive this exception

../node_modules/rtcpeerconnection/node_modules/traceablepeerconnection/index.js:35
    this.peerconnection = new window.RTCPeerConnection(config, constraints);
                              ^

ReferenceError: window is not defined
    at new TraceablePeerConnection (.../node_modules/rtcpeerconnection/node_modules/traceablepeerconnection/index.js:35:31)
    at new PeerConnection (.../node_modules/rtcpeerconnection/rtcpeerconnection.js:115:15)
    at Object.<anonymous> (.../server.js:148:10)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:134:18)
    at node.js:961:3
29 Oct 20:56:12 - [nodemon] app crashed - waiting for file changes before starting..

how to create answer with ICE restart when a offer received

Scenario:
Create offer
set local description
Received answer
set remote description
ICE & DTLS negation success and audio works fine.'
Received offer with new ice/dtls credentials
set remote description
Create answer with restart ICE with new credentials (Not working)
send answer.

Adding ICE Candidate while signaling state is `have-local-offer` causes exception

I'm running into an error where I'm receiving an ice candidate prior to receiving the remote description (i.e., jingle transport-info before jingle session-accept). The error is occurring here. It could be avoided by adding another check to return if signaling state is have-local-offer. it's a crazy race condition with the xmpp server that's causing these to come in out of order, and could set me up for missing that candidate though... thoughts @fippo?

https://github.com/otalk/RTCPeerConnection/blob/master/rtcpeerconnection.js#L246

message flow

Is there a recommended/standard message flow from User A to User B? a diagram etc?

I am a bit confused on the order of PeerConnection object creation, create offer etc.

errors and warnings in FF

I'm getting the following errors and warnings on receiving "ICE" candidates from singling server

RTCIceServer.url is deprecated! Use urls instead. rtcpeerconnection.bundle.js:6265

TURNS is not yet supported. rtcpeerconnection.bundle.js:6265

onaddstream is deprecated! Use peerConnection.ontrack instead.  rtcpeerconnection.bundle.js:6274

TypeError: update.candidate.candidate is undefined  rtcpeerconnection.bundle.js:6455:1
Data received for ice: {"candidate":"candidate:1201536341 1 udp 25108991 xx.yy.zzz.79 55964 typ relay raddr xx.yy.zzz.5 rport 55786 generation 0 ufrag ZZjb network-id 2 network-cost 50","sdpMid":"video","sdpMLineIndex":1}

I used the most recent files.

Use new constraints format

var constraints = {
    mandatory: {
        OfferToReceiveAudio: true,
        OfferToReceiveVideo: true
    }
}

Should now just be

var constraints = {
    offerToReceiveAudio: true,
    offerToReceiveVideo: true,
}

What is the format for ice and offer/answer events?

I'm trying to integrate this library with a different RTC library, and I was just wonder about what the format of the events actually is so that I can modify it so the two libraries can talk to each other.

Nothing happens after offer/answer cycle finishes

I successfully managed to complete the offer/answer cycle between 2 clients. However, I don't see any relevant events (*streams) being triggered after that.

I also have a wildcard event catcher that is catching undocumented events like "iceConnectionStateChange" etc and I also noticed the offer/answer events get called on PeerConnection.

I'm also running PC.handleAnswer on answer.

What could be wrong?

Socket.io over NodeJS for signaling

Hi, I want to use this library with socket.io running on a nodejs server.. Also in the client I would like to use socket.io-client implementation..
Is it possible? Can you show me an example code?

Thanks in advance!

getting error while running below code

I have tried to create peer connection using below code. I am getting the error as attached in the screen shot. Please correct me anything wrong

var PeerConnection = require('../rtcpeerconnection');
pc1 = new PeerConnection({url: 'stun:stun.l.google.com:19302'}, {});

Error Message:
C:\Node1\node_modules\rtcpeerconnection\node_modules\traceablepeerconnection\ind
ex.js:35
this.peerconnection = new webrtc.PeerConnection(config, constraints);
^
TypeError: undefined is not a function

I am using windows 7 OS and I installed node module using npm install rtcpeerconnection
rtcerror

adapter.js

Do I need to include adapter.js before this lib or it comes with adapter.js?

The latest adapter.js version is 3.2.0

Screen stream from firefox to chrome

When i try to add screen share stream to established peer connection(with audio and video data), from firefox to chrome, on the chrome side i have an erorr: "Failed to initialize the answer".
Offer that chrome receive is :
"v=0
↵o=mozilla...THIS_IS_SDPARTA-42.0 1756619254475437899 1 IN IP4 0.0.0.0
↵s=-
↵t=0 0
↵a=fingerprint:sha-256 17:CC:6A:29:61:D5:8B:77:A7:24:D3:BA:D9:DD:01:B9:C7:9E:0A:4E:42:48:6C:36:EF:46:9D:2C:FC:51:6A:A5
↵a=group:BUNDLE sdparta_0 sdparta_1 sdparta_2
↵a=ice-options:trickle
↵a=msid-semantic:WMS *
↵m=audio 54693 RTP/SAVPF 109 9 0 8
↵c=IN IP4 206.54.171.168
↵a=candidate:0 1 UDP 2122252543 192.168.1.11 61907 typ host
↵a=candidate:1 1 UDP 1686052863 195.88.113.136 61907 typ srflx raddr 192.168.1.11 rport 61907
↵a=candidate:2 1 UDP 92217343 206.54.171.168 54693 typ relay raddr 206.54.171.168 rport 54693
↵a=sendrecv
↵a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
↵a=ice-pwd:e3d38d1f3271f1922b53ee3a0c329aaf
↵a=ice-ufrag:970059ba
↵a=mid:sdparta_0
↵a=msid:{06639e53-45f3-42a8-a6cc-644778c6d471} {d6ad0fcd-f160-4752-a2de-c061afd5ab75}
↵a=rtcp-mux
↵a=rtpmap:109 opus/48000/2
↵a=rtpmap:9 G722/8000/1
↵a=rtpmap:0 PCMU/8000
↵a=rtpmap:8 PCMA/8000
↵a=setup:actpass
↵a=ssrc:3934791550 cname:{9af297ab-4ada-47d2-81e4-919931391eb6}
↵m=video 9 RTP/SAVPF 120 126 97
↵c=IN IP4 0.0.0.0
↵a=sendrecv
↵a=fmtp:120 max-fs=12288;max-fr=60
↵a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
↵a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
↵a=ice-pwd:e3d38d1f3271f1922b53ee3a0c329aaf
↵a=ice-ufrag:970059ba
↵a=mid:sdparta_1
↵a=msid:{06639e53-45f3-42a8-a6cc-644778c6d471} {07fc56ab-4378-4012-b009-1b12c1992ba9}
↵a=rtcp-fb:120 nack
↵a=rtcp-fb:120 nack pli
↵a=rtcp-fb:120 ccm fir
↵a=rtcp-fb:126 nack
↵a=rtcp-fb:126 nack pli
↵a=rtcp-fb:126 ccm fir
↵a=rtcp-fb:97 nack
↵a=rtcp-fb:97 nack pli
↵a=rtcp-fb:97 ccm fir
↵a=rtcp-mux
↵a=rtpmap:120 VP8/90000
↵a=rtpmap:126 H264/90000
↵a=rtpmap:97 H264/90000
↵a=setup:actpass
↵a=ssrc:3229964890 cname:{9af297ab-4ada-47d2-81e4-919931391eb6}
↵m=video 9 RTP/SAVPF 120 126 97
↵c=IN IP4 0.0.0.0
↵a=bundle-only
↵a=sendonly
↵a=fmtp:120 max-fs=12288;max-fr=60
↵a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
↵a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
↵a=ice-pwd:e3d38d1f3271f1922b53ee3a0c329aaf
↵a=ice-ufrag:970059ba
↵a=mid:sdparta_2
↵a=msid:{3f4c297b-50e3-4f4b-b350-37de1be1c469} {a36a8f86-51a5-4a39-a115-4bc669d2b8d4}
↵a=rtcp-fb:120 nack
↵a=rtcp-fb:120 nack pli
↵a=rtcp-fb:120 ccm fir
↵a=rtcp-fb:126 nack
↵a=rtcp-fb:126 nack pli
↵a=rtcp-fb:126 ccm fir
↵a=rtcp-fb:97 nack
↵a=rtcp-fb:97 nack pli
↵a=rtcp-fb:97 ccm fir
↵a=rtcp-mux
↵a=rtpmap:120 VP8/90000
↵a=rtpmap:126 H264/90000
↵a=rtpmap:97 H264/90000
↵a=setup:actpass
↵a=ssrc:3162226236 cname:{9af297ab-4ada-47d2-81e4-919931391eb6}
↵"
In other combinations of browsers all is ok.

Streaming video does not work for some combination of browsers

I stream between two browser sites, one is called master and the other is called slave.
Master streams video to slave.
Master is always active, slave sometimes connects.

On both sides, the RTCPeerConnection is initiated in this way:

pc = new PeerConnection(
        {'iceServers': [{'url': isChrome ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121'}]},
        {'optional': [{'DtlsSrtpKeyAgreement': true},{'RtpDataChannels': true}]});

Master sends offer for receiving no audio and no video:

      pc.offer({
        mandatory: {
          OfferToReceiveAudio: false,
          OfferToReceiveVideo: false
        }
      }, function (err, offer) {
         ...
        }
      );

Slave handles offer and answers with offer for receiving video:

  pc.handleOffer(offer, function (err) {
      pc.answer({
        mandatory: {
          OfferToReceiveAudio: false,
          OfferToReceiveVideo: true
        }
      }, function (err, answer) {
         ...
      });
  });

Master handles answer:

pc.handleAnswer(answer);

Ice candidates are processed on both sides.
Video is attached to peer connection before sending offer.

I tested it to work with following combination of Master->Slave:
Andorid Chrome->Linux Chrome - works
Android Chrome->Linux Firefox - works
Andorid Firefox->Linux Firefox - works
Android Firefox->Linux Chrome - doesn't work
Linux Chrome->Linux Chrome - works
Linux Chrome->Linux Firefox - works
Linux Firefox->Linux Firefox - works
Linux Firefox->Linux Chrome - doesn't work
Linux Chrome->Windows Chrome - doesn't work
Linux Chrome->Windows Firefox - works
Linux Firefox->Windows Firefox - works
Linux Firefox->Windows Chrome - doesn't work

Why the hell it does not work for those combinations? No error is given. Everything looks ordinary as normal, but the video element on slave is blank.

close event doesn't fire when other person closes their browser

Instead it waits a few second then a PeerConnectionTrace event is emitted

Event value:

{
  time: Mon May 26 2014 17:55:44 GMT-0700 (MST),
  type: "oniceconnectionstatechange",
  value: "disconnected"
}

so somewhere it recognizes that it disconnected, but the proper event isn't fired.

What is the format of the constraints?

I'm a little confused as to what the format for the various constraints are. What exactly are the constraints in the constructor? It mentions that they're "constraints as to regular PC" but there doesn't seem to be a link as to where I can find those constraints. The other constraints that I'm a little confused about are the ones taken by peerconnection.answer(); would it be possible to link to those in the documentation as well?
Also, where would one attach their local stream to send it to the other user?

moz-prefix deprecated

WebRTC-Interface with "moz"-Prefix (mozRTCPeerConnection, mozRTCSessionDescription, mozRTCIceCandidate) should not be used anymore

Package fails after running

Hi,

I'm trying to use this package in my node server.
Unfortunately the package fails to run, since it depends on traceable peer connection,
and traceablepeerconnection uses window.

Do you have any solution for this manner.

can I use this without a browser?

this.peerconnection = new window.RTCPeerConnection(config, constraints);
                              ^
ReferenceError: window is not defined
    at new TraceablePeerConnection (/intermidiate/node_modules/rtcpeerconnection/node_modules/traceablepeerconnection/index.js:35:31)
    at new PeerConnection (/home/tal/Code/WebstormProjects/intermidiate/node_modules/rtcpeerconnection/rtcpeerconnection.js:115:15)
    at makeOffer (/intermidiate/public/serverless-webrtc-create/serverless-webrtc.js:79:8)
    at Object.<anonymous> (/intermidiate/public/serverless-webrtc-create/serverless-webrtc.js:130:1)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)

two peerconnections share the same underlying connection

Test case:

  • User A connects to User B
  • User A closes, PeerConnection is closed now
  • User A attempts to connect to User B
Uncaught InvalidStateError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': The RTCPeerConnection's signalingState is 'closed'. 

super weird, still trying to dig around but I've compared references all the way down and it doesn't seem like any of the libraries are responsible

Chrome 35.0.1916.114 on OSX

RTCPeerConnection without requireJS

Is it possible to use this lib without using requireJS (I have a AngularJS setup and read about some issues using AngularJS with requireJS)

Firefox issue when _onIce called

Hi Guys, i am using your cool stanza.io, and during filetransfer testing i find out that it is not working between Chrome and Firefox, and during investigation i came to the point that issue is in rtcpeerconnection (we all know that issue is in Firefox) but nevertheless:

if (!ice.sdpMid) { // firefox doesn't set this
    ice.sdpMid = self.localDescription.contents[ice.sdpMLineIndex].name;
}

settings sdpMid to"data", then goes:

 if (!self.config.ice[ice.sdpMid]) 
, which must fix everything, but
SJJ.toSessionJSON(self.pc.localDescription.sdp, bla bla bla
parse m=, and setting content to application, we end's up with the situation where ice.sdpMid = "data", but self.config.ice have only "application" key, and this cause to fail next code:

                       
ufrag: self.config.ice[ice.sdpMid].ufrag,
pwd: self.config.ice[ice.sdpMid].pwd,

with: "TypeError: self.config.ice[ice.sdpMid] is undefined".
Any ideas how to fix this? If i can somehow help you just let me know. I am not an WebRTC expert so i can only guessing what is going on here. Thank you very much for attention.

Firefox: "Mandatory/optional in createOffer options no longer works!"

Code to reproduce:

var pc = new RTCPeerConnection({
  iceServers: [
    {
      urls: 'stun:stun.l.google.com:19302'
    }
  ]
});
pc.offer(function(err, offer) {
  console.log(err);
});

Console output:

Mandatory/optional in createOffer options no longer works! Use {"offerToReceiveAudio":true,"offerToReceiveVideo":true} instead (note the case difference)! <unknown>
DOMException [InternalError: "Cannot create an offer with no local tracks, no offerToReceiveAudio/Video, and no DataChannel."
code: 0
nsresult: 0x0]

Can we catch that exception in createOffer, create a new constraints object that FF will support, and try again?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.