SHOW:
|
|
- or go back to the newest paste.
1 | <script> | |
2 | if(!location.hash.replace('#', '').length) { | |
3 | location.href = location.href.split('#')[0] + '#' + (Math.random() * 100).toString().replace('.', ''); | |
4 | location.reload(); | |
5 | } | |
6 | </script> | |
7 | ||
8 | <title>Broadcast Multiple-Cameras using RTCMultiConnection.js</title> | |
9 | <h1>Broadcast Multiple-Cameras using <a href="http://www.rtcmulticonnection.org/">RTCMultiConnection.js</a> | |
10 | </h1> | |
11 | <style> | |
12 | ||
13 | ||
14 | button { | |
15 | font-family: Myriad, Arial, Verdana; | |
16 | font-weight: normal; | |
17 | border-top-left-radius: 3px; | |
18 | border-top-right-radius: 3px; | |
19 | border-bottom-right-radius: 3px; | |
20 | border-bottom-left-radius: 3px; | |
21 | padding: 4px 12px; | |
22 | text-decoration: none; | |
23 | color: rgb(27, 26, 26); | |
24 | display: inline-block; | |
25 | box-shadow: rgb(255, 255, 255) 1px 1px 0px 0px inset; | |
26 | text-shadow: none; | |
27 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0.05, rgb(241, 241, 241)), to(rgb(230, 230, 230))); | |
28 | font-size: 20px; | |
29 | border: 1px solid red; | |
30 | } | |
31 | ||
32 | button[disabled] { | |
33 | background: rgba(216, 205, 205, 0.2); | |
34 | border: 1px solid rgb(233, 224, 224); | |
35 | outline: none; | |
36 | box-shadow: none; | |
37 | } | |
38 | ||
39 | blockquote { | |
40 | font-size: 20px; | |
41 | color: rgb(172, 10, 10); | |
42 | border: 1px solid rgb(172, 10, 10); | |
43 | padding: 5px 10px; | |
44 | border-radius: 5px; | |
45 | margin: 9px 10px; | |
46 | } | |
47 | ||
48 | </style> | |
49 | <hr /> | |
50 | <div id="buttons-container"> | |
51 | <button id="broadcast-all-cameras" disabled>Broadcast All Cameras</button> | |
52 | </div> | |
53 | <blockquote> | |
54 | This demo is using <a href="http://www.rtcmulticonnection.org/">RTCMultiConnection.js</a>. This demo enumerates over all available video devices, and appends <button> for each device. You can click any button to capture relevant webcam. Then you can click "Broadcast All Cameras" button to broadcast your "multiple-cameras" over multiple users. | |
55 | </blockquote> | |
56 | <hr /> | |
57 | ||
58 | <div id="videos-container"> | |
59 | <video muted autoplay id="one" style="display:inline-block; background:black;" controls></video> | |
60 | </div> | |
61 | ||
62 | <script src="https://cdn.webrtc-experiment.com/RTCMultiConnection.js"></script> | |
63 | <script src="https://cdn.webrtc-experiment.com/DetectRTC.js"></script> | |
64 | <script src="https://cdn.webrtc-experiment.com/socket.io.js"></script> | |
65 | <script src="dist/video-stream-merger.js"></script> | |
66 | <script src="videoResize.js"></script> | |
67 | <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> | |
68 | <script src="https://cdnjs.cloudflare.com/ajax/libs/simple-peer/7.0.0/simplepeer.min.js"></script> | |
69 | <script> | |
70 | var CANVAS_MULTIPLIER = 3 | |
71 | var connection = new RTCMultiConnection(); | |
72 | ||
73 | // https://github.com/muaz-khan/WebRTC-Experiment/tree/master/socketio-over-nodejs | |
74 | var SIGNALING_SERVER = 'https://webrtcweb.com:9559/'; | |
75 | connection.openSignalingChannel = function(config) { | |
76 | var channel = config.channel || connection.channel || 'default-namespace'; | |
77 | var sender = Math.round(Math.random() * 9999999999) + 9999999999; | |
78 | ||
79 | io.connect(SIGNALING_SERVER).emit('new-channel', { | |
80 | channel: channel, | |
81 | sender: sender | |
82 | }); | |
83 | ||
84 | var socket = io.connect(SIGNALING_SERVER + channel); | |
85 | socket.channel = channel; | |
86 | ||
87 | socket.on('connect', function() { | |
88 | if (config.callback) config.callback(socket); | |
89 | }); | |
90 | ||
91 | socket.send = function(message) { | |
92 | socket.emit('message', { | |
93 | sender: sender, | |
94 | data: message | |
95 | }); | |
96 | }; | |
97 | ||
98 | socket.on('message', config.onmessage); | |
99 | }; | |
100 | ||
101 | connection.onNewSession = function(session) { | |
102 | connection.join(session); | |
103 | }; | |
104 | ||
105 | // connection.getExternalIceServers = false; // optional--remove it. | |
106 | // connection.iceServers.length = 1; // optional--remove it. | |
107 | ||
108 | connection.dontCaptureUserMedia = true; | |
109 | ||
110 | // Parent <div> for videos | |
111 | connection.body = document.getElementById('videos-container'); | |
112 | ||
113 | connection.session = { | |
114 | audio: true, | |
115 | video: true | |
116 | }; | |
117 | ||
118 | connection.direction = 'one-way'; | |
119 | ||
120 | connection.sdpConstraints.mandatory = { | |
121 | OfferToReceiveAudio: true, | |
122 | OfferToReceiveVideo: true | |
123 | }; | |
124 | ||
125 | var buttonsContainer = document.getElementById('buttons-container'); | |
126 | // DetectRTC.load --- to make sure all devices are captured | |
127 | // connection.enumerateDevices --- to get list of all captured devices | |
128 | var merger = new VideoStreamMerger({ | |
129 | width: 640*CANVAS_MULTIPLIER, | |
130 | height: 360*CANVAS_MULTIPLIER | |
131 | }) | |
132 | var players = document.querySelectorAll('video') | |
133 | var buttons = document.querySelectorAll('button') | |
134 | ||
135 | ||
136 | var peer1 = new SimplePeer({initiator: true, stream:merger.result}) | |
137 | peer1.on('stream', function (stream) { | |
138 | players[0].srcObject = stream | |
139 | }) | |
140 | ||
141 | ||
142 | var skipDuplicateDevies = {}; | |
143 | var uniqueCamerasLength = 0; | |
144 | var numStreams = 0 | |
145 | var curStream = 0 | |
146 | DetectRTC.load(function() { | |
147 | // iterate over devices-array | |
148 | DetectRTC.videoInputDevices.forEach(function(device) { | |
149 | if (skipDuplicateDevies[device.id]) return; | |
150 | skipDuplicateDevies[device.id] = true; | |
151 | ||
152 | // skip audio devices | |
153 | if (device.kind.indexOf('audio') != -1) return; | |
154 | // if(device.label.indexOf("Logitech HD") !== -1) { | |
155 | uniqueCamerasLength++; | |
156 | ||
157 | var button = document.createElement('button'); | |
158 | button.id = device.id; | |
159 | button.innerHTML = device.label || device.id; | |
160 | button.onclick = function () { | |
161 | this.disabled = true; | |
162 | ||
163 | connection._mediaSources.video = this.id; | |
164 | ||
165 | connection.dontCaptureUserMedia = false; | |
166 | connection.captureUserMedia(function (stream) { | |
167 | ||
168 | merger.addStream(stream, { | |
169 | x: 300, | |
170 | y: 0, | |
171 | width: merger.width - 100, | |
172 | height: merger.height, | |
173 | mute: numStreams > 0, | |
174 | draw: function (ctx, frame, done) { | |
175 | // merger.width = 1920 | |
176 | // merger.height = 1080 | |
177 | ||
178 | if (curStream >= numStreams) curStream = 0 | |
179 | ||
180 | var unit = merger.width / numStreams | |
181 | ctx.drawImage(frame, unit * curStream, 0, unit, merger.height) | |
182 | // console.log(curStream) | |
183 | ||
184 | curStream++ | |
185 | ||
186 | // players[0].style.width = 640+'px' | |
187 | // players[0].style.height = 360+'px' | |
188 | done() | |
189 | } | |
190 | }) | |
191 | connection.attachStreams.push(stream); | |
192 | connection.dontCaptureUserMedia = true; | |
193 | ||
194 | merger.start() | |
195 | players[0].srcObject = merger.result | |
196 | ||
197 | //videoResize("#video-container","#video-container video"); | |
198 | ||
199 | numStreams++ | |
200 | //console.log(stream) | |
201 | ||
202 | }); | |
203 | }; | |
204 | buttonsContainer.appendChild(button); | |
205 | ||
206 | }); | |
207 | }); | |
208 | ||
209 | connection.connect(); | |
210 | ||
211 | ||
212 | ||
213 | </script> |