xjcloudy

获取用户端的图像数据  |  Web  |  Google Developers

xjcloudy · 2016-11-20翻译 · 1315阅读 原文链接

目前,很多浏览器已经具备了访问用户端输入的音频与视频的能力。 但是,这取决于浏览器是内部处理还是委托给用户设备中其他的应用去处理。

开始

最简单的情况,就是添加一个file标签。加上accept属性。用来声明希望获得的文件类型。 理想情况下,就可以直接通过摄像头获取到相应的文件。

 <input type="file" accept="image/*" capture>

这种方法在所有平台中都是可用的。在桌面系统中,会给用户一个上传文件弹窗提示。用户可以选择本地文件上传。在IOS的Safari里则会打开摄像机,允许用户拍摄照片然后返回web页;在Android中会由用户来先选择拍摄照片的应用,然后拍摄并返回。

返回的数据作为<form>的数据或者通过设置一个ochange事件监听,在回调参数中的event对象中的target属性获取。

捕获单张画面

访问图片文件很简单

<input type="file" accept="image/*" capture="camera" id="camera">
<img>
&lt;script&gt;
  var camera = document.getElementById('camera');
  var frame = document.getElementById('frame');

  camera.addEventListener('change', function(e) {
    var file = e.target.files[0]; 
    // 对图片文件做些操作.
    frame.src = URL.createObjectURL(file);
  });
&lt;/script&gt;

一旦获取到图片文件,你就可以做任何你想做的。比如:

  • 直接绑定到一个 canvas 元素上面, 这样就可以使用它了

  • 下载到设备

  • 通过 XMLHttpRequest 上传到服务器

同时,使用input元素获取图片是很常见的做法,但是是最不推荐的做法,因为没有完全集成到网页中,同时在桌面浏览器里不能访问用户的网络摄像头。

交互式访问摄像机

现代浏览器可以直接与摄像机交互,用户无需离开浏览器,也可以获得完整的交互体验。

警告: 直接与摄像机交互是一个强大的功能,需要获得用户的许可,并且你的网站需要开启https。

获取访问摄像机的许可

我们可以使用WebRTC规范中的一个叫做getUserMedia()的API,来访问摄像机与麦克风。它会提示用户程序需要访问摄像头和麦克风。 如果得到用户授权,这个API会返回一个MediaStream对象,包含了有关摄像机的数据。接下来我们既可以通过将它绑定到一个<video> 元素上面而实现实时预览效果,也可以绑定到&lt;canvas&gt;上面来获取快照。

想要获得摄像机的数据,调用getUserMedia()时传递一个video: true的配置就好。

<video controls autoplay></video>
&lt;script&gt;  
  var player = document.getElementById('player');

  var handleSuccess = function(stream) {
    player.srcObject = stream;
  };

  navigator.mediaDevices.getUserMedia({video: true})
      .then(handleSuccess);
&lt;/script&gt;

单独看来这其实没什么用,你能做的仅仅是做个视频回放而已。

获取快照

为了能访问摄像机获得的原始数据,我们需要处理getUserMedia()返回的流。不像Web Audio那样,对于视频没有专用的处理流数据的API。所以我们的做点hack工作才能得到快照。

过程如下:

  1. 创建一个canvas对象用来保持摄像机的画面。

  2. 获得摄像机的流数据。

  3. 绑定到一个video元素上

  4. 当你需要捕获一副画面时,使用drawImage()方法将video的数据保存到canvas对象。

结束.

<video controls autoplay></video>
&lt;button id="capture"&gt;Capture&lt;/button&gt;
&lt;canvas id="snapshot" width=320 height=240&gt;&lt;/canvas&gt;
&lt;script&gt;
  var player = document.getElementById('player'); 
  var snapshotCanvas = document.getElementById('snapshot');
  var captureButton = document.getElementById('capture');

  var handleSuccess = function(stream) {
    //绑定视频流到video元素,并自动播放
    player.srcObject = stream;
  };

  captureButton.addEventListener('click', function() {
    var context = snapshot.getContext('2d');
    // 将画面`画`到canvas中.
    context.drawImage(player, 0, 0, snapshotCanvas.width, 
        snapshotCanvas.height);
  });

  navigator.mediaDevices.getUserMedia({video: true})
      .then(handleSuccess);
&lt;/script&gt;

得到存到canvas中的数据后,你就可以做很多事情。比如:

  • 上传到服务器

  • 存到本地

  • 加滤镜之类很酷的东西

不需要使用流的时候记得关闭

当你不再需要使用摄像机时,记得及时关闭它。这是比较推荐的做法。不只是为了省电,也会使用户对你的应用增加信任(让人觉得你的应用质量可靠,不是恶意程序之类。译者注)

要停止访问摄像机。只需要在每一个通过getUserMedia()获得的流上面调用stop()即可。

<video controls autoplay></video>
&lt;button id="capture"&gt;Capture&lt;/button&gt;
&lt;canvas id="snapshot" width=320 height=240&gt;&lt;/canvas&gt;
&lt;script&gt;
  var player = document.getElementById('player'); 
  var snapshotCanvas = document.getElementById('snapshot');
  var captureButton = document.getElementById('capture');
  **var videoTracks;**

  var handleSuccess = function(stream) {
    // 绑定视频流到video元素,并自动播放
    player.srcObject = stream;
    **videoTracks = stream.getVideoTracks();**
  };

  captureButton.addEventListener('click', function() {
    var context = snapshot.getContext('2d');
    context.drawImage(player, 0, 0, snapshotCanvas.width, snapshotCanvas.height);

    **// 关闭所有的视频流.
    videoTracks.forEach(function(track) {track.stop()});**
  });

  navigator.mediaDevices.getUserMedia({video: true})
      .then(handleSuccess);
&lt;/script&gt;

请求用户授权

如果用户之前没有给你的网站授权过访问摄像机的权限。那么当你调用getUserMedia时浏览器会立刻给用户一个弹窗确认。请求用户授权访问摄像机。

用户比较讨厌这种要求访问他们的关键设备的请求。所以经常会阻塞请求,或者如果他们不清楚这个弹窗来自哪里时就会忽略掉它。 最佳实践就是,仅首次使用摄像机时请求用户授权,一旦用户授权通过就不会再次询问。但是,如果用户在第一次拒绝了授权,那么你就再也无法获得权限,除非用户手动更改权限设置。

警告: 在页面加载时,请求用户授权,大部分用户会选择拒绝。

兼容性

更多的关于移动端与桌面浏览器的实现请查看 srcObject navigator.mediaDevices.getUserMedia() 我们也建议使用adapter.js这个shim库,来解决WebRTC的兼容性问题。


版权声明 Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the Apache 2.0 License. For details, see our Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

译者xjcloudy尚未开通打赏功能

相关文章