请在Chrome、Firefox等现代浏览器浏览本站。

getUserMedia html5 摄像头截图

html+html5 admin 1214℃
  •  navigator.getUserMedia
  •  MediaStreamTrack.getSources
  •  Node.JS相关

涉及到的一些不常见却必须的方法或属性

getUserMedia

getUserMedia是window宿主下navigator对象的方法,由于直到目前HTML5的多媒体相关的标准还没有最终确定,所以还是用下文中列出的兼容方法,而在我的这个应用场景中,由于只在webkit下路,所以事实上,只需要navigator.webkitGetUserMedia即可。

JavaScript:

navigator.getUserMedia = ( 
    navigator.getUserMedia ||
    navigator.webkitGetUserMedia ||
    navigator.mozGetUserMedia || 
    navigator.msGetUserMedia
);

完整的调用语句:

JavaScript:


navigator.getUserMedia({video: true,audio:false}, function (stream) {
     //在这里操作stream对象,一般是用createObjectURL把stream生成URL对象输出给video元素的src属性
     //videoDom.src=window.webkitURL.createObjectURL(stream);
}, function (error) {
     console.log(error);
});

网上有许多教程为getUserMedia的第一个参数赋值是video,而不是{video: true}。这是因为之前说的标准还没有确定,这个接口早期就是这样定义的,而之后发现它不足够,就重新定义了。

为什么说之前定义一个video是不够的?

getUserMedia,顾名思意是获取用户的多媒体,所以除了视频,还有音频,所以接口要变成类似{video: true,audio:false},可以设定音视频的获取开关。

如果只是知道这里,那么很认真的告诉你,你目前的知识还不足够使用!

你会发现video元素渲染的画面品质很差,不管你使用多好的摄像头设备!当遇到这个问题时,我几乎放弃了Node-Webkit+H5方案,打算直接调directshow的vfw接口。但就在我打开vs2012,打算开操c++时候,不甘的心情让我决定做一个尝试,直接看一下chrome的相关源码,我不相信他们会傻x成这样.

于是让我看到了这么一段代码:

media_stream_video_source.cc

CPP:


#include "base/logging.h"    
#include "base/strings/string_number_conversions.h"    
#include "content/renderer/media/media_stream_dependency_factory.h"   
#include "content/renderer/media/media_stream_video_track.h"   
#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"   
namespace content {

// Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b
const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio";
const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio";
const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth";
const char MediaStreamVideoSource::kMinWidth[] = "minWidth";
const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight";
const char MediaStreamVideoSource::kMinHeight[] = "minHeight";
const char MediaStreamVideoSource::kMaxFrameRate[] = "maxFrameRate";
const char MediaStreamVideoSource::kMinFrameRate[] = "minFrameRate"

const char* kSupportedConstraints[] = {    
    MediaStreamVideoSource::kMaxAspectRatio,
    MediaStreamVideoSource::kMinAspectRatio,
    MediaStreamVideoSource::kMaxWidth,
    MediaStreamVideoSource::kMinWidth,
    MediaStreamVideoSource::kMaxHeight,
    MediaStreamVideoSource::kMinHeight,
    MediaStreamVideoSource::kMaxFrameRate,
    MediaStreamVideoSource::kMinFrameRate    
};

const int MediaStreamVideoSource::kDefaultWidth = 640;   
const int MediaStreamVideoSource::kDefaultHeight = 480;  
const int MediaStreamVideoSource::kDefaultFrameRate = 30;  

namespace {  

// Constraints keys for http://dev.w3.org/2011/webrtc/editor/getusermedia.html
const char kSourceId[] = "sourceId";
// Google-specific key prefix. Constraints with this prefix are ignored if they
// are unknown.

const char kGooglePrefix[] = "goog";

看到这段代码后我的困惑消失了,kDefaultWidthkDefaultHeight是组成了默认的视频分辩率,如果没有特别设定的话,这种品质最多也就相当于我们平时所说的480p。

在这段代码里还有几个特别的属性minAspectRatio(最小宽比)、maxAspectRatio(最大宽高比)、maxFrameRate(最大每秒帧数)、minFrameRate(最小每秒帧数),似乎我们所能想到的都已经定义了。

而上文提到的kDefaultWidthkDefaultHeight并不是webkit暴露给JavaScript的接口,需要用到maxHeight,minHeight,maxWidth,minHeight,只要在这里设定的合理的值(4:3或16:9,我使用的是1280*720,也就是常说的720p),就可以改变输出的画质

最后的代码如下:

JavaScript:

