HTML5的权限愈来愈大了,浏览器能够直接调用摄像头、麦克风了,好激动啊。咱们要用纯洁的HTML代码造出本身的天地。html
本篇介绍的栗子 都是在chrome 47 版本以上的,低版本的可能会出现白屏和错误。前端
随着Chrome版本的升高,安全性问题也愈来愈被重视,较新版本的Chrome浏览器在调用一些API时须要页面处在安全环境中。本篇文章所介绍的API函数,都须要在安全环境中执行。若是处在非安全环境下 ( http页面 ) 这些API就会有意想不到的问题。html5
好比 getUserMedia()
就会报出警告,并执行出错。而在设备枚举enumerateDevices()
时,虽然不会报错,可是他隐藏了设备label。nginx
getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.web
根据谷歌的意思,经常使用的安全环境有以下chrome
https 开头的地址页面服务器
若是你作了一个视频测试的页面,想嘚瑟给局域网的其余人,可是又没有域名证书怎么办?
这时候只能经过修改其余人的hosts文件了
好比你的测试服务器IP地址是192.168.2.18,那么其余人的hosts文件修改以下:微信
#localhost 127.0.0.1 localhost 192.168.2.18
当使用别人的Chrome浏览器访问 http://localhost/[getUserMedi...时,就会顺利的执行这些API了。
可是移动端的浏览器并不认localhost,就算你修改了hosts ,移动端的浏览器根本不理你,解析都不解析。
因此想在手机上测试,只能老老实实申请个证书了。
在开启摄像头以前,先要把可使用的麦克风和摄像头 ( 输入设备 ) 列出来,若是没有这两样设备也就没法继续。
代码以下:
<label for="audioDevice"> 录音设备: </label> <select id="audioDevice"> </select> <br> <label for="videoDevice"> 录影设备: </label> <select id="videoDevice"> </select> <script> navigator.mediaDevices.enumerateDevices().then(function (data) { data.forEach(function (item) { if(item.kind=="audioinput"){ //麦克风 document.getElementById("audioDevice").innerHTML += "<option value='"+ item.deviceId +"'>" + item.label + " </option> " }else if(item.kind=="videoinput"){ //摄像头 document.getElementById("videoDevice").innerHTML += "<option value='"+ item.deviceId +"'>" + item.label + " </option> " } }) },function (error) { console.log(error); }) </script>
效果以下图,和浏览器本身获取的如出一辙。
注意:上图的实例中,浏览器地址栏最右边的摄像头标识是须要使用 getUserMedia()
函数时才会出现。
<script> var getUserMedia = navigator.webkitGetUserMedia; //Chrome浏览器的方法 getUserMedia.call(navigator, { video:true, // 开启音频 audio:true // 开启视频 }, function(stream){ console.log(stream); // 成功获取媒体流 }, function(error){ //处理媒体流建立失败错误 }); </script>
这时候能够经过浏览器给出的菜单下拉选择设备。
咱们能够经过代码来指定使用哪一个摄像头和麦克风设备。
也能够经过代码设置视频的宽、高和帧率。
代码以下:
<video id="video" autoplay></video> <!-- 必定要有 autoplay --> <script> var getUserMedia = navigator.webkitGetUserMedia ; getUserMedia.call(navigator, { "audio":{ "mandatory":{ "sourceId":"" // 指定设备的 deviceId } }, "video":{ "optional":[ {"minWidth":400}, {"maxWidth":400}, // 数字类型,固定宽度 {"minHeight":220}, {"maxHeight":220}, // 数字类型,固定高度 {"frameRate":"12"} // 帧率 ],"mandatory":{ "sourceId":"" // 指定设备的 deviceId } } }, function(stream){ //绑定本地媒体流到video标签用于输出 document.getElementById("video").src = URL.createObjectURL(stream); }, function(error){ //处理媒体流建立失败错误 }); </script>
输出的视频流经过blob对象连接绑定到video标签输出。
这个deviceId
就是从上文设备枚举 enumerateDevices()
获取到的。
两种设备,若是有一个deviceId
填写不正确,就会报出一个DevicesNotFoundError
的错误。并且一旦指定了设备后,浏览器本身的设备选择就会变成灰色不可选。
视频的宽高,并不会由于填写的数值比例不合法而失真。
好比你设定了宽度30,高度100,那么他会从视频中心截取 30x100 的画面,而不是把原画面挤压到这个30x100的尺寸。
效果以下:
若是您的预览一片漆黑,或者只有一个小黑点,那么说明您的摄像头正在被占用...
吐槽:这个getUserMedia()
函数的参数,w3的官方文档连接以下:
https://www.w3.org/TR/mediaca...
但是Chrome并无遵循它,并且差距还挺大...
Chrome浏览器是大力推广webm的视频格式的。能够用MediaRecorder.isTypeSupported("video/webm")
来测试是否支持这种类型的编码。若是返回true,那么咱们录制的视频就能够被保存为这种指定的格式。若是不指定,那么将会使用浏览器自动指定的文件格式。文档原话以下
If this paramater is not specified, the UA will use a platform-specific default format.
可是这个默认值却没法直接获取,全靠猜...
咱们使用 MediaRecorder
来录制视频,参数是经过getUserMedia()
获取的媒体流。
经过绑定ondataavailable
事件,来获取视频片断数据,并在内存中累积。
录制的开始和结束分别使用 start
和stop
函数。
执行start
以后会周期性触发ondataavailable
事件。
执行stop
以后会中止触发ondataavailable
事件。
录制结束后,把累计的片断数据保存为blob对象,并从浏览器下载存为视频文件。
代码以下:
<script> var getUserMedia = navigator.webkitGetUserMedia ; var g_stream = null, g_recorder = null; function startPreview(){ getUserMedia.call(navigator, { video:true, audio:true }, function(stream){ g_stream = stream; }, function(error){ }); } function stopRecording(){ g_recorder.stop(); } function startRecording(){ var chunks = []; g_recorder = new MediaRecorder(g_stream,{mimeType:"video/webm"}); g_recorder.ondataavailable = function(e) { chunks.push(e.data); } g_recorder.onstop = function(e) { var blob = new Blob(chunks, { 'type' : 'video/webm' }); var audioURL = URL.createObjectURL(blob); window.open(audioURL); } g_recorder.start(); } </script>
注意:本例并无填写视频文件头,因此保存出来的视频文件没有时间轨,没法快进和跳跃。能够用格式工厂转
“莫基了”上面有一个录制音频的例子 传送门
这篇文章的DEMO请戳 这里
相关阅读
多屏互动——H5中级进阶
前端,想说爱你不容易!
无需Flash实现图片裁剪——HTML5中级进阶
做者信息
做者来自力谱宿云 LeapCloud 团队_UX成员:王诗诗 【原创】
力谱宿云 LeapCloud 团队首发:https://blog.maxleap.cn/archi...
欢迎关注微信订阅号:MaxLeap_yidongyanfa