npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

peer-lite

v2.0.2

Published

Lightweight WebRTC browser library that supports video, audio and data channels

Downloads

125

Readme

PeerLite

CircleCI

Lightweight WebRTC browser library that supports video, audio and data channels.

Features

  • Lightweight! 3kb (gzipped)
  • Zero dependencies
  • Ships with TypeScript definitions
  • Uses modern WebRTC APIs
  • "Perfect negotiation" pattern
  • Support for renegotiation of connection
  • ICE candidate batching

Installation

yarn add peer-lite

Usage

Two peers connecting locally

import Peer from 'peer-lite';

const peer1 = new Peer();
const peer2 = new Peer();

peer1.on('signal', async (description) => {
  await peer2.signal(description);
})

peer2.on('signal', async (description) => {
  await peer1.signal(description);
})

peer1.on('onicecandidates', async (candidates) => {
  const promises = candidates.map(async candidate => peer2.addIceCandidate(candidate));
  await Promise.all(promises);
});

peer2.on('onicecandidates', async (candidates) => {
  const promises = candidates.map(async candidate => peer1.addIceCandidate(candidate));
  await Promise.all(promises);
});

peer1.on('streamRemote', (stream) => {
  document.querySelector('#video1').srcObject = stream;
});

peer2.on('streamRemote', (stream) => {
  document.querySelector('#video2').srcObject = stream;
});

(async () => {
  const stream = await Peer.getUserMedia();
  peer1.addStream(stream);
  peer2.addStream(stream);
  peer1.start();
})();

Peer connection with fake signalling server

import Peer from 'peer-lite';

const peer = new Peer();
const fakeSocket = new Socket();

// Peer events

peer.on('signal', async (description) => {
  fakeSocket.emit('signal', description);
});

peer.on('onicecandidates', async (candidates) => {
  fakeSocket.emit('onicecandidates', candidates);
});

peer.on('streamLocal', (stream) => {
  document.querySelector('#videoLocal').srcObject = stream;
});

peer.on('streamRemote', (stream) => {
  document.querySelector('#videoRemote').srcObject = stream;
});

// Socket events

fakeSocket.on('signal', async (description) => {
  await peer.signal(description);
});

fakeSocket.on('onicecandidates', async (candidates) => {
  const promises = candidates.map(async candidate => peer.addIceCandidate(candidate));
  await Promise.all(promises);
});

(async () => {
  const stream = await Peer.getUserMedia();
  peer.addStream(stream);
  peer.start();
})();

Examples

See more examples here with signalling server.

API

Constructor

new Peer(Options)

Peer Options

interface PeerOptions {
  /** Enable support for batching ICECandidates */
  batchCandidates?: boolean;
  /** Timeout in MS before emitting batched ICECandidates */
  batchCandidatesTimeout?: number;
  /** Peer id used when emitting errors */
  id?: string;
  /** RTCPeerConnection options */
  config?: RTCConfiguration;
  /** RTCOfferOptions options */
  offerOptions?: RTCOfferOptions;
  /** Enable support for RTCDataChannels */
  enableDataChannels?: boolean;
  /** Default RTCDataChannel label */
  channelLabel?: string;
  /** Default RTCDataChannel options */
  channelOptions?: RTCDataChannelInit;
  /** Function to transform offer/answer SDP */
  sdpTransform?: (sdp: string) => string;
}

Peer API

interface Peer {
  /** Create a peer instance */
  constructor(options?: PeerOptions);
  /** Initialize the peer */
  init(): RTCPeerConnection;
  /** Start the RTCPeerConnection signalling */
  start({ polite }?: {
      polite?: boolean | undefined;
  }): void;
  /** Process a RTCSessionDescriptionInit on peer */
  signal(description: RTCSessionDescriptionInit): Promise<void>;
  /** Add RTCIceCandidate to peer */
  addIceCandidate(candidate: RTCIceCandidate): Promise<void>;
  /** Send data to connected peer using an RTCDataChannel */
  send(data: string | Blob | ArrayBuffer | ArrayBufferView, label?: string): boolean;
  /** Add RTCDataChannel to peer */
  addDataChannel(label?: string, options?: RTCDataChannelInit): void;
  /** Get RTCDataChannel added to peer */
  getDataChannel(label?: string): RTCDataChannel | undefined;
  /** Close peer if active */
  destroy(): void;
  /** Return the ICEConnectionState of the peer */
  status(): RTCIceConnectionState;
  /** Return true if the peer is connected */
  isConnected(): boolean;
  /** Return true if the peer is closed */
  isClosed(): boolean;
  /** Return the RTCPeerConnection */
  get(): RTCPeerConnection;
  /** Return the local stream */
  getStreamLocal(): MediaStream;
  /** Add stream to peer */
  addStream(stream: MediaStream, replace?: boolean): void;
  /** Remove stream from peer */
  removeStream(stream: MediaStream): void;
  /** Add track to peer */
  addTrack(track: MediaStreamTrack): void;
  /** Remove track on peer */
  removeTrack(track: MediaStreamTrack): void;
  /** Remove tracks on peer */
  removeTracks(tracks: MediaStreamTrack[]): void;
  /** Replace track with another track on peer */
  replaceTrack(track: MediaStreamTrack, newTrack: MediaStreamTrack): Promise<void>;
  on<E extends keyof PeerEvents>(event: E, listener: PeerEvents[E]): TypedEmitter<PeerEvents>;
  off<E extends keyof PeerEvents>(event: E, listener: PeerEvents[E]): TypedEmitter<PeerEvents>;
  offAll<E extends keyof PeerEvents>(event?: E): TypedEmitter<PeerEvents>;
}

Peer Events

interface PeerEvents {
  error: (data: { id: string; message: string; error?: Error }) => void;
  // Connection Status
  connecting: VoidFunction;
  connected: VoidFunction;
  disconnected: VoidFunction;
  status: (status: RTCIceConnectionState) => void;
  // Signal and RTCIceCandidates
  signal: (description: RTCSessionDescriptionInit) => void;
  onicecandidates: (iceCandidates: RTCIceCandidate[]) => void;
  // MediaStreams
  streamLocal: (stream: MediaStream) => void;
  streamRemote: (stream: MediaStream) => void;
  // RTCDataChannel
  channelOpen: (data: { channel: RTCDataChannel }) => void;
  channelClosed: (data: { channel: RTCDataChannel }) => void;
  channelError: (data: { channel: RTCDataChannel; event: RTCErrorEvent }) => void;
  channelData: (data: {
    channel: RTCDataChannel;
    source: 'incoming' | 'outgoing';
    data: string | Blob | ArrayBuffer | ArrayBufferView;
  }) => void;
}

Testing

The tests run inside a headless Chrome and Firefox with Playwright and @playwright/test. These run quickly and allow testing of WebRTC APIs in real browsers.

Run Tests (Chrome only)

yarn test

Run Tests (Chrome + Firefox)

CI=true yarn test

Similar Projects

  • PeerJS: https://github.com/peers/peerjs
  • Simple Peer: https://github.com/feross/simple-peer
  • SimpleWebRTC: https://github.com/andyet/SimpleWebRTC
  • More here: https://stackoverflow.com/questions/24857637/current-state-of-javascript-webrtc-libraries