原文地址:http://www.html5rocks.com/en/tutorials/getusermedia/intro/
有了HTML5,我们就可以在不借助Flash或者Silverlight的情况下完成这项工作了。
HTML5能够使我们访问设备的硬件,比如GPS,WebGL等等。
这篇文章,我们就来看看一个新的API——navigator.getUserMedia(),她允许网页应用去访问用户的摄像机和麦克风。
当我们设置<input type="file">标签,并设置此标签的accept属性,她就可以正常的工作了。
<input type="file" accept="image/*;capture=camera"> <!--拍照--> <input type="file" accept="video/*;capture=camcorder"> <!--摄像--> <input type="file" accept="audio/*;capture=micophone"> <!--录音-->
这个"API"的短板之处在于她做实时处理的能力比较弱,比如用canvas来渲染和应用于WebGL.
HTML Media Capture只允许你去及时的记录视频和拍照。
很多人认为HTML Media Capture太有局限性了,所以一个强大的支持所有设备的元素出现了。好不惊奇的,她的名字就是<device>,她就是getUserMedia要处理的对象。
Opera、WhatWG、Microsoft等都相继实现此元素与API。
<device>看起来如下:
<device type="media" onchange="update(this.data)"></device> <video autoplay></video> <script> function update(stream){ document.querySelector('video').src = stream.url; } </script>
不幸的是,没有发布的浏览器支持此标签。
尽管如此她还是有两个好处的:
<device>最终还是流产了。
多亏了WebRTC才让需找合适的API的步伐得意继续。
现在的getUserMedia()就是参考的WebRTC,因为这是通往一套API的桥梁。她提供了访问用户本地摄像机和麦克风的能力。
在使用之前我们应该检查一下我们的设备是否支持此方法。
function hasGetUserMedia(){ return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); } if(hasGetUserMedia()){ alert('Good to go!'); }else{ alert('Not supported!'); }
我们应当发送允许我们使用设备的请求。getUserMedia的第一个参数是一个对象,保存的是我们想要请求的设备。例如,如果我们想用摄像机和麦克风,第一个参数就是{video: true, audio: ture};
<video autoplay></video> <script> var errorCallback = function(e){ console.log('Reeeejected!'); }; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; if(!!navigator.getUserMedia){ //good to go console.log('Not Suppoted!'); navigator.getUserMedia({video: true, audio: ture}, function(localMediaStream){ var video = document.querySelector('video'); video.src = window.URL.createObjectURL(localMediaStream); video.onloadedmetadata = function(e){ //Do some stuff }; }, errorCallback); } </script>
getUserMedia的第一个参数也可以被用实现高清等。
var hdConstraints = { video: { minWidth: 1280, minHeight: 720 } } navigator.getUserMedia(hdConstraints, successCallback, errorCallback); var vgaConstraints = { video: { mandatory: { maxWidth: 640, maxHeight: 360 } } } navigator.getUserMedia(vgaConstraints, successCallback, errorCallback);
在Chrome 30之后,我们可以使用MediaStreamTrack.getSources() API来选择video/audio的源。
MediaStreamTrack.getSources(function(sourceInfos){ var audioSource = null; var videoSource = null; for(var i=0; i!=sourceInfos.length; ++i){ var souceInfo = 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); }
当我们调用getUserMedia()时,浏览器会弹出一个对话框来让用户决定接下怎么做,不幸的是,当我们的应用使用的是https时,这将会被拒绝。
对用不支持getUserMedia的用户来说,我们可以指定一个存在的video或者抛出错误提示。
function fallback(e){ video.src = 'fallbackvideo.webm'; } function success(stream){ video.src = window.URL.createObjectURL(stream); } if(!navigator.getUserMedia){ fallback(); }else{ navigator.getUserMedia({video: true}, success, fallback); }
我们可以使用<canvas>捕获<video>的某一帧,这样就可以实现截图了。
<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); 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>
<style> video { width: 307px; height: 250px; background: rgba(255,255,255,0.5); border: 1px solid #ccc; } .grayscale { +filter: grayscale(1); } .sepia { +filter: sepia(1); } .blur { +filter: blur(3px); } ... </style> <video autoplay></video> <script> var idx = 0; var filters = ['grayscale', 'sepia', 'blur', 'brightness', 'contrast', 'hue-rotate', 'hue-rotate2', 'hue-rotate3', 'saturate', 'invert', '']; function changeFilter(e) { var el = e.target; el.className = ''; var effect = filters[idx++ % filters.length]; // loop through filters. if (effect) { el.classList.add(effect); } } document.querySelector('video').addEventListener( 'click', changeFilter, false); </script>
有兴趣的可以参考http://learningthreejs.com/blog/2012/02/07/live-video-in-webgl/ 这篇文章。
window.AudioContext = window.AudioContext || window.webkitAudioContext; var context = new AudioContext(); navigator.getUserMedia({audio: true}, function(stream) { var microphone = context.createMediaStreamSource(stream); var filter = context.createBiquadFilter(); // microphone -> filter -> destination. microphone.connect(filter); filter.connect(context.destination); }, errorCallback);