概述
有了HTML5,我们就可以在不借助Flash或者Silverlight的情况下完成这项工作了。
HTML5能够使我们访问设备的硬件,比如GPS,WebGL等等。
这篇文章,我们就来看看一个新的API——navigator.getUserMedia(),她允许网页应用去访问用户的摄像机和麦克风。
getUserMedia之路
第一阶段:HTML Media Capture
当我们设置标签,并设置此标签的accept属性,她就可以正常的工作了。
这个"API"的短板之处在于她做实时处理的能力比较弱,比如用canvas来渲染和应用于WebGL.
HTML Media Capture只允许你去及时的记录视频和拍照。
第二阶段:device element
很多人认为HTML Media Capture太有局限性了,所以一个强大的支持所有设备的元素出现了。好不惊奇的,她的名字就是,她就是getUserMedia要处理的对象。
Opera、WhatWG、Microsoft等都相继实现此元素与API。
看起来如下:
functionupdate(stream){
document.querySelector('video').src=stream.url;
}
不幸的是,没有发布的浏览器支持此标签。
尽管如此她还是有两个好处的:
语义化
高扩展性不仅仅是audio/video.
第三阶段:WebRTC
最终还是流产了。
多亏了WebRTC才让需找合适的API的步伐得意继续。
现在的getUserMedia()就是参考的WebRTC,因为这是通往一套API的桥梁。她提供了访问用户本地摄像机和麦克风的能力。
正式开始
特性检查
在使用之前我们应该检查一下我们的设备是否支持此方法。
functionhasGetUserMedia(){return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||navigator.mozGetUserMedia||navigator.msGetUserMedia);
}if(hasGetUserMedia()){
alert('Good to go!');
}else{
alert('Not supported!');
}
获得访问设备的权限
我们应当发送允许我们使用设备的请求。getUserMedia的第一个参数是一个对象,保存的是我们想要请求的设备。例如,如果我们想用摄像机和麦克风,第一个参数就是{video: true, audio: ture};
varerrorCallback= 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){varvideo=document.querySelector('video');
video.src=window.URL.createObjectURL(localMediaStream);
video.onloadedmetadata= function(e){//Do some stuff
};
}, errorCallback);
}
定制media
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);
});functionsourceSelected(audioSource, videoSource){var constraints ={
audio: {
optional: [{sourceId: audioSource}]
},
video: {
optional: [{sourceId: videoSource}]
}
};
navigator.getUserMedia(constraints, successCallback, errorCallback);
}
安全
当我们调用getUserMedia()时,浏览器会弹出一个对话框来让用户决定接下怎么做,不幸的是,当我们的应用使用的是https时,这将会被拒绝。
后备方法
对用不支持getUserMedia的用户来说,我们可以指定一个存在的video或者抛出错误提示。
functionfallback(e){
video.src= 'fallbackvideo.webm';
}functionsuccess(stream){
video.src=window.URL.createObjectURL(stream);
}if(!navigator.getUserMedia){
fallback();
}else{
navigator.getUserMedia({video:true}, success, fallback);
}
屏幕截图
我们可以使用捕获的某一帧,这样就可以实现截图了。
varvideo=document.querySelector('video');varcanvas=document.querySelector('canvas');varctx=canvas.getContext('2d');varlocalMediaStream= null;functionsnapshot(){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);
应用样式
使用css过滤器
}.grayscale{+filter:grayscale(1);
}.sepia{+filter:sepia(1);
}.blur{+filter:blur(3px);
}...
varidx= 0;varfilters=['grayscale','sepia','blur','brightness','contrast','hue-rotate','hue-rotate2','hue-rotate3','saturate','invert',''];functionchangeFilter(e) {varel=e.target;
el.className= '';vareffect=filters[idx++ %filters.length];//loop through filters.
if(effect) {
el.classList.add(effect);
}
}
document.querySelector('video').addEventListener('click', changeFilter,false);
WebGL纹理
使用Audio API
window.AudioContext = window.AudioContext ||window.webkitAudioContext;var context = newAudioContext();
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);