参考:

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的输入节点:
 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)也需要确定和交换本地和远程音频、视频的媒体信,如分辨率和编解码器等功能。
 
posted on 2014-11-03 15:56  ~小二黑~  阅读(5291)  评论(0编辑  收藏  举报