MCPcopy
hub / github.com/feross/simple-peer

github.com/feross/simple-peer @v9.11.1 sqlite

repository ↗ · DeepWiki ↗ · release v9.11.1 ↗
155 symbols 587 edges 14 files 8 documented · 5%
README

simple-peer ci coveralls npm downloads javascript style guide javascript style guide

Simple WebRTC video, voice, and data channels

Sponsored by    DFINITY

We are hiring a peer-to-peer WebRTC mobile Web application expert.

DFINITY is building an exciting peer-to-peer WebRTC-based mobile Web app to help improve democracy on the Internet Computer blockchain. The mobile web app connects groups of up to four people in a peer-to-peer WebRTC audio and video call so that they can mutually prove unique personhood.

We are looking for a software engineer or consultant who can help us solve (platform-dependent) reliability issues of our implementation. We are interested in applicants with substantial WebRTC experience for mobile Web apps, experience with different communication patterns (e.g., peer-to-peer, server relay), and substantial problem-solving skills. Having experience in automated testing of this type of applications is a plus. Pay is extremely competitive for the right expertise. For details, please see the full job description.

features

  • concise, node.js style API for WebRTC
  • works in node and the browser!
  • supports video/voice streams
  • supports data channel
  • text and binary data
  • node.js duplex stream interface
  • supports advanced options like:
  • enable/disable trickle ICE candidates
  • manually set config options
  • transceivers and renegotiation

This package is used by WebTorrent and many others.

install

npm install simple-peer

This package works in the browser with browserify. If you do not use a bundler, you can use the simplepeer.min.js standalone script directly in a <script> tag. This exports a SimplePeer constructor on window. Wherever you see Peer in the examples below, substitute that with SimplePeer.

usage

Let's create an html page that lets you manually connect two peers:

<html>
  <body>
    <style>
      #outgoing {
        width: 600px;
        word-wrap: break-word;
        white-space: normal;
      }
    </style>
    <form>
      <textarea id="incoming"></textarea>
      <button type="submit">submit</button>
    </form>
    <pre id="outgoing"></pre>
    <script src="https://github.com/feross/simple-peer/raw/v9.11.1/simplepeer.min.js"></script>
    <script>
      const p = new SimplePeer({
        initiator: location.hash === '#1',
        trickle: false
      })

      p.on('error', err => console.log('error', err))

      p.on('signal', data => {
        console.log('SIGNAL', JSON.stringify(data))
        document.querySelector('#outgoing').textContent = JSON.stringify(data)
      })

      document.querySelector('form').addEventListener('submit', ev => {
        ev.preventDefault()
        p.signal(JSON.parse(document.querySelector('#incoming').value))
      })

      p.on('connect', () => {
        console.log('CONNECT')
        p.send('whatever' + Math.random())
      })

      p.on('data', data => {
        console.log('data: ' + data)
      })
    </script>
  </body>
</html>

Visit index.html#1 from one browser (the initiator) and index.html from another browser (the receiver).

An "offer" will be generated by the initiator. Paste this into the receiver's form and hit submit. The receiver generates an "answer". Paste this into the initiator's form and hit submit.

Now you have a direct P2P connection between two browsers!

A simpler example

This example create two peers in the same web page.

In a real-world application, you would never do this. The sender and receiver Peer instances would exist in separate browsers. A "signaling server" (usually implemented with websockets) would be used to exchange signaling data between the two browsers until a peer-to-peer connection is established.

data channels

var Peer = require('simple-peer')

var peer1 = new Peer({ initiator: true })
var peer2 = new Peer()

peer1.on('signal', data => {
  // when peer1 has signaling data, give it to peer2 somehow
  peer2.signal(data)
})

peer2.on('signal', data => {
  // when peer2 has signaling data, give it to peer1 somehow
  peer1.signal(data)
})

peer1.on('connect', () => {
  // wait for 'connect' event before using the data channel
  peer1.send('hey peer2, how is it going?')
})

peer2.on('data', data => {
  // got a data channel message
  console.log('got a message from peer1: ' + data)
})

video/voice

Video/voice is also super simple! In this example, peer1 sends video to peer2.

var Peer = require('simple-peer')

// get video/voice stream
navigator.mediaDevices.getUserMedia({
  video: true,
  audio: true
}).then(gotMedia).catch(() => {})

function gotMedia (stream) {
  var peer1 = new Peer({ initiator: true, stream: stream })
  var peer2 = new Peer()

  peer1.on('signal', data => {
    peer2.signal(data)
  })

  peer2.on('signal', data => {
    peer1.signal(data)
  })

  peer2.on('stream', stream => {
    // got remote video stream, now let's show it in a video tag
    var video = document.querySelector('video')

    if ('srcObject' in video) {
      video.srcObject = stream
    } else {
      video.src = window.URL.createObjectURL(stream) // for older browsers
    }

    video.play()
  })
}

For two-way video, simply pass a stream option into both Peer constructors. Simple!

Please notice that getUserMedia only works in pages loaded via https.

dynamic video/voice

It is also possible to establish a data-only connection at first, and later add a video/voice stream, if desired.

var Peer = require('simple-peer') // create peer without waiting for media

var peer1 = new Peer({ initiator: true }) // you don't need streams here
var peer2 = new Peer()

peer1.on('signal', data => {
  peer2.signal(data)
})

peer2.on('signal', data => {
  peer1.signal(data)
})

peer2.on('stream', stream => {
  // got remote video stream, now let's show it in a video tag
  var video = document.querySelector('video')

  if ('srcObject' in video) {
    video.srcObject = stream
  } else {
    video.src = window.URL.createObjectURL(stream) // for older browsers
  }

  video.play()
})

function addMedia (stream) {
  peer1.addStream(stream) // <- add streams to peer dynamically
}

// then, anytime later...
navigator.mediaDevices.getUserMedia({
  video: true,
  audio: true
}).then(addMedia).catch(() => {})

in node

To use this library in node, pass in opts.wrtc as a parameter (see the constructor options):

var Peer = require('simple-peer')
var wrtc = require('wrtc')

var peer1 = new Peer({ initiator: true, wrtc: wrtc })
var peer2 = new Peer({ wrtc: wrtc })

api

peer = new Peer([opts])

Create a new WebRTC peer connection.

A "data channel" for text/binary communication is always established, because it's cheap and often useful. For video/voice communication, pass the stream option.

If opts is specified, then the default options (shown below) will be overridden.

{
  initiator: false,
  channelConfig: {},
  channelName: '<random string>',
  config: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }] },
  offerOptions: {},
  answerOptions: {},
  sdpTransform: function (sdp) { return sdp },
  stream: false,
  streams: [],
  trickle: true,
  allowHalfTrickle: false,
  wrtc: {}, // RTCPeerConnection/RTCSessionDescription/RTCIceCandidate
  objectMode: false
}

The options do the following:

  • initiator - set to true if this is the initiating peer
  • channelConfig - custom webrtc data channel configuration (used by createDataChannel)
  • channelName - custom webrtc data channel name
  • config - custom webrtc configuration (used by RTCPeerConnection constructor)
  • offerOptions - custom offer options (used by createOffer method)
  • answerOptions - custom answer options (used by createAnswer method)
  • sdpTransform - function to transform the generated SDP signaling data (for advanced users)
  • stream - if video/voice is desired, pass stream returned from getUserMedia
  • streams - an array of MediaStreams returned from getUserMedia
  • trickle - set to false to disable trickle ICE and get a single 'signal' event (slower)
  • wrtc - custom webrtc implementation, mainly useful in node to specify in the wrtc package. Contains an object with the properties:
  • RTCPeerConnection
  • RTCSessionDescription
  • RTCIceCandidate

  • objectMode - set to true to create the stream in Object Mode. In this mode, incoming string data is not automatically converted to Buffer objects.

peer.signal(data)

Call this method whenever the remote peer emits a peer.on('signal') event.

The data will encapsulate a webrtc offer, answer, or ice candidate. These messages help the peers to eventually establish a direct connection to each other. The contents of these strings are an implementation detail that can be ignored by the user of this module; simply pass the data from 'signal' events to the remote peer and call peer.signal(data) to get connected.

peer.send(data)

Send text/binary data to the remote peer. data can be any of several types: String, Buffer (see buffer), ArrayBufferView (Uint8Array, etc.), ArrayBuffer, or Blob (in browsers that support it).

Note: If this method is called before the peer.on('connect') event has fired, then an exception will be thrown. Use peer.write(data) (which is inherited from the node.js duplex stream interface) if you want this data to be buffered instead.

peer.addStream(stream)

Add a MediaStream to the connection.

peer.removeStream(stream)

Remove a MediaStream from the connection.

peer.addTrack(track, stream)

Add a MediaStreamTrack to the connection. Must also pass the MediaStream you want to attach it to.

peer.removeTrack(track, stream)

Remove a MediaStreamTrack from the connection. Must also pass the MediaStream that it was attached to.

peer.replaceTrack(oldTrack, newTrack, stream)

Replace a MediaStreamTrack with another track. Must also pass the MediaStream that the old track was attached to.

peer.addTransceiver(kind, init)

Add a RTCRtpTransceiver to the connection. Can be used to add transceivers before adding tracks. Automatically called as neccesary by addTrack.

peer.destroy([err])

Destroy and cleanup this peer connection.

If the optional err parameter is passed, then it will be emitted as an 'error' event on the stream.

Peer.WEBRTC_SUPPORT

Detect native WebRTC support in the javascript environment.

var Peer = require('simple-peer')

if (Peer.WEBRTC_SUPPORT) {
  // webrtc support!
} else {
  // fallback
}

duplex stream

Peer objects are instances of stream.Duplex. They behave very similarly to a net.Socket from the node core net module. The duplex stream reads/writes to the data channel.

```js var peer = new Peer(opts) // ... signaling ... peer.write(new Buffer('hey')) peer.on('data', function (chunk) {

Core symbols most depended-on inside this repo

signal
called by 84
index.js
destroy
called by 81
index.js
_debug
called by 41
index.js
send
called by 28
index.js
addStream
called by 17
index.js
negotiate
called by 7
index.js
addTrack
called by 6
index.js
_needsNegotiation
called by 6
index.js

Shape

Method 87
Function 64
Class 4

Languages

TypeScript100%

Modules by API surface

simplepeer.min.js94 symbols
index.js50 symbols
test/trickle.js3 symbols
test/basic.js2 symbols
test/stream.js1 symbols
test/object-mode.js1 symbols
test/binary.js1 symbols
perf/server.js1 symbols
perf/send.js1 symbols
perf/receive.js1 symbols

Dependencies from manifests, versioned

airtap4.0.3 · 1×
airtap-manual1.0.0 · 1×
airtap-sauce1.1.0 · 1×
babel-minify0.5.1 · 1×
bowser2.11.0 · 1×
browserify17.0.0 · 1×
buffer6.0.3 · 1×
coveralls3.1.1 · 1×
debug4.3.2 · 1×
err-code3.0.1 · 1×
get-browser-rtc1.1.0 · 1×
nyc15.1.0 · 1×

For agents

$ claude mcp add simple-peer \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact