參考:
https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack
轉自http://c.tieba.baidu.com/p/3312565203
http://c.tieba.baidu.com/p/3312569139
http://c.tieba.baidu.com/p/3312680272
Network Stream API
MediaStream:MediaStream用來表示一個媒體數據流。
MediaStreamTrack在瀏覽器中表示一個媒體源。
篇文章會對MediaStream進行講解。
MediaStream (別名 getUserMedia)
MediaStream API 代表媒體數據流的同步。舉個例子,從相機獲取的視頻流的同步和跟蹤。
理解MediaStream最簡單的方法應該就是看看它的實際應用:
在Chrome或Opera中, 打開這個demo simpl.info/gum。
打開命令行。
查看全局范圍的數據流變量。
每個MediaStream都有一個輸入,這個輸入可以理解成MediaStream生成的一個導航器。getUserMedia()可以傳輸視頻元素或者是RTCPeerConnection。
getUserMedia()方法有三個參數:
一個 約束對象
一個成功的回調,如果成功會回傳一個MediaStream
一個失敗的回調,如果失敗會回傳一個error對象。
每個MediaStream都有一個標簽,像*Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ*一樣,getAudioTradks()和getAudioTracks()方法會回傳一個MediaStreamTracks對象的數組。
針對 simpl.info/gum 這個例子來說,stream.getAudioTracks() 返回了一個空數組 (因為沒有音頻) , 假設已經有一個攝像頭連接成功,getVideoTracks()會返回一個MediaStreamTrack對象的數組, 這個數組代表從攝像頭得到的數據流。每個MediaStreamTrack都有一個類型 (*video* 或 *audio*), 和一個標簽(代表一個或多個頻道的音頻或視頻),在這個例子中,只有video track,但是很容易想象到可以用到這個例子的地方,比如一個聊天應用程序的前置攝像頭、后置攝像頭,一個屏幕分享軟件等等。
在Chrome或Opera中, URL.createObjectURL() 方法把MediaStream 轉換成了一個 Blob URL,Blob URL可以看成一個視頻元素的src。 (在Firefox和Opera中,視頻的src可以通過數據流本身設定)。
getUserMedia 也可以作為網絡音頻API的輸入節點:
基於Chromium的應用和擴展可以合並getUserMedia。在manifest 中添加audioCapture 和 videoCapture權限可以在加載的時候得到(僅一次)授權,畢竟加載之后用戶不會有對攝像頭或麥克風的訪問請求。同樣,forgetUserMedia()也是只有一次授權。
他的最終目的是使MediaStream能取到任意的數據源,不只是局限於攝像頭或是手機。這將拿其兼容其他輸入,如傳感器等。
需要注意的是getUserMedia()必須在服務器上使用,而不是本地文件中,否則的話將會拋出權限的錯誤。
getUserMedia() 已經成功的融合了其它的JavaScript APIs和庫:
Webcam Toy 是一個photobooth應用,它使用WebGL來添加一些特效,讓用戶可以共享照片或是保存本地。
FaceKat 是一個人臉追蹤的游戲,使用headtrackr.js。
ASCII Camera 使用Canvas API來生成ASCII碼的圖片。
約束
約束 在Chrome 24和Opera 18版本之后被引入。它們可以被用來設置 getUserMedia()和RTCPeerConnection addStream() 這些視頻的流的分辨率。 約束的實現是為了制約例如視頻高度和寬度的比例、幀率、和正反攝像頭模式等等……
針對約束,這里有一個例子: simpl.info/getusermedia/constraints.
一個陷阱:getUserMedia約束在瀏覽器所有選項卡影響約束后完成后才設置,設置一個錯誤的值會發生以下錯誤:
navigator.getUserMedia error:
NavigatorUserMediaError {code: 1, PERMISSION_DENIED: 1}
屏幕和標簽捕獲你同樣可以利用MediaStream捕獲屏幕和標簽的數據源。它已經在Chrome中實現了像這個例子一樣,但是在Opera上還沒有實現。
Chrome應用很多都已經實現了通過chrome.tabCaptureAPI 分享在線錄播的功能。更多具體的信息,如屏幕錄制的編碼,請到 Screensharing with WebRTC上進行相關學習,但是目前只支持Chrome。
信號: session控制,網絡和多媒體信息
WebRTC使用RTCPeerConnection進行兩個瀏覽器之間的數據流的通信,但是也需要一種機制來協調溝通控制信息,這一個過程叫做信號。信號的方法和協議不是WebRTC指定的,而是RTCPeerConnection API的一部分。
相應的,WebRTC應用開發者可以選擇任意一種自己喜歡的消息協議,比如SIP或是XMPP,也可以選擇任何適當的雙工協議,apprtc.appspot.com 這個例子使用XHR和Channel API機制的信號,codelab是我們構建的通過Socket.io運行在 Node服務器上的應用。
信號用來交換以下三個類型的信息:
Session控制信息:用來初始化或是關閉通信,並報告錯誤。
網絡配置:本機的IP和端口等配置。
媒體功能:編碼解碼器配置。
信號的配置必須沒有任何差錯,在完成點對點的傳輸之后就可以通過信號交換信息。
舉個例子,想像一下如果Jack Ma要和Jobs通信,這里有個demo來自於WebRTC W3C Working Draft, 它展示了信號的行為。下面的的代碼假設某種信號機制的存在,在createSignalingChannel方法中創建。還要注意:在Chrome,Opera中使用RTCPeerConnection是目前的前提。
首先,Jack Ma和Jobs要交換網絡信息。 (表達式 *finding candidates*指向查找網絡接口和端口的進程,通過ICE framework完成)
Jack ma通過onicecandidatehandler創建一個RTCPeerConnection對象。
handler在網絡通的時候開始執行。
Jack Ma發送將序列化的數據發送給Jobs,通過WebSock或其它機制建立信號。
當Jobs收到這些序列化的信息之后,他會調用saddIceCandidate, 來添加遠程連接的候選地址。
WebRTC 客戶端(也就是我們所說的端點,Jack Ma和Jobs)也需要確定和交換本地和遠程音頻、視頻的媒體信,如分辨率和編解碼器等功能。
MediaStream (別名 getUserMedia)
MediaStream API 代表媒體數據流的同步。舉個例子,從相機獲取的視頻流的同步和跟蹤。
理解MediaStream最簡單的方法應該就是看看它的實際應用:
在Chrome或Opera中, 打開這個demo simpl.info/gum。
打開命令行。
查看全局范圍的數據流變量。
每個MediaStream都有一個輸入,這個輸入可以理解成MediaStream生成的一個導航器。getUserMedia()可以傳輸視頻元素或者是RTCPeerConnection。
getUserMedia()方法有三個參數:
一個 約束對象
一個成功的回調,如果成功會回傳一個MediaStream
一個失敗的回調,如果失敗會回傳一個error對象。
每個MediaStream都有一個標簽,像*Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ*一樣,getAudioTradks()和getAudioTracks()方法會回傳一個MediaStreamTracks對象的數組。
針對 simpl.info/gum 這個例子來說,stream.getAudioTracks() 返回了一個空數組 (因為沒有音頻) , 假設已經有一個攝像頭連接成功,getVideoTracks()會返回一個MediaStreamTrack對象的數組, 這個數組代表從攝像頭得到的數據流。每個MediaStreamTrack都有一個類型 (*video* 或 *audio*), 和一個標簽(代表一個或多個頻道的音頻或視頻),在這個例子中,只有video track,但是很容易想象到可以用到這個例子的地方,比如一個聊天應用程序的前置攝像頭、后置攝像頭,一個屏幕分享軟件等等。
在Chrome或Opera中, URL.createObjectURL() 方法把MediaStream 轉換成了一個 Blob URL,Blob URL可以看成一個視頻元素的src。 (在Firefox和Opera中,視頻的src可以通過數據流本身設定)。
getUserMedia 也可以作為網絡音頻API的輸入節點:
1 function gotStream(stream) { 2 window.AudioContext = window.AudioContext || window.webkitAudioContext; 3 var audioContext = new AudioContext(); 4 5 // Create an AudioNode from the stream 6 var mediaStreamSource = audioContext.createMediaStreamSource(stream); 7 8 // Connect it to destination to hear yourself 9 // or any other node for processing! 10 mediaStreamSource.connect(audioContext.destination); 11 } 12 13 navigator.getUserMedia({audio:true}, gotStream);
基於Chromium的應用和擴展可以合並getUserMedia。在manifest 中添加audioCapture 和 videoCapture權限可以在加載的時候得到(僅一次)授權,畢竟加載之后用戶不會有對攝像頭或麥克風的訪問請求。同樣,forgetUserMedia()也是只有一次授權。
他的最終目的是使MediaStream能取到任意的數據源,不只是局限於攝像頭或是手機。這將拿其兼容其他輸入,如傳感器等。
需要注意的是getUserMedia()必須在服務器上使用,而不是本地文件中,否則的話將會拋出權限的錯誤。
getUserMedia() 已經成功的融合了其它的JavaScript APIs和庫:
Webcam Toy 是一個photobooth應用,它使用WebGL來添加一些特效,讓用戶可以共享照片或是保存本地。
FaceKat 是一個人臉追蹤的游戲,使用headtrackr.js。
ASCII Camera 使用Canvas API來生成ASCII碼的圖片。

約束
約束 在Chrome 24和Opera 18版本之后被引入。它們可以被用來設置 getUserMedia()和RTCPeerConnection addStream() 這些視頻的流的分辨率。 約束的實現是為了制約例如視頻高度和寬度的比例、幀率、和正反攝像頭模式等等……
針對約束,這里有一個例子: simpl.info/getusermedia/constraints.
一個陷阱:getUserMedia約束在瀏覽器所有選項卡影響約束后完成后才設置,設置一個錯誤的值會發生以下錯誤:
navigator.getUserMedia error:
NavigatorUserMediaError {code: 1, PERMISSION_DENIED: 1}
屏幕和標簽捕獲你同樣可以利用MediaStream捕獲屏幕和標簽的數據源。它已經在Chrome中實現了像這個例子一樣,但是在Opera上還沒有實現。
Chrome應用很多都已經實現了通過chrome.tabCaptureAPI 分享在線錄播的功能。更多具體的信息,如屏幕錄制的編碼,請到 Screensharing with WebRTC上進行相關學習,但是目前只支持Chrome。
信號: session控制,網絡和多媒體信息
WebRTC使用RTCPeerConnection進行兩個瀏覽器之間的數據流的通信,但是也需要一種機制來協調溝通控制信息,這一個過程叫做信號。信號的方法和協議不是WebRTC指定的,而是RTCPeerConnection API的一部分。
相應的,WebRTC應用開發者可以選擇任意一種自己喜歡的消息協議,比如SIP或是XMPP,也可以選擇任何適當的雙工協議,apprtc.appspot.com 這個例子使用XHR和Channel API機制的信號,codelab是我們構建的通過Socket.io運行在 Node服務器上的應用。
信號用來交換以下三個類型的信息:
Session控制信息:用來初始化或是關閉通信,並報告錯誤。
網絡配置:本機的IP和端口等配置。
媒體功能:編碼解碼器配置。
信號的配置必須沒有任何差錯,在完成點對點的傳輸之后就可以通過信號交換信息。
舉個例子,想像一下如果Jack Ma要和Jobs通信,這里有個demo來自於WebRTC W3C Working Draft, 它展示了信號的行為。下面的的代碼假設某種信號機制的存在,在createSignalingChannel方法中創建。還要注意:在Chrome,Opera中使用RTCPeerConnection是目前的前提。
1 var signalingChannel = createSignalingChannel(); 2 var pc; 3 var configuration = ...; 4 5 // run start(true) to initiate a call 6 function start(isCaller) { 7 pc = new RTCPeerConnection(configuration); 8 9 // send any ice candidates to the other peer 10 pc.onicecandidate = function (evt) { 11 signalingChannel.send(JSON.stringify({ "candidate": evt.candidate })); 12 }; 13 14 // once remote stream arrives, show it in the remote video element 15 pc.onaddstream = function (evt) { 16 remoteView.src = URL.createObjectURL(evt.stream); 17 }; 18 19 // get the local stream, show it in the local video element and send it 20 navigator.getUserMedia({ "audio": true, "video": true }, function (stream) { 21 selfView.src = URL.createObjectURL(stream); 22 pc.addStream(stream); 23 24 if (isCaller) 25 pc.createOffer(gotDescription); 26 else 27 pc.createAnswer(pc.remoteDescription, gotDescription); 28 29 function gotDescription(desc) { 30 pc.setLocalDescription(desc); 31 signalingChannel.send(JSON.stringify({ "sdp": desc })); 32 } 33 }); 34 } 35 36 signalingChannel.onmessage = function (evt) { 37 if (!pc) 38 start(false); 39 40 var signal = JSON.parse(evt.data); 41 if (signal.sdp) 42 pc.setRemoteDescription(new RTCSessionDescription(signal.sdp)); 43 else 44 pc.addIceCandidate(new RTCIceCandidate(signal.candidate)); 45 };
首先,Jack Ma和Jobs要交換網絡信息。 (表達式 *finding candidates*指向查找網絡接口和端口的進程,通過ICE framework完成)
Jack ma通過onicecandidatehandler創建一個RTCPeerConnection對象。
handler在網絡通的時候開始執行。
Jack Ma發送將序列化的數據發送給Jobs,通過WebSock或其它機制建立信號。
當Jobs收到這些序列化的信息之后,他會調用saddIceCandidate, 來添加遠程連接的候選地址。
WebRTC 客戶端(也就是我們所說的端點,Jack Ma和Jobs)也需要確定和交換本地和遠程音頻、視頻的媒體信,如分辨率和編解碼器等功能。