├── .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 |
--------------------------------------------------------------------------------