WebRTC One-Way video sharing/broadcasting / Demo
来源:互联网 发布:随机过程教材 知乎 编辑:程序博客网 时间:2024/06/09 13:55
https://github.com/muaz-khan/WebRTC-Experiment/tree/master/webrtc-broadcasting
WebRTC One-Way video sharing/broadcasting / Demo
Participants can view your broadcasted video anonymously. They can also listen you without allowing access to their own microphone!
This experiment is actually a one-way audio/video/screen streaming.
- This WebRTC experiment is aimed to transmit audio/video streams in one-way style.
- It setups multiple peer connections to support multi-user connectivity feature. Rememebr, WebRTC doesn't supports 3-way handshake!
- Out of multi-peers establishment; many RTP-ports are opened according to number of media streamas referenced to each peer connection.
- Multi-ports establishment will cause huge CPU and bandwidth usage!
- Mesh networking model is implemented to open multiple interconnected peer connections.
- Maximum peer connections limit is 256 (on chrome). It means that 256 users can be interconnected!
You can:
- Share your screen in one-way over many peers
- Share you camera in one-way over many peers
- Share/transmit your voice in one-way over many peers
How WebRTC One-Way Broadcasting Works?
- Mesh networking model is implemented to open multiple interconnected peer connections
- Maximum peer connections limit is 256 (on chrome)
It is one-way broadcasting; media stream is attached only by the broadcaster.
It means that, if 10 people are watching your one-way broadcasted audio/video stream; on your system:
- 10 RTP ports are opened to send video upward i.e. outgoing video
- 10 RTP ports are opened to send audio upward i.e. outgoing audio
And on participants system:
- 10 RTP ports are opened to receive video i.e. incoming video
- 10 RTP ports are opened to receive audio i.e. incoming audio
Maximum bandwidth used by each video RTP port (media-track) is about 1MB. You're streaming audio and video tracks. You must be careful when streaming video over more than one peers. If you're broadcasting audio/video over 10 peers; it means that 20MB bandwidth is required on your system to stream-up (broadcast/transmit) your video. Otherwise; you'll face connection lost; CPU usage issues; and obviously audio-lost/noise/echo issues.
You can handle such things using "b=AS" (application specific bandwidth) session description parameter values to deliver a little bit low quality video.
// removing existing bandwidth linessdp = sdp.replace( /b=AS([^\r\n]+\r\n)/g , '');// setting "outgoing" audio RTP port's bandwidth to "50kbit/s"sdp = sdp.replace( /a=mid:audio\r\n/g , 'a=mid:audio\r\nb=AS:50\r\n');// setting "outgoing" video RTP port's bandwidth to "256kbit/s"sdp = sdp.replace( /a=mid:video\r\n/g , 'a=mid:video\r\nb=AS:256\r\n');
Possible issues
- Blurry video experience
- Unclear voice and audio lost
- Bandwidth issues / slow streaming / CPU overwhelming
Solution? Obviously a media server!
How to setup private rooms?
Following "channel" line makes private rooms according to the domain name.
https://github.com/muaz-khan/WebRTC-Experiment/blob/master/webrtc-broadcasting/index.html#L140
var channel = config.channel || location.href.replace( /\/|:|#|%|\.|\[|\]/g , '');
You can see this code: location.href.replace( /\/|:|#|%|\.|\[|\]/g , '')
It means that "channel" which is a unique identifier of the room....is taken from the actual URL...
So, your room will be visible only on your domain.
You can use custom channel name if you wanna open single channel among all your pages.....
var channel = config.channel || 'this-must-be-unique-must-be-private';
For first case, where I was taking "channel" from the URL ....
i.e. location.href.replace( /\/|:|#|%|\.|\[|\]/g , '')
In that case, each URL will have unique channel i.e.
http://localhost/first-page/http://localhost/second-page/http://localhost/third-page/
Users from all three pages can't see each other; they'll NEVER see "join" buttons etc.
If no one has access to your channel; he can't see/view your broadcast.
Also, hashes or query-string parameters causes unique channels.
http://localhost/first-page/http://localhost/first-page/#hashhttp://localhost/first-page/?query=something
All these three pages has unique channels. They'll NEVER see rooms from each other.
Want to use video-conferencing in your own webpage?
<script src="//cdn.webrtc-experiment.com/socket.io.js"> </script><script src="//cdn.webrtc-experiment.com/RTCPeerConnection-v1.5.js"> </script><script src="//cdn.webrtc-experiment.com/webrtc-broadcasting/broadcast.js"> </script><select id="broadcasting-option"> <option>Audio + Video</option> <option>Only Audio</option> <option>Screen</option></select><button id="setup-new-broadcast">Setup New Broadcast</button><table style="width: 100%;" id="rooms-list"></table><div id="videos-container"></div><script> var config = { openSocket: function(config) { // http://socketio-over-nodejs.hp.af.cm/ (Ordinary port: HTTP) // http://socketio-over-nodejs.nodejitsu.com:80 (Secure port: HTTPs) // https://socketio-over-nodejs.nodejitsu.com:443/ (Ordinary port: HTTP) // https://webrtc-signaling.nodejitsu:443/ (Secure port: HTTPs) // http://webrtc-signaling.nodejitsu:80/ (Ordinary port: HTTP) var SIGNALING_SERVER = 'https://webrtc-signaling.nodejitsu.com:443/'; var channel = config.channel || location.href.replace( /\/|:|#|%|\.|\[|\]/g , ''); var sender = Math.round(Math.random() * 999999999) + 999999999; io.connect(SIGNALING_SERVER).emit('new-channel', { channel: channel, sender: sender }); var socket = io.connect(SIGNALING_SERVER + channel); socket.channel = channel; socket.on('connect', function() { if (config.callback) config.callback(socket); }); socket.send = function(message) { socket.emit('message', { sender: sender, data: message }); }; socket.on('message', config.onmessage); }, onRemoteStream: function(htmlElement) { htmlElement.setAttribute('controls', true); videosContainer.insertBefore(htmlElement, videosContainer.firstChild); htmlElement.play(); }, onRoomFound: function(room) { var alreadyExist = document.querySelector('button[data-broadcaster="' + room.broadcaster + '"]'); if (alreadyExist) return; var tr = document.createElement('tr'); tr.innerHTML = '<td><strong>' + room.roomName + '</strong> is broadcasting his media!</td>' + '<td><button class="join">Join</button></td>'; roomsList.insertBefore(tr, roomsList.firstChild); var joinRoomButton = tr.querySelector('.join'); joinRoomButton.setAttribute('data-broadcaster', room.broadcaster); joinRoomButton.setAttribute('data-roomToken', room.broadcaster); joinRoomButton.onclick = function() { this.disabled = true; var broadcaster = this.getAttribute('data-broadcaster'); var roomToken = this.getAttribute('data-roomToken'); broadcastUI.joinRoom({ roomToken: roomToken, joinUser: broadcaster }); }; }, onNewParticipant: function(numberOfViewers) { document.title = 'Viewers: ' + numberOfViewers; } }; var broadcastUI = broadcast(config); var videosContainer = document.getElementById('videos-container') || document.body; var setupNewBroadcast = document.getElementById('setup-new-broadcast'); var roomsList = document.getElementById('rooms-list'); var broadcastingOption = document.getElementById('broadcasting-option'); document.getElementById('broadcasting-option').onclick = function() { this.disabled = true; captureUserMedia(function() { var shared = 'video'; if (window.option == 'Only Audio') shared = 'audio'; if (window.option == 'Screen') shared = 'screen'; broadcastUI.createRoom({ roomName: 'Anonymous', isAudio: shared === 'audio' }); }); }; function captureUserMedia(callback) { var constraints = null; window.option = broadcastingOption ? broadcastingOption.value : ''; if (option === 'Only Audio') { constraints = { audio: true, video: false }; } if (option === 'Screen') { var video_constraints = { mandatory: { chromeMediaSource: 'screen' }, optional: [] }; constraints = { audio: false, video: video_constraints }; } var htmlElement = document.createElement(option === 'Only Audio' ? 'audio' : 'video'); htmlElement.setAttribute('autoplay', true); htmlElement.setAttribute('controls', true); videosContainer.insertBefore(htmlElement, videosContainer.firstChild); var mediaConfig = { video: htmlElement, onsuccess: function(stream) { config.attachStream = stream; htmlElement.setAttribute('muted', true); callback(); }, onerror: function() { if (option === 'Only Audio') alert('unable to get access to your microphone'); else if (option === 'Screen') { if (location.protocol === 'http:') alert('Please test this WebRTC experiment on HTTPS.'); else alert('Screen capturing is either denied or not supported. Are you enabled flag: "Enable screen capture support in getUserMedia"?'); } else alert('unable to get access to your webcam'); } }; if (constraints) mediaConfig.constraints = constraints; getUserMedia(mediaConfig); }</script>
For signaling; please check following page:
https://github.com/muaz-khan/WebRTC-Experiment/blob/master/Signaling.md
Remember, you can use any signaling implementation exists out there without modifying any single line! Just skip below code and open above link!
Browser Support
This WebRTC One-Way Broadcasting experiment works fine on following web-browsers:
License
WebRTC One-Way Broadcasting experiment is released under MIT licence . Copyright (c) Muaz Khan.
- WebRTC One-Way video sharing/broadcasting / Demo
- JSONP -- one way of cross-domain data sharing
- Live broadcasting video/audio APPS
- Introduction to Adaptive Cursor Sharing Concepts and Multimedia Demo [Video] (文档 ID 1115994.1)
- webRTC demo
- One Sample JD-sharing
- Broadcasting
- One-way Web Hacking
- one way单程杀机
- One-way ANOVA
- Blizzard One-Way Hash
- lightoj1049 - One Way Roads
- React one-way flow
- codeforce723E One-Way Reform
- rank() one way useful
- E. One-Way Reform
- [CEOI2017]One-Way Streets
- IPTV and Internet Video: Expanding the Reach of Television Broadcasting
- robot framework总结
- android-activity之启动模式singleInstance
- v$sqlarea
- 白手起家学习数据科学 ——Naive Bayes之“背后的思想”(十)
- MySQL InnoDB 锁表与锁行
- WebRTC One-Way video sharing/broadcasting / Demo
- TTreeView customSort 实现 自定义排序
- 嵌入式Linux中SQLITE数据库的应用
- VC中Unicode字符集转UTF-8字符集
- Ext.js5表单—即时查询(结合Ext.Template和远程数据)(52)
- ifconfig找不到命令
- Mysql 存储过程基本语法
- Unity 5.x BuildAssetBundles 角色换装 加载ab包 资源管理 根据部件组合完整角色
- c++ builder 简单读、分析网页数据