<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## 概述 WebRTC是“網絡實時通信”(Web Real Time Communication)的縮寫。它最初是為了解決瀏覽器上視頻通話而提出的,即兩個瀏覽器之間直接進行視頻和音頻的通信,不經過服務器。后來發展到除了音頻和視頻,還可以傳輸文字和其他數據。 Google是WebRTC的主要支持者和開發者,它最初在Gmail上推出了視頻聊天,后來在2011年推出了Hangouts,語序在瀏覽器中打電話。它推動了WebRTC標準的確立。 WebRTC主要讓瀏覽器具備三個作用。 * 獲取音頻和視頻 * 進行音頻和視頻通信 * 進行任意數據的通信 WebRTC共分成三個API,分別對應上面三個作用。 * MediaStream (又稱getUserMedia) * RTCPeerConnection * RTCDataChannel ## getUserMedia ### 概述 navigator.getUserMedia方法目前主要用于,在瀏覽器中獲取音頻(通過麥克風)和視頻(通過攝像頭),將來可以用于獲取任意數據流,比如光盤和傳感器。 下面的代碼用于檢查瀏覽器是否支持getUserMedia方法。 ~~~ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; if (navigator.getUserMedia) { ? ? // 支持 } else { ? ? // 不支持 } ~~~ Chrome 21, Opera 18和Firefox 17,支持該方法。目前,IE還不支持,上面代碼中的msGetUserMedia,只是為了確保將來的兼容。 getUserMedia方法接受三個參數。 ~~~ navigator.getUserMedia({ ? ? video: true, ? ? audio: true }, onSuccess, onError); ~~~ getUserMedia的第一個參數是一個對象,表示要獲取哪些多媒體設備,上面的代碼表示獲取攝像頭和麥克風;onSuccess是一個回調函數,在獲取多媒體設備成功時調用;onError也是一個回調函數,在取多媒體設備失敗時調用。 下面是一個例子。 ~~~ var constraints = {video: true}; function onSuccess(stream) { var video = document.querySelector("video"); video.src = window.URL.createObjectURL(stream); } function onError(error) { console.log("navigator.getUserMedia error: ", error); } navigator.getUserMedia(constraints, onSuccess, onError); ~~~ 如果網頁使用了getUserMedia方法,瀏覽器就會詢問用戶,是否同意瀏覽器調用麥克風或攝像頭。如果用戶同意,就調用回調函數onSuccess;如果用戶拒絕,就調用回調函數onError。 onSuccess回調函數的參數是一個數據流對象stream。stream.getAudioTracks方法和stream.getVideoTracks方法,分別返回一個數組,其成員是數據流包含的音軌和視軌(track)。使用的聲音源和攝影頭的數量,決定音軌和視軌的數量。比如,如果只使用一個攝像頭獲取視頻,且不獲取音頻,那么視軌的數量為1,音軌的數量為0。每個音軌和視軌,有一個kind屬性,表示種類(video或者audio),和一個label屬性(比如FaceTime HD Camera (Built-in))。 onError回調函數接受一個Error對象作為參數。Error對象的code屬性有如下取值,說明錯誤的類型。 * PERMISSION_DENIED:用戶拒絕提供信息。 * NOT_SUPPORTED_ERROR:瀏覽器不支持硬件設備。 * MANDATORY_UNSATISFIED_ERROR:無法發現指定的硬件設備。 ### 范例:獲取攝像頭 下面通過getUserMedia方法,將攝像頭拍攝的圖像展示在網頁上。 首先,需要先在網頁上放置一個video元素。圖像就展示在這個元素中。 ~~~ <video id="webcam"></video> ~~~ 然后,用代碼獲取這個元素。 ~~~ function onSuccess(stream) { ? ? var video = document.getElementById('webcam'); } ~~~ 接著,將這個元素的src屬性綁定數據流,攝影頭拍攝的圖像就可以顯示了。 ~~~ function onSuccess(stream) { ? ? var video = document.getElementById('webcam'); ? ? if (window.URL) { video.src = window.URL.createObjectURL(stream); } else { video.src = stream; } video.autoplay = true; // 或者 video.play(); } if (navigator.getUserMedia) { navigator.getUserMedia({video:true}, onSuccess); } else { document.getElementById('webcam').src = 'somevideo.mp4'; } ~~~ 在Chrome和Opera中,URL.createObjectURL方法將媒體數據流(MediaStream)轉為一個二進制對象的URL(Blob URL),該URL可以作為video元素的src屬性的值。 在Firefox中,媒體數據流可以直接作為src屬性的值。Chrome和Opera還允許getUserMedia獲取的音頻數據,直接作為audio或者video元素的值,也就是說如果還獲取了音頻,上面代碼播放出來的視頻是有聲音的。 獲取攝像頭的主要用途之一,是讓用戶使用攝影頭為自己拍照。Canvas API有一個ctx.drawImage(video, 0, 0)方法,可以將視頻的一個幀轉為canvas元素。這使得截屏變得非常容易。 ~~~ <video autoplay></video> <img src=""> <canvas style="display:none;"></canvas> <script> var video = document.querySelector('video'); var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); var localMediaStream = null; function snapshot() { if (localMediaStream) { ctx.drawImage(video, 0, 0); // “image/webp”對Chrome有效, // 其他瀏覽器自動降為image/png document.querySelector('img').src = canvas.toDataURL('image/webp'); } } video.addEventListener('click', snapshot, false); navigator.getUserMedia({video: true}, function(stream) { video.src = window.URL.createObjectURL(stream); localMediaStream = stream; }, errorCallback); </script> ~~~ ### 范例:捕獲麥克風聲音 通過瀏覽器捕獲聲音,需要借助Web Audio API。 ~~~ window.AudioContext = window.AudioContext || window.webkitAudioContext; var context = new AudioContext(); function onSuccess(stream) { var audioInput = context.createMediaStreamSource(stream); audioInput.connect(context.destination); } navigator.getUserMedia({audio:true}, onSuccess); ~~~ ### 捕獲的限定條件 getUserMedia方法的第一個參數,除了指定捕獲對象之外,還可以指定一些限制條件,比如限定只能錄制高清(或者VGA標準)的視頻。 ~~~ var hdConstraints = { video: { mandatory: { minWidth: 1280, minHeight: 720 } } }; navigator.getUserMedia(hdConstraints, onSuccess, onError); var vgaConstraints = { video: { mandatory: { maxWidth: 640, maxHeight: 360 } } }; navigator.getUserMedia(vgaConstraints, onSuccess, onError); ~~~ ### MediaStreamTrack.getSources() 如果本機有多個攝像頭/麥克風,這時就需要使用MediaStreamTrack.getSources方法指定,到底使用哪一個攝像頭/麥克風。 ~~~ MediaStreamTrack.getSources(function(sourceInfos) { var audioSource = null; var videoSource = null; for (var i = 0; i != sourceInfos.length; ++i) { var sourceInfo = sourceInfos[i]; if (sourceInfo.kind === 'audio') { console.log(sourceInfo.id, sourceInfo.label || 'microphone'); audioSource = sourceInfo.id; } else if (sourceInfo.kind === 'video') { console.log(sourceInfo.id, sourceInfo.label || 'camera'); videoSource = sourceInfo.id; } else { console.log('Some other kind of source: ', sourceInfo); } } sourceSelected(audioSource, videoSource); }); function sourceSelected(audioSource, videoSource) { var constraints = { audio: { optional: [{sourceId: audioSource}] }, video: { optional: [{sourceId: videoSource}] } }; navigator.getUserMedia(constraints, onSuccess, onError); } ~~~ 上面代碼表示,MediaStreamTrack.getSources方法的回調函數,可以得到一個本機的攝像頭和麥克風的列表,然后指定使用最后一個攝像頭和麥克風。 ## RTCPeerConnectionl,RTCDataChannel ### RTCPeerConnectionl RTCPeerConnection的作用是在瀏覽器之間建立數據的“點對點”(peer to peer)通信,也就是將瀏覽器獲取的麥克風或攝像頭數據,傳播給另一個瀏覽器。這里面包含了很多復雜的工作,比如信號處理、多媒體編碼/解碼、點對點通信、數據安全、帶寬管理等等。 不同客戶端之間的音頻/視頻傳遞,是不用通過服務器的。但是,兩個客戶端之間建立聯系,需要通過服務器。服務器主要轉遞兩種數據。 * 通信內容的元數據:打開/關閉對話(session)的命令、媒體文件的元數據(編碼格式、媒體類型和帶寬)等。 * 網絡通信的元數據:IP地址、NAT網絡地址翻譯和防火墻等。 WebRTC協議沒有規定與服務器的通信方式,因此可以采用各種方式,比如WebSocket。通過服務器,兩個客戶端按照Session Description Protocol(SDP協議)交換雙方的元數據。 下面是一個示例。 ~~~ var signalingChannel = createSignalingChannel(); var pc; var configuration = ...; // run start(true) to initiate a call function start(isCaller) { pc = new RTCPeerConnection(configuration); // send any ice candidates to the other peer pc.onicecandidate = function (evt) { signalingChannel.send(JSON.stringify({ "candidate": evt.candidate })); }; // once remote stream arrives, show it in the remote video element pc.onaddstream = function (evt) { remoteView.src = URL.createObjectURL(evt.stream); }; // get the local stream, show it in the local video element and send it navigator.getUserMedia({ "audio": true, "video": true }, function (stream) { selfView.src = URL.createObjectURL(stream); pc.addStream(stream); if (isCaller) pc.createOffer(gotDescription); else pc.createAnswer(pc.remoteDescription, gotDescription); function gotDescription(desc) { pc.setLocalDescription(desc); signalingChannel.send(JSON.stringify({ "sdp": desc })); } }); } signalingChannel.onmessage = function (evt) { if (!pc) start(false); var signal = JSON.parse(evt.data); if (signal.sdp) pc.setRemoteDescription(new RTCSessionDescription(signal.sdp)); else pc.addIceCandidate(new RTCIceCandidate(signal.candidate)); }; ~~~ RTCPeerConnection帶有瀏覽器前綴,Chrome瀏覽器中為webkitRTCPeerConnection,Firefox瀏覽器中為mozRTCPeerConnection。Google維護一個函數庫[adapter.js](https://apprtc.appspot.com/js/adapter.js),用來抽象掉瀏覽器之間的差異。 ### RTCDataChannel RTCDataChannel的作用是在點對點之間,傳播任意數據。它的API與WebSockets的API相同。 下面是一個示例。 ~~~ var pc = new webkitRTCPeerConnection(servers, {optional: [{RtpDataChannels: true}]}); pc.ondatachannel = function(event) { receiveChannel = event.channel; receiveChannel.onmessage = function(event){ document.querySelector("div#receive").innerHTML = event.data; }; }; sendChannel = pc.createDataChannel("sendDataChannel", {reliable: false}); document.querySelector("button#send").onclick = function (){ var data = document.querySelector("textarea#send").value; sendChannel.send(data); }; ~~~ Chrome 25、Opera 18和Firefox 22支持RTCDataChannel。 ### 外部函數庫 由于這兩個API比較復雜,一般采用外部函數庫進行操作。目前,視頻聊天的函數庫有[SimpleWebRTC](https://github.com/henrikjoreteg/SimpleWebRTC)、[easyRTC](https://github.com/priologic/easyrtc)、[webRTC.io](https://github.com/webRTC/webRTC.io),點對點通信的函數庫有[PeerJS](http://peerjs.com/)、[Sharefest](https://github.com/peer5/sharefest)。 下面是SimpleWebRTC的示例。 ~~~ var webrtc = new WebRTC({ localVideoEl: 'localVideo', remoteVideosEl: 'remoteVideos', autoRequestMedia: true }); webrtc.on('readyToCall', function () { webrtc.joinRoom('My room name'); }); ~~~ 下面是PeerJS的示例。 ~~~ var peer = new Peer('someid', {key: 'apikey'}); peer.on('connection', function(conn) { conn.on('data', function(data){ // Will print 'hi!' console.log(data); }); }); // Connecting peer var peer = new Peer('anotherid', {key: 'apikey'}); var conn = peer.connect('someid'); conn.on('open', function(){ conn.send('hi!'); }); ~~~ ## 參考鏈接 * Andi Smith,[Get Started with WebRTC](http://www.netmagazine.com/tutorials/get-started-webrtc) * Thibault Imbert,?[From microphone to .WAV with: getUserMedia and Web Audio](http://typedarray.org/from-microphone-to-wav-with-getusermedia-and-web-audio/) * Ian Devlin,?[Using the getUserMedia API with the HTML5 video and canvas elements](http://html5hub.com/using-the-getusermedia-api-with-the-html5-video-and-canvas-elements/#i.bz41ehmmhd3311) * Eric Bidelman,?[Capturing Audio & Video in HTML5](http://www.html5rocks.com/en/tutorials/getusermedia/intro/) * Sam Dutton,?[Getting Started with WebRTC](http://www.html5rocks.com/en/tutorials/webrtc/basics/) * Dan Ristic,?[WebRTC data channels](http://www.html5rocks.com/en/tutorials/webrtc/datachannels/) * Justin Uberti, Sam Dutton,?[WebRTC: Plugin-free realtime communication](http://io13webrtc.appspot.com/) * Mozilla Developer Network,?[Taking webcam photos](https://developer.mozilla.org/en-US/docs/Web/Guide/API/WebRTC/Taking_webcam_photos) * Sam Dutton,?[WebRTC in the real world: STUN, TURN and signaling](http://www.html5rocks.com/en/tutorials/webrtc/infrastructure/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看