├── .gitignore ├── LICENCE ├── README.md ├── browser.js ├── example ├── server.js └── static │ ├── index.html │ └── index.js ├── lib ├── log.js ├── mediaStream.js ├── peerConnection.js ├── simplePeerConnections.js └── webrtcStreams.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | *.err -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Raynos. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webrtc-stream 2 | 3 | Stream video and audio 4 | 5 | ## Example 6 | 7 | See [example folder][1] for more details 8 | 9 | ``` js 10 | var WebRTC = require("webrtc-stream") 11 | , MediaStream = WebRTC.MediaStream 12 | , WebRTCStreams = WebRTC.WebRTCStreams 13 | , DiscoveryNetwork = require("discovery-network") 14 | , Connection = DiscoveryNetwork.Connection 15 | 16 | var localVideo = document.getElementById("local-webrtc") 17 | , remoteVideos = document.getElementById("remote-videos") 18 | 19 | MediaStream.local(localVideo, function (myMediaStream) { 20 | var conn = Connection("http://discoverynetwork.co/service") 21 | 22 | WebRTCStreams(conn, "mediaStreams-demo", myMediaStream, renderStream) 23 | 24 | function renderStream(remotePeerId, stream) { 25 | var remoteVideo = document.createElement("video") 26 | remoteVideo.autoplay = true 27 | remoteVideos.appendChild(remoteVideo) 28 | MediaStream.remote(remoteVideo, stream) 29 | } 30 | }) 31 | ``` 32 | 33 | ## Contributors 34 | 35 | - Raynos 36 | 37 | ## MIT Licenced 38 | 39 | [1]: https://github.com/Raynos/webrtc-stream/tree/master/example 40 | -------------------------------------------------------------------------------- /browser.js: -------------------------------------------------------------------------------- 1 | var MediaStream = require("./lib/mediaStream") 2 | , PeerConnection = require("./lib/peerConnection") 3 | , SimplePeerConnections = require("./lib/simplePeerConnections") 4 | , WebRTCStreams = require("./lib/webrtcStreams") 5 | , log = require("./lib/log") 6 | 7 | module.exports = { 8 | MediaStream: MediaStream 9 | , PeerConnection: PeerConnection 10 | , log: log 11 | , SimplePeerConnections: SimplePeerConnections 12 | , WebRTCStreams: WebRTCStreams 13 | } -------------------------------------------------------------------------------- /example/server.js: -------------------------------------------------------------------------------- 1 | var browserifyServer = require("browserify-server") 2 | 3 | var server = browserifyServer.listen(__dirname, 8080) 4 | 5 | console.log("running on port 8080") -------------------------------------------------------------------------------- /example/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebRTC stream 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/static/index.js: -------------------------------------------------------------------------------- 1 | var WebRTC = require("../../browser") 2 | , MediaStream = WebRTC.MediaStream 3 | , WebRTCStreams = WebRTC.WebRTCStreams 4 | , DiscoveryNetwork = require("discovery-network") 5 | , Connection = DiscoveryNetwork.Connection 6 | 7 | var localVideo = document.getElementById("local-webrtc") 8 | , remoteVideos = document.getElementById("remote-videos") 9 | 10 | WebRTC.log.enabled = true 11 | DiscoveryNetwork.log.enabled = true 12 | 13 | MediaStream.local(localVideo, function (myMediaStream) { 14 | var conn = Connection("http://discoverynetwork.co/service") 15 | 16 | WebRTCStreams(conn, "mediaStreams-demo", myMediaStream, renderStream) 17 | 18 | function renderStream(remotePeerId, stream) { 19 | var remoteVideo = document.createElement("video") 20 | remoteVideo.autoplay = true 21 | remoteVideos.appendChild(remoteVideo) 22 | MediaStream.remote(remoteVideo, stream) 23 | } 24 | }) -------------------------------------------------------------------------------- /lib/log.js: -------------------------------------------------------------------------------- 1 | module.exports = require("browser-log").create() -------------------------------------------------------------------------------- /lib/mediaStream.js: -------------------------------------------------------------------------------- 1 | var getUserMedia = window.navigator.getUserMedia || 2 | window.navigator.webkitGetUserMedia 3 | , URL = window.URL || window.webkitURL 4 | , log = require("./log") 5 | 6 | module.exports = { 7 | local: LocalMediaStream 8 | , remote: RemoteMediaStream 9 | } 10 | 11 | function LocalMediaStream(videoElem, callback) { 12 | log.verbose("LocalMediaStream", arguments) 13 | return getUserMedia.call(navigator, { 14 | video: true 15 | , audio: true 16 | }, function (stream) { 17 | videoElem.src = URL.createObjectURL(stream) 18 | callback(stream) 19 | }) 20 | } 21 | 22 | function RemoteMediaStream(videoElem, mediaStream) { 23 | log.verbose("RemoteMediaStream", arguments) 24 | videoElem.src = URL.createObjectURL(mediaStream) 25 | } -------------------------------------------------------------------------------- /lib/peerConnection.js: -------------------------------------------------------------------------------- 1 | var RTCPeerConnection = window.PeerConnection || window.webkitPeerConnection00 2 | , SERVER = "STUN stun.l.google.com:19302" 3 | , EventEmitter = require("events").EventEmitter 4 | , log = require("./log") 5 | 6 | module.exports = PeerConnection 7 | 8 | function PeerConnection(stream) { 9 | var pc = new RTCPeerConnection(SERVER, onIceCandidate) 10 | , emitter = new EventEmitter() 11 | 12 | pc.addStream(stream) 13 | 14 | pc.onaddstream = onRemoteStreamAdded 15 | 16 | emitter.createOffer = createOffer 17 | emitter.receiveOffer = receiveOffer 18 | emitter.createAnswer = createAnswer 19 | emitter.receiveAnswer = receiveAnswer 20 | emitter.receiveCandidate = receiveCandidate 21 | 22 | return emitter 23 | 24 | function onIceCandidate(candidate) { 25 | log.silly("onIceCandidate", arguments) 26 | emitter.emit("candidate", candidate) 27 | } 28 | 29 | function onRemoteStreamAdded(event) { 30 | log.verbose("onRemoteStreamAdded", event) 31 | emitter.emit("stream", event.stream) 32 | } 33 | 34 | function createOffer() { 35 | log.info("createOffer") 36 | var offer = pc.createOffer({ 37 | video: true 38 | , audio: true 39 | }) 40 | 41 | pc.setLocalDescription(pc.SDP_OFFER, offer) 42 | pc.startIce() 43 | 44 | return offer 45 | } 46 | 47 | function receiveOffer(offer) { 48 | log.info("receiveOffer", arguments) 49 | pc.setRemoteDescription(pc.SDP_OFFER, offer) 50 | } 51 | 52 | function createAnswer(offer) { 53 | log.info("createAnswer", offer) 54 | var answer = pc.createAnswer(offer.toSdp(), { 55 | video: true 56 | , audio: true 57 | }) 58 | 59 | pc.setLocalDescription(pc.SDP_ANSWER, answer) 60 | pc.startIce() 61 | 62 | return answer 63 | } 64 | 65 | function receiveAnswer(answer) { 66 | log.info("receiveAnswer", answer) 67 | pc.setRemoteDescription(pc.SDP_ANSWER, answer) 68 | } 69 | 70 | function receiveCandidate(candidate) { 71 | log.silly("receiveCandidate", candidate) 72 | pc.processIceMessage(candidate) 73 | } 74 | } -------------------------------------------------------------------------------- /lib/simplePeerConnections.js: -------------------------------------------------------------------------------- 1 | var EventEmitter = require("events").EventEmitter 2 | , PeerConnection = require("./peerConnection") 3 | , forEach = require("iterators").forEachSync 4 | , log = require("./log") 5 | 6 | module.exports = SimplePeerConnections 7 | 8 | function SimplePeerConnections(myMediaStream) { 9 | var peerConnections = {} 10 | , streams = {} 11 | , pcs = new EventEmitter() 12 | 13 | pcs.create = create 14 | pcs.streams = streams 15 | pcs.handleCandidate = handleCandidate 16 | pcs.handleAnswer = handleAnswer 17 | pcs.destroy = destroy 18 | 19 | return pcs 20 | 21 | function create(remotePeerId, offer) { 22 | log.info("create", arguments) 23 | var pc = peerConnections[remotePeerId] = PeerConnection(myMediaStream) 24 | 25 | pc.on("candidate", pcs.emit.bind(pcs, "candidate", remotePeerId)) 26 | 27 | if (offer) { 28 | pc.on("stream", handleStream) 29 | 30 | pc.receiveOffer(offer) 31 | 32 | return pc.createAnswer(offer) 33 | } 34 | 35 | return pc.createOffer() 36 | 37 | function handleStream(stream) { 38 | streams[remotePeerId] = stream 39 | 40 | pcs.emit("stream", remotePeerId, stream) 41 | } 42 | } 43 | 44 | function handleCandidate(remotePeerId, candidate) { 45 | log.silly("handleCandidate", arguments) 46 | var pc = peerConnections[remotePeerId] 47 | 48 | pc.receiveCandidate(candidate) 49 | } 50 | 51 | function handleAnswer(remotePeerId, answer) { 52 | log.info("handleAnswer", arguments) 53 | var pc = peerConnections[remotePeerId] 54 | 55 | pc.on("stream", handleStream) 56 | 57 | pc.receiveAnswer(answer) 58 | 59 | function handleStream(stream) { 60 | streams[remotePeerId] = stream 61 | 62 | pcs.emit("stream", remotePeerId, stream) 63 | } 64 | } 65 | 66 | function destroy() { 67 | forEach(peerConnections, close) 68 | 69 | pcs.emit("close") 70 | } 71 | 72 | function close(stream) { 73 | stream.close() 74 | } 75 | } -------------------------------------------------------------------------------- /lib/webrtcStreams.js: -------------------------------------------------------------------------------- 1 | var SimplePeerConnections = require("./simplePeerConnections") 2 | , DiscoveryNetwork = require("discovery-network") 3 | , WebRTCNetwork = DiscoveryNetwork.WebRTCNetwork 4 | , PeerNetwork = DiscoveryNetwork.PeerNetwork 5 | , EventEmitter = require("events").EventEmitter 6 | , log = require("./log") 7 | 8 | module.exports = WebRTCStreams 9 | 10 | function WebRTCStreams(conn, name, mediaStream, callback) { 11 | var pcs = SimplePeerConnections(mediaStream) 12 | , peerNetwork = PeerNetwork(conn, name + "/peer") 13 | , webrtcNetwork = WebRTCNetwork(conn, name + "/webrtc") 14 | , streams = new EventEmitter() 15 | 16 | // when you detect a new peer joining, open a PC to them 17 | peerNetwork.on("peer", handlePeer) 18 | 19 | // incoming offer from another peer 20 | webrtcNetwork.on("offer", handleOffer) 21 | 22 | // incoming answers from another peer 23 | webrtcNetwork.on("answer", pcs.handleAnswer) 24 | 25 | // incoming candidates from another peer 26 | webrtcNetwork.on("candidate", pcs.handleCandidate) 27 | 28 | // outgoing candidates to another peer 29 | pcs.on("candidate", webrtcNetwork.sendCandidate) 30 | 31 | // render streams from pcs 32 | pcs.on("stream", callback) 33 | 34 | peerNetwork.join() 35 | 36 | streams.pcs = pcs 37 | streams.streams = pcs.streams 38 | streams.peerNetwork = peerNetwork 39 | streams.webrtcNetwork = webrtcNetwork 40 | streams.destroy = destroy 41 | 42 | return streams 43 | 44 | 45 | function handlePeer(remotePeerId) { 46 | log.info("handlePeer", remotePeerId) 47 | var offer = pcs.create(remotePeerId) 48 | 49 | webrtcNetwork.sendOffer(remotePeerId, offer) 50 | } 51 | 52 | function handleOffer(remotePeerId, offer) { 53 | log.info("handleOffer", arguments) 54 | var answer = pcs.create(remotePeerId, offer) 55 | 56 | webrtcNetwork.sendAnswer(remotePeerId, answer) 57 | } 58 | 59 | function destroy() { 60 | pcs.destroy() 61 | peerNetwork.destroy() 62 | webrtcNetwork.destroy() 63 | 64 | streams.emit("close") 65 | } 66 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webrtc-stream", 3 | "version": "0.5.0", 4 | "description": "Stream video and audio", 5 | "keywords": [], 6 | "author": "Raynos ", 7 | "repository": "git://github.com/Raynos/webrtc-stream.git", 8 | "homepage": "https://github.com/Raynos/webrtc-stream", 9 | "browserify": "browser.js", 10 | "contributors": [ 11 | { 12 | "name": "Jake Verbaten" 13 | } 14 | ], 15 | "bugs": { 16 | "url": "https://github.com/Raynos/webrtc-stream/issues", 17 | "email": "raynos2@gmail.com" 18 | }, 19 | "dependencies": { 20 | "browser-log": "0.0.2", 21 | "iterators": "~0.2.0", 22 | "discovery-network": "~0.5.2" 23 | }, 24 | "devDependencies": { 25 | "browserify-server": "~0.3.1", 26 | "mux-demux-shoe": "~0.2.7", 27 | "discovery-network": "~0.5.2" 28 | }, 29 | "licenses": [ 30 | { 31 | "type": "MIT", 32 | "url": "http://github.com/Raynos/webrtc-stream/raw/master/LICENSE" 33 | } 34 | ], 35 | "scripts": {} 36 | } 37 | --------------------------------------------------------------------------------