浏览器的音视频接口GetUserMedia
HTML5带来了一系列的新功能。比如:GPS,WebGL,Web Audio API. 这些功能很轻大,通过高层的Javascript APIS调用系统底层硬件。
navigator.getUserMedia 这个接口也有个有趣的历史故事。
在过去几年中,“媒体捕获API”的几个变体已经演变。许多人认识到需要能够访问网络上的本地设备,但这导致每个人和他们的妈妈都制定了一个新的规范。事情变得如此混乱,以至于W3C最终决定成立一个工作组。他们唯一的目的是什么?让疯狂变得有意义!设备API政策(DAP)工作组的任务是整合和标准化大量提案。
我将尝试总结2011年发生的事情…
第1轮:HTML媒体捕获#
HTML媒体捕获是DAP第一次标准化网络媒体捕获。它通过重载<input-type=“file”>并为accept参数添加新值来工作。
如果您想让用户使用网络摄像头拍摄自己的快照,使用capture=camera可以做到这一点:
<input-type=“file”accept=“image/*;capture=camera”>
录制视频或音频类似:
<input type=“file”accept=“video/*;capture=摄像机”>
<input-type=“file”accept=“audio/*;capture=麦克风”>
<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">
不错吧?我特别喜欢它重用文件输入。从语义上讲,这很有意义。这个特定的“API”不具备实时效果的能力(例如,将实时网络摄像头数据渲染到<canvas>并应用WebGL过滤器)。HTML媒体捕获仅允许您及时录制媒体文件或拍摄快照。
navigator.getUserMedia 这个接口也有个有趣的历史故事。
在过去几年中,“媒体捕获API”的几个变体已经演变。许多人认识到需要能够访问网络上的本地设备,但这导致每个人和他们的妈妈都制定了一个新的规范。事情变得如此混乱,以至于W3C最终决定成立一个工作组。他们唯一的目的是什么?让疯狂变得有意义!设备API政策(DAP)工作组的任务是整合和标准化大量提案。
我将尝试总结2011年发生的事情…
第1轮:HTML媒体捕获#
HTML媒体捕获是DAP第一次标准化网络媒体捕获。它通过重载<input-type=“file”>并为accept参数添加新值来工作。
如果您想让用户使用网络摄像头拍摄自己的快照,使用capture=camera可以做到这一点:
<input-type=“file”accept=“image/*;capture=camera”>
录制视频或音频类似:
<input type=“file”accept=“video/*;capture=摄像机”>
<input-type=“file”accept=“audio/*;capture=麦克风”>
<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">
不错吧?我特别喜欢它重用文件输入。从语义上讲,这很有意义。这个特定的“API”不具备实时效果的能力(例如,将实时网络摄像头数据渲染到<canvas>并应用WebGL过滤器)。HTML媒体捕获仅允许您及时录制媒体文件或拍摄快照。
支持:
Android 3.0浏览器-首批实现之一。查看此视频以查看其实际操作。
Android版Chrome(0.16)
Firefox Mobile 10.0
iOS6 Safari和Chrome(部分支持)
第2轮:设备元素#
许多人认为HTML媒体捕获限制太大,因此出现了一种支持任何类型(未来)设备的新规范。毫不奇怪,该设计需要一个新元素,即<device>元素,它成为getUserMedia()的前身。
Opera是最早基于<device>元素创建视频捕获初始实现的浏览器之一。不久后(准确地说是同一天),WhatWG决定放弃<device>标签,转而选择另一个新的,这次是一个名为navigator.getUserMedia()的JavaScript API。一周后,Opera发布了新的版本,其中包括对更新的getUserMedia(()规范的支持。同年晚些时候,微软发布了支持新规范的IE9实验室,加入了这一行列。
以下是<device>的外观:
Android 3.0浏览器-首批实现之一。查看此视频以查看其实际操作。
Android版Chrome(0.16)
Firefox Mobile 10.0
iOS6 Safari和Chrome(部分支持)
第2轮:设备元素#
许多人认为HTML媒体捕获限制太大,因此出现了一种支持任何类型(未来)设备的新规范。毫不奇怪,该设计需要一个新元素,即<device>元素,它成为getUserMedia()的前身。
Opera是最早基于<device>元素创建视频捕获初始实现的浏览器之一。不久后(准确地说是同一天),WhatWG决定放弃<device>标签,转而选择另一个新的,这次是一个名为navigator.getUserMedia()的JavaScript API。一周后,Opera发布了新的版本,其中包括对更新的getUserMedia(()规范的支持。同年晚些时候,微软发布了支持新规范的IE9实验室,加入了这一行列。
以下是<device>的外观:
<device type="media" onchange="update(this.data)"></device> <video autoplay></video> <script> function update(stream) { document.querySelector('video').src = stream.url; } </script>
支持:
不幸的是,从未发布过包含<device>的浏览器。我想,不必担心一个API:)<device>确实有两个优点:1)它是语义的,2)它很容易扩展,支持的不仅仅是音频/视频设备。
喘口气这东西动作很快!
第3轮:WebRTC#
<device>元素最终走上了渡渡鸟的道路。
由于更大的[WebRTC][WebRTC规范](Web实时通信)努力,寻找合适的捕获API的步伐加快了。该规范由W3C WebRTC工作组监督。谷歌、Opera、Mozilla和其他一些公司都有实现。
getUserMedia()与WebRTC相关,因为它是一组API的网关。它提供了访问用户本地摄像机/麦克风流的方法。
支持:
自Chrome 21、Opera 18和Firefox 17以来,getUserMedia()一直受到支持。
入门#
使用navigator.getUserMedia(),我们终于可以在不使用插件的情况下使用网络摄像头和麦克风输入。摄像头接入现在只需通话,而不是安装。它直接烘焙到浏览器中。兴奋了吗?
特征检测#
功能检测是对navigator.getUserMedia是否存在的简单检查:
使用navigator.getUserMedia(),我们终于可以在不使用插件的情况下使用网络摄像头和麦克风输入。摄像头接入现在只需通话,而不是安装。它直接烘焙到浏览器中。兴奋了吗?
特征检测#
功能检测是对navigator.getUserMedia是否存在的简单检查:
function hasGetUserMedia() { return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); } if (hasGetUserMedia()) { // Good to go! } else { alert('getUserMedia() is not supported in your browser'); }
您还可以使用Modernizr检测getUserMedia,以避免供应商前缀dance:
if (Modernizr.getusermedia){ var gUM = Modernizr.prefixed('getUserMedia', navigator); gUM({video: true}, function( //... //... }
访问输入设备#
要使用网络摄像头或麦克风,我们需要请求许可。getUserMedia()的第一个参数是一个对象,指定要访问的每种媒体类型的详细信息和要求。例如,如果要访问网络摄像头,第一个参数应该是{video:true}。要同时使用麦克风和相机,请传递{video:true,audio:true}:
<video autoplay></video> <script> var errorCallback = function(e) { console.log('Reeeejected!', e); }; // Not showing vendor prefixes. navigator.getUserMedia({video: true, audio: true}, function(localMediaStream) { var video = document.querySelector('video'); video.src = window.URL.createObjectURL(localMediaStream); // Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia. // See crbug.com/110938. video.onloadedmetadata = function(e) { // Ready to go. Do some stuff. }; }, errorCallback); </script>
好的。那么这里发生了什么?媒体捕获是新的HTML5 API协同工作的完美例子。它与我们的其他HTML5好友<audio>和<video>一起工作。注意,我们没有在<video>元素上设置src属性或包含<source>元素。我们不是向视频提供一个URL到媒体文件,而是向视频提供从表示网络摄像头的LocalMediaStream对象获得的Blob URL。
我还告诉<video>自动播放,否则它将在第一帧被冻结。添加控件也可以如您所预期的那样工作。
如果您需要跨浏览器工作的功能,请尝试以下操作:
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; var video = document.querySelector('video'); if (navigator.getUserMedia) { navigator.getUserMedia({audio: true, video: true}, function(stream) { video.src = window.URL.createObjectURL(stream); }, errorCallback); } else { video.src = 'somevideo.webm'; // fallback. }
设置介质限制(分辨率、高度、宽度)#
getUserMedia()的第一个参数也可以用于指定返回的媒体流的更多要求(或约束)。例如,您可以另外要求流是高清的,而不是仅仅表示您想要基本访问视频(例如{vide:true}):
var hdConstraints = { video: { mandatory: { minWidth: 1280, minHeight: 720 } } }; navigator.getUserMedia(hdConstraints, successCallback, errorCallback); ... var vgaConstraints = { video: { mandatory: { maxWidth: 640, maxHeight: 360 } } }; navigator.getUserMedia(vgaConstraints, successCallback, errorCallback);
For more configurations, see the constraints API
选择媒体源#
在Chrome 30或更高版本中,getUserMedia()还支持使用MediaStreamTrack.getSources()API选择视频/音频源。
在此示例中,找到的最后一个麦克风和相机被选为媒体流源:
选择媒体源#
在Chrome 30或更高版本中,getUserMedia()还支持使用MediaStreamTrack.getSources()API选择视频/音频源。
在此示例中,找到的最后一个麦克风和相机被选为媒体流源:
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, successCallback, errorCallback); }
Check out Sam Dutton's great demo of how to let users select the media source.
安全#
一些浏览器在调用getUserMedia()时会弹出一个信息栏,用户可以选择授权或拒绝访问其相机/麦克风。不幸的是,当涉及到安全性时,该规范非常安静。例如,这里是Chrome的权限对话框:
如果您的应用程序是从SSL(https://)运行的,则此权限将是永久性的。也就是说,用户不必每次都授予/拒绝访问权限。
提供回退#
对于不支持getUserMedia()的用户,如果API不受支持和/或由于某种原因调用失败,一个选项是回退到现有视频文件:
安全#
一些浏览器在调用getUserMedia()时会弹出一个信息栏,用户可以选择授权或拒绝访问其相机/麦克风。不幸的是,当涉及到安全性时,该规范非常安静。例如,这里是Chrome的权限对话框:
如果您的应用程序是从SSL(https://)运行的,则此权限将是永久性的。也就是说,用户不必每次都授予/拒绝访问权限。
提供回退#
对于不支持getUserMedia()的用户,如果API不受支持和/或由于某种原因调用失败,一个选项是回退到现有视频文件:
阅读量: 724
发布于:
修改于:
发布于:
修改于: