司项目需要调用摄像头,看了一下html5文档,主要是使用html5的getUserMedia()API,写一个例子来记录具体的使用方法。
<html> <body> <!-- 用于展示摄像头视频流 --> <video id="video" autoplay style="width: 480px;height: 320px"></video> <div> <button id="capture" onclick="handleClickCapture()">拍照</button> </div> <!-- 展示拍摄的照片 --> <canvas id="canvas" width="480" height="320"></canvas> <script> var video = document.getElementById('video'); var capture = document.getElementById('capture'); var ctx = document.getElementById('canvas').getContext('2d'); /** * 调用用户媒体设备 * @param constraints 配置信息 * @param success 成功回调函数 * @param error 失败回调函数 */ function getUserMediaToPhoto(constraints,success,error) { if(navigator.mediaDevices.getUserMedia){ navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error); }else if (navigator.webkitGetUserMedia) { navigator.webkitGetUserMedia(constraints,success,error); }else if(navigator.mozGetUserMedia){ navigator.mozGetUserMedia(constraints,success,error); }else if(navigator.getUserMedia){ navigator.getUserMedia(constraints,success,error); } } /** * 成功回调函数 * @param stream 视频流 */ function success(stream){ var CompatibleURL = window.URL || window.webkitURL; try { video.src = CompatibleURL.createObjectURL(stream); } catch (e) { video.srcObject = stream; } video.play(); } /** * 失败回调 * @param error 错误对象 */ function error(error) { console.log('无法访问媒体设备', error); } if(navigator.mediaDevices.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia){ getUserMediaToPhoto({video:{width:480,height:320}},success,error); }else{ alert('不支持访问用户媒体设备'); } /** * 拍照按钮点击事件 */ function handleClickCapture() { ctx.drawImage(video,0,0,480,320); } </script> </body> </html>
实现了基本的摄像头调用和拍照,实现思路非常简单,基本上只是在调用api,唯一恶心的地方在于api版本比较多,不得不多做一些判断。具体的api介绍、使用和参数可以查看MediaDevices.getUserMedia()。
外小哥利用了几行代码直接访问了手机的相机功能,这听起来是一件很新鲜的事情。究竟是怎么实现的呢?感兴趣的话,可以继续了解下去哦。
这位国外小哥是从事网页开发的工程师,海外网友都叫他Austin Gil。
既然是从事网页开发设计的,对HTML、java、CSS等相关网页语言都很熟悉了。
Austin Gil采用了最简单的网页语言,仅用HTML,实现了在网页上点击按钮就能够直接打开手机前置镜头来拍照。也可以调用手机后置镜头,开启录像模式。
整个编译过程,利用了HTML的capture属性,设置几个input参数和加上几行代码就搞定了,不费吹灰之力。
虽然用JavaScript或其它的方法也可以实现,但比起别的方法,这样能够便捷地获取用户相机权限,而且不用担心安全问题。
很多人都想知道相关代码,接下来会提到的,一起来看看吧。
教你使用HTML打开相机:
首先创建一个index.html文档,配合HTML的accpet属性,来指定不同标签所要capture的文件的具体属性。
Austin Gil设置了“environment”和“user”两个标签。
点击“environment”,可以调用相机的后置镜头,且可以录像;
点击“user”,可以打开相机前置镜头拍照。
具体代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<style>
* {
font-size: 1.5rem;
}
</style>
</head>
<body>
<label for="environment">Capture environment:</label>
<br>
<input
type="file"
id="environment"
capture="environment"
accept="video/*"
>
<br><br>
<label for="user">Capture user:</label>
<br>
<input
type="file"
id="user"
capture="user"
accept="image/*"
>
</body>
</html>
从这些代码中,我们可以捕获到一个信息,就是没有提示用户是否打开访问相机的权限,网页就直接调用了相机。
问题是,这样操作,没有安全风险吗?
当很多人提出疑惑的时候,Austin Gil做出了解释:无额外风险。
浏览器其实并不能真正控制手机相机APP,即便是这样操作可以直接访问,但也只不过是能轻松上传相机生成的新文件而已。
简单来说,就是对于用户而言,浏览器通过HTML只能打开手机摄像头。如果要把照片、视频展示到网站上,或是想要保存下来,还得用到JavaScript的MediaDevices API。
这样操作是比纯用JavaScript更安全的。
因为运用JavaScript,在用户允许访问相机后,浏览器就能直接控制摄像头了。
而在Web 3.0标准之后,规定网页不能直接访问用户的手机镜头。
PS:现在主要用的是Web 5的标准。
最后是兼容性,据悉在这方面并不是很好。
Austin Gil指出,这种直接通过HTML指令打开用户摄像头的方式目前还存在不足,比如兼容性不太好。
如下图所示:
红色模块:不支持
绿色模块:支持
棕色模块:部分支持
灰色:未知
很多网友在好奇心的驱使下,测试了调用手机相机的代码。也有前端小哥进行了测试,结果如下:
点击environment和user按钮,在MacBook上分别可以打开视频格式和图片格式的文件;而在iPhone上,使用百度等浏览器,真的可以直接打开前置和后置摄像头!
好咯,本期内容就分享到这里了~
PC 端网页调用摄像头的场景想必大家并不陌生,打开一个网址,开启摄像头开始笔试/视频聊天/直播等。
而在移动端网页调用摄像头的场景你见得多吗?我想答案应该是不多吧(在下见识浅薄)。
H5 相较于native app 一直被诟病的就有调用手机原生能力差这一点。
但需求总是会突如其来,做与不做?
其实,做与不做都不应该影响你去贮备相关知识、做较为充分的调研。市面上类似的技术实现不多,不代表不能做。真的不能做,也至少得知道原因吧?
也许在你探寻的过程中,就会有不一样的发现。
方案一就是 webRTC,也正是 PC 端的实现方案。
WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。 —— MDN-WebRTC_API
核心的API为:navigator.mediaDevices.getUserMedia
Can I Use:看一下这个 API 的兼容情况
https://caniuse.com/?search=GetUserMedia
本瓜结合网上代码,小做修改,放到了线上。
在线测试地址:https://tuaran.site/static/webrtc.html
贴下关键代码
<body>
<div>H5调前置摄像头DEMO</div>
<video id="video" width="480" height="320" muted controls autoplay="autoplay">
</video>
<div>
<button id="capture">拍照</button>
</div>
<canvas id="canvas" width="480" height="320"></canvas>
<script>
//访问用户媒体设备的兼容方法
function getUserMedia(constraints, success, error) {
if (navigator.mediaDevices.getUserMedia) {
//最新的标准API
navigator.mediaDevices.getUserMedia({
'audio':{ echoCancellation: false },
'video':{ 'facingMode': "user" }//调用前置摄像头,后置摄像头使用video: { facingMode: { exact: "environment" } }
})
.then(success)
.catch(error)
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
navigator.webkitGetUserMedia(constraints, success, error)
} else if (navigator.mozGetUserMedia) {
//firfox浏览器
navigator.mozGetUserMedia(constraints, success, error);
} else if (navigator.getUserMedia) {
//旧版API
navigator.getUserMedia(constraints, success, error);
}
}
let video = document.getElementById('video');
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
function success(stream) {
//兼容webkit核心浏览器
let CompatibleURL = window.URL || window.webkitURL;
//将视频流设置为video元素的源
console.log(stream);
//video.src = CompatibleURL.createObjectURL(stream);
video.srcObject = stream;
video.play();
}
function error(error) {
console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
}
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
//调用用户媒体设备, 访问摄像头
getUserMedia({ video: { width: 480, height: 320 } }, success, error);
} else {
alert('不支持访问用户媒体');
}
document.getElementById('capture').addEventListener('click', function () {
context.drawImage(video, 0, 0, 480, 320);
})
</script>
</body>
用 video 播放视频,如果想要实现截屏,则用 canvas 进行绘制。
从上图和实践中可以得出,WebRTC调起摄像头的方案 PC 端支持良好,但移动端浏览器支持不一。 国内的安卓机自置浏览器大部分为低版本的 chrome 内核分支,加壳嵌套,更新缓慢。iOS 对于 Vedio 标签属性的兼容也不尽如人意。
这里安利一个第三方库 tracking.js
它上面有关于 face_camera 的 demo 正用的此解决方案。
调用前置摄像头代码实现:
<input class="phone_input" type="file" accept="video/* capture="user" />
https://caniuse.com/?search=capture
同样把代码放到了线上,在线测试地址 https://tuaran.site/static/capture.html
PC 不支持,iOS 支持良好,少部分 Android 机存在兼容差异(部分8.0以上安卓机无法调起前置,会调起后置)。
WebRTC | capture |
PC 支持 | PC 不支持 |
移动端兼容性混乱 | 移动端兼容性较优 |
可自定义视频分辨率/窗口大小等(直播流) | 无法自定义(本地全屏录制) |
代码实现复杂 | 代码实现简单 |
综上:在移动端网页调起摄像头,WebRTC 方案兼容性较差,但可自定义程度很高,可操作视频流、设定分辨率、调整窗口大小等,实现近似 app 调用摄像头的效果,但相应的实现难度就高、兼容也相对复杂;而 capture 方案兼容性较好,但只是调用原生的相机进行一段视频录制,可自定义程度不高。如果视频过大,压缩等也将是一个问题。如何平衡二者?可以在兼容的情况下使用前者,不兼容的情况下使用后者,浏览器才是最终的答案。
本瓜相信 H5 一定将会有更多更好的能力!
我是掘金安东尼: 一名人气前端技术博主(文章 100w+ 阅读量)
终身写作者(INFP 写作人格)
坚持与热爱(简书打卡 1000 日)
我能陪你一起度过漫长技术岁月吗(以梦为马)
觉得不错,给个三连吧(这是我最大的动力 ) b( ̄▽ ̄)d
*请认真填写需求信息,我们会在24小时内与您取得联系。