 navigator.getUserMedia({
        video: {
            mandatory: {
                minAspectRatio: 1.40,
                maxAspectRatio: 1.78,
                minFrameRate: 15,
                maxFrameRate: 25,
                minWidth: 1280,
                minHeight: 720
            }
        }
    }, function (stream) {  
      //xxxx  
    }, function (error) {
        console.log(error);
    });

可能有的同学会问到,为何你不直接输出1080p的效果出来?

答案是:我试过了从30到1000的摄像头不等,发现1280720和19201080,真心没有看出区别,生成的文件大小,也是一样的,所以极有可能最高只到720p

在这里还要说明的是FrameRate也是不生效的,AspectRatio是生效的,但设定的最大最小值一定要能取1.333333(4:3)及1.777777777(16:9)这两个值其中一个。因为video元素输出时,会认得这两个宽高比,如果计算得不出这两个比值,那你会看到一片漆黑!

MediaStreamTrack.getSources

H5同时还提供MediaStreamTrack对象,用以跟踪多媒体的输出源。

MediaStreamTrack.getSources方法需要一个回调函数,并向该回调函数传入本机器所有的(音,视频)多媒体源。

接上文的需求,如果我们的机器上有两部(以上)的摄像设备,如何人工选择我们的视(音)频源设备?代码如下:

JavaScript:


var exArray=[];
MediaStreamTrack.getSources(function (sourceInfos) {
            console.log("sourceInfos:%o", sourceInfos);
            for (var i = 0; i != sourceInfos.length; ++i) {
                var sourceInfo = sourceInfos[i];
//这里会遍历audio,video,所以要加以区分
                if (sourceInfo.kind === 'video') {
                    exArray.push(sourceInfo.label);
                }
            }
        });

   navigator.getUserMedia({
            video: {
                mandatory: {
                    minAspectRatio: 1.40,
                    maxAspectRatio: 1.78,
                    minFrameRate: 15,
                    maxFrameRate: 25,
                    minWidth: 1280,
                    minHeight: 720
                },
                optional: [
                    {
                        sourceId: exArray[0]
                    }
                ]
            }
        }, function (stream) {  
          //xxxx  
        }, function (error) {
            console.log(error);
        });

video对象的还提供了一个optional属性来处理多媒体源的选择,MediaStreamTrack.getSources的回调中我们可以得到每个多媒体源的“标志”,我们只要把这个标志输给sourceId即可。

最后要说的

Node-Webkit后MediaStreamTrack.getSources会传入一些无效的视频源信息到回调函数里,需要人工过滤一下,在chrome里没有发现这个问题。

Node-Webkit取摄像头,有时会走到error里,不给权限,目前在chrome里,没有发现

Node-Webkit要走的路还很远!

 

 

通过WebRTC获取摄像头影像

Heero.Luo发表于2年前,已被查看3683次

WebRTCWeb Real-Time Communication,网页实时通信),是一个支持网页浏览器进行实时语音对话或视频对话的API,目前已经是W3C的推荐标准。本文主要阐述如何通过WebRTC的接口获取摄像头影像并截图。

获取摄像头影像

要播放摄像头的影像,首先需要一个video标签:

<video id="video"></video>

获取摄像头影像主要是通过navigator.getUserMedia这个接口,在caniuse.com上查询一下这个接口的支持情况,可以看到目前只有Chrome和Firefox支持得比较好,而且都要加上自家的前缀,移动端几乎全线不可用。

2013091513062560350

为了便于使用这个接口,先做一下兼容性处理:

navigator.getUserMedia = navigator.getUserMedia
    || navigator.webkitGetUserMedia
    || navigator.mozGetUserMedia;

navigator.getUserMedia接口的原型如下;

navigator.getUserMedia(constraints, successCallback, errorCallback);

第一个参数是Object类型,里面包含了需要启用的多媒体设备,例如要启用视频设备(摄像头),就要传入:

{ video: true }

如果要启用视频设备和音频设备(麦克风),就要传入:

{ video: true, audio: true }

另外两个参数分别是启用成功和失败时的回调函数。启用成功的时候,successCallback的第一个参数为视频流对象,可以进一步通过window.URL.createObjectURL接口把视频流转换为对象URL;启用失败的时候,errorCallback的第一个参数是错误对象(Chrome)或错误信息字符串(Firefox)。

navigator.getUserMedia的调用代码如下:

var video = document.getElementById('video');
navigator.getUserMedia({
    video: true
}, function(stream) {
    video.src = window.URL.createObjectURL(stream);
    video.play();
}, function(error) {
    alert(error.name || error);
});

浏览器执行这段代码的时候,会提示用户是否允许使用摄像头,允许之后,网页上就可以实时显示摄像头影像了。如果不允许,就会触发错误事件。

截图

截图的原理是把影像的某一帧传入到canvas中绘制,先创建截图按钮以及canvas元素:

<input type="button" id="capture" value="截图" />
<canvas id="canvas"></canvas>

canvas中绘制图片的接口是drawImage。它有四个参数,分别是绘制坐标(x、y)与图片尺寸(宽、高)。图片尺寸跟视频尺寸一致,但视频尺寸必须在video加载完成后才能获取

video.addEventListener('loadeddata', function() {
    console.log(this.videoWidth);
}, false);

很遗憾,上述代码在Firefox中获取到的值是0。即使在playing事件中,获取到的也还是0。所以,没其他办法的情况下只好通过setTimeout监听:

function bindCapture() {
    var videoWidth = video.videoWidth, videoHeight = video.videoHeight;
    if (videoWidth && videoHeight) {
        var canvas = document.getElementById('canvas');
        canvas.width = videoWidth;
        canvas.height = videoHeight;
        document.getElementById('capture').addEventListener(
            'click',
            function() {
                canvas.getContext('2d').drawImage(
                    video, 0, 0, videoWidth, videoHeight
                );
            },
            false
        );
    } else {
        setTimeout(bindCapture, 200);
    }
}
bindCapture();

至此,截图功能完成。

转载请注明:许得龙博客 » getUserMedia html5 摄像头截图

喜欢 (0)or分享 (0)