UNPKG

@bowbee/peer-lite

Version:

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

17 lines (11 loc) 9.3 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('webrtc-adapter')) : typeof define === 'function' && define.amd ? define(['webrtc-adapter'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Peer = factory(global.a)); })(this, (function (a) { 'use strict'; class EventEmitter{constructor(){this.eventMap={};}emit(d){for(var b=arguments.length,e=new Array(b>1?b-1:0),a=1;a<b;a++)e[a-1]=arguments[a];let c=this.eventMap[d];return !!c&&(c.forEach(a=>{a(...e);}),!0)}on(a,c){var b;return this.eventMap[a]=null!==(b=this.eventMap[a])&& void 0!==b?b:[],this.eventMap[a].push(c),this}off(d,e){var b;let c=null!==(b=this.eventMap[d])&& void 0!==b?b:[];for(let a=c.length-1;a>=0;a-=1)if(c[a]===e){c.splice(a,1);break}return this}offAll(a){if(a){let b=this.eventMap[a];if(!b)return this;delete this.eventMap[a];}else this.eventMap={};return this}} function getDefaultCamConstraints(){let a={},b=navigator.mediaDevices.getSupportedConstraints();b.facingMode&&(a.facingMode="user"),b.frameRate&&(a.frameRate={max:30});let c=!(Object.keys(a).length>0)||a;return {audio:!0,video:c}}function randomHex(b){let a=new Uint8Array(b);return crypto.getRandomValues(a),Array.from(a).map(a=>a.toString(16).padStart(2,"0")).join("")}function getSenderForTrack(a,b){return a.getSenders().filter(a=>a.track===b)[0]}function removeTrack(a,b){let c=!(arguments.length>2)|| void 0===arguments[2]||arguments[2];a.getTracks().filter(a=>a===b).forEach(b=>{c&&b.stop(),a.removeTrack(b);});} a.browserDetails.browser;class g{constructor(a){this.streamLocal=new MediaStream,this.channels=new Map,this.channelsPending=new Map,this.emitter=new EventEmitter,this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.options={batchCandidates:!0,batchCandidatesTimeout:200,id:randomHex(4),config:{iceServers:[{urls:["stun:stun.l.google.com:19302"]}]},offerOptions:{},enableDataChannels:!1,channelLabel:randomHex(20),channelOptions:{},sdpTransform:a=>a},this.options={...this.options,...a},this.peer=this.init();}init(){if("new"===this.status())return this.peer;this.destroy(),this.peer=new RTCPeerConnection(this.options.config);let a=[],b;function c(){clearTimeout(b),a.length=0;}return this.peer.onicecandidate=d=>{(null==d?void 0:d.candidate)&&(this.options.batchCandidates?(clearTimeout(b),a.push(d.candidate),"complete"===this.peer.iceGatheringState?this.emit("onicecandidates",a):b=setTimeout(()=>{a.length&&(this.emit("onicecandidates",a),c());},this.options.batchCandidatesTimeout)):this.emit("onicecandidates",[d.candidate]));},this.peer.ontrack=a=>{a.streams&&this.emit("streamRemote",a.streams[0]);},this.peer.oniceconnectionstatechange=()=>{switch(this.emit("status",this.status()),this.status()){case"closed":case"failed":case"disconnected":c(),this.destroy();break;case"checking":this.emit("connecting");break;case"connected":this.emit("connected");}},this.peer.onnegotiationneeded=async()=>{try{if(!this.isActive)return;this.makingOffer=!0;let{offerOptions:c,sdpTransform:d}=this.options,a=await this.peer.createOffer(c);if("stable"!==this.peer.signalingState)return;a.sdp=a.sdp&&d(a.sdp),await this.peer.setLocalDescription(a),this.peer.localDescription&&this.emit("signal",this.peer.localDescription);}catch(b){b instanceof Error&&this.error("Failed in negotiationNeeded",b);}finally{this.makingOffer=!1;}},this.peer.ondatachannel=b=>{let{channel:a}=b;this.options.enableDataChannels&&(this.channels.set(a.label,a),this.addDataChannelEvents(a));},this.peer}start(){let{polite:b=!0}=arguments.length>0&& void 0!==arguments[0]?arguments[0]:{};try{"have-local-offer"===this.peer.signalingState&&this.destroy(),this.isClosed()&&this.init(),this.isActive=!0,this.polite=b,this.syncStreams(),this.syncChannels();}catch(a){if(a instanceof Error)throw this.error("Failed to start",a),a}}async signal(b){try{this.isClosed()&&this.init(),this.isActive=!0;let d="offer"===b.type&&(this.makingOffer||"stable"!==this.peer.signalingState);if(this.ignoreOffer=!this.polite&&d,this.ignoreOffer)return;if(await this.peer.setRemoteDescription(b),"offer"===b.type){this.syncStreams(),this.syncChannels();let a=await this.peer.createAnswer();a.sdp=a.sdp&&this.options.sdpTransform(a.sdp),await this.peer.setLocalDescription(a),this.emit("signal",a);}this.polite=!0;}catch(c){if(c instanceof Error)throw this.error("Failed to signal",c),c}}async addIceCandidate(b){try{await this.peer.addIceCandidate(b);}catch(a){if(!this.ignoreOffer&&a instanceof Error)throw this.error("Failed to addIceCandidate",a),a}}send(b){let c=arguments.length>1&& void 0!==arguments[1]?arguments[1]:this.options.channelLabel,a=this.channels.get(c);return (null==a?void 0:a.readyState)==="open"&&!!b&&(a.send(b),this.emit("channelData",{channel:a,data:b,source:"outgoing"}),!0)}addDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel,b=arguments.length>1&& void 0!==arguments[1]?arguments[1]:{};if(!this.options.enableDataChannels){this.error('Failed to addDataChannel as "enableDataChannels" is false');return}if(this.isClosed()){this.error("Failed to addDataChannel as peer connection is closed");return}this.channels.has(a)||this.channelsPending.set(a,b),this.isActive&&this.createDataChannels();}getDataChannel(){let a=arguments.length>0&& void 0!==arguments[0]?arguments[0]:this.options.channelLabel;return this.channels.get(a)}createDataChannels(){try{Array.from(this.channelsPending.entries()).forEach(c=>{let[a,d]=c,b=this.peer.createDataChannel(a,d);this.channels.set(a,b),this.addDataChannelEvents(b);}),this.channelsPending.clear();}catch(a){if(a instanceof Error)throw this.error("Failed to createDataChannels",a),a}}addDataChannelEvents(a){a.onopen=()=>this.emit("channelOpen",{channel:a}),a.onerror=b=>{this.emit("channelError",{channel:a,event:b});},a.onclose=()=>{this.channels.delete(a.label),this.emit("channelClosed",{channel:a});},a.onmessage=b=>{this.emit("channelData",{channel:a,data:b.data,source:"incoming"});};}destroy(){this.isClosed()||(this.polite=!0,this.isActive=!1,this.makingOffer=!1,this.ignoreOffer=!1,this.channels.clear(),this.channelsPending.clear(),this.peer.close(),this.emit("disconnected"));}status(){var a,b;return null!==(b=null===(a=this.peer)|| void 0===a?void 0:a.iceConnectionState)&& void 0!==b?b:"closed"}isConnected(){return "connected"===this.status()}isClosed(){return "closed"===this.status()}get(){return this.peer}getStreamLocal(){return this.streamLocal}error(a,b){this.emit("error",{id:this.options.id,message:a,error:b});}syncStreams(){this.streamLocal.getTracks().forEach(a=>{let b=getSenderForTrack(this.peer,a);b||this.peer.addTrack(a,this.streamLocal);});}syncChannels(){let{channelLabel:a,channelOptions:b,enableDataChannels:c}=this.options;c&&this.addDataChannel(a,b);}addStream(a){let b=arguments.length>1&& void 0!==arguments[1]&&arguments[1],c=!(arguments.length>2)|| void 0===arguments[2]||arguments[2];b&&this.removeTracks(this.streamLocal.getTracks(),c),a.getTracks().forEach(a=>this.addTrack(a));}removeStream(a){let b=!(arguments.length>1)|| void 0===arguments[1]||arguments[1];this.removeTracks(a.getTracks(),b);}addTrack(b){try{this.streamLocal.addTrack(b),this.emit("streamLocal",this.streamLocal),this.isActive&&this.peer.addTrack(b,this.streamLocal);}catch(a){if(a instanceof Error)throw this.error("Failed to addTrack",a),a}}removeTrack(a){let c=!(arguments.length>1)|| void 0===arguments[1]||arguments[1];if(removeTrack(this.streamLocal,a,c),this.isActive){let b=getSenderForTrack(this.peer,a);b&&this.peer.removeTrack(b);}}removeTracks(a){let b=!(arguments.length>1)|| void 0===arguments[1]||arguments[1];a.forEach(a=>this.removeTrack(a,b));}async replaceTrack(a,c){let g=!(arguments.length>2)|| void 0===arguments[2]||arguments[2];try{if(this.isActive){let e=getSenderForTrack(this.peer,a);e?(removeTrack(this.streamLocal,a,g),this.streamLocal.addTrack(c),await e.replaceTrack(c),this.emit("streamLocal",this.streamLocal)):this.error(`Failed to find track to replace: ${a.id}`);}}catch(b){if(b instanceof Error)throw this.error("Failed to replaceTrack",b),b}}on(a,b){return this.emitter.on(a,b)}off(a,b){return this.emitter.off(a,b)}offAll(a){return this.emitter.offAll(a)}emit(d){for(var b=arguments.length,c=new Array(b>1?b-1:0),a=1;a<b;a++)c[a-1]=arguments[a];return this.emitter.emit(d,...c)}static getUserMedia(a){return navigator.mediaDevices.getUserMedia({...getDefaultCamConstraints(),...a})}static checkBrowserSupport(){let b={rtcPeerConnection:"undefined"!=typeof RTCPeerConnection,getUserMedia:!!(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia),mediaDevices:void 0!==navigator.mediaDevices,mediaStream:"undefined"!=typeof MediaStream,rtcDataChannel:"undefined"!=typeof RTCDataChannel,supportedBrowser:["chrome","firefox","safari","edge"].includes(a.browserDetails.browser||"")};return {supported:Object.values(b).every(Boolean),details:b}}static getBrowserDetails(){let b=a.browserDetails.browser||"unknown",c=a.browserDetails.version||0;return {browser:b,version:c,isUnifiedPlan:c>=(a=>{switch(a){case"firefox":return 59;case"chrome":return 75;case"safari":return 12;default:return 0}})(b)}}} return g; })); //# sourceMappingURL=index.js.map