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> |