用JS getUserMedia调用摄像头展示上传

前言

    最近接手一个需求,页面上调用设备摄像头将拍摄的内容实时展示,用户可以随时截图上传,描述起来觉得挺简单,实际做了不少工作,特此记录。

get​User​Media使用环境

    目前获取摄像头流推荐的API是navigator.mediaDevices.getUserMedia,很多刚接触的小伙伴可能会发现自己的navigator找不到mediaDevices这个对象,如果你出现这种情况有两种方式可以解决,使用localhost或者https协议(推荐),我本人开发过程中使用Vue+webpack,对于https有很便捷的支持,只需要在webpack配置文件devServer选项中添加https: true 参考链接。

注:如果你遇到程序出现req.handle.writev is not a function, 这种情况一般会发生在iphone请求https时候,我的解决方法是给node降级,没搜到什么好方法,参考自https://github.com/nodejs/node/issues/21665,都是泪...

给get​User​Media做个备胎

    并不是所有的用户浏览器都是支持get​User​Media,我们又不知道究竟各个浏览器哪个版本是支持的,为了兼容性我们给get​User​Media做个垫片,代码从MDN上copy而来。

// Older browsers might not implement mediaDevices at all, so we set an empty object first
if (navigator.mediaDevices === undefined) {
  navigator.mediaDevices = {};
}

// Some browsers partially implement mediaDevices. We can't just assign an object
// with getUserMedia as it would overwrite existing properties.
// Here, we will just add the getUserMedia property if it's missing.
if (navigator.mediaDevices.getUserMedia === undefined) {
  navigator.mediaDevices.getUserMedia = function(constraints) {

    // First get ahold of the legacy getUserMedia, if present
    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

    // Some browsers just don't implement it - return a rejected promise with an error
    // to keep a consistent interface
    if (!getUserMedia) {
      return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
    }

    // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
    return new Promise(function(resolve, reject) {
      getUserMedia.call(navigator, constraints, resolve, reject);
    });
  }
}

调用get​User​Media

    所有的准备工作都已经做好了,那下一部分就是开始使用get​User​Media来获取视频流了,不出意外你就可以打开摄像头并且在video中播放实时画面了。

navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(function(stream) {
  var video = document.querySelector('video');
  // Older browsers may not have srcObject
  if ("srcObject" in video) {
    video.srcObject = stream;
  } else {
    // Avoid using this in new browsers, as it is going away.
    video.src = window.URL.createObjectURL(stream);
  }
  video.onloadedmetadata = function(e) {
    video.play();
  };
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});

iphone运行有问题

    如果上几步你都跟着做了,你应该发现在PC网页端可以完美运行,如果你尝试在移动端运行,运气好你先拿起了一部安卓手机,完美运行,你又拿起了一部iphone,what?为什么只有第一帧就卡住了(PS:iphone微信打开无法运行,我也没有解决,只能用Safari打开),找不到那篇说明文档了,大致说一下意思就是苹果对于网页端媒体开发进行了限制,会限制视频的自动播放,需要用户主动去触发授权。比如可以在onclick事件中调用,我看文档上写着还可以设置viedo无声(muted属性)也可以自动播放,我尝试并没有效果,结果就是加了一个按钮,让用户主动去调用video.play()。OK,那就好了吗?你会发现苹果会自己把video全屏,那有些时候这可能不是你想要的效果,解决方法,Safari在10版本前后有些差异,webkit-playsinline、playsinline作用相同,只不过为了更全面的兼容性。

 

你可能感兴趣的:(工作总结)