• [译] 用HTML5捕获音频和视频


    原文地址:http://www.html5rocks.com/en/tutorials/getusermedia/intro/

    概述

    有了HTML5,我们就可以在不借助Flash或者Silverlight的情况下完成这项工作了。

    HTML5能够使我们访问设备的硬件,比如GPS,WebGL等等。

    这篇文章,我们就来看看一个新的API——navigator.getUserMedia(),她允许网页应用去访问用户的摄像机和麦克风。

    getUserMedia之路

    第一阶段:HTML Media Capture

    当我们设置<input type="file">标签,并设置此标签的accept属性,她就可以正常的工作了。

    <input type="file" accept="image/*;capture=camera"> <!--拍照-->
    <input type="file" accept="video/*;capture=camcorder"> <!--摄像-->
    <input type="file" accept="audio/*;capture=micophone"> <!--录音-->

    这个"API"的短板之处在于她做实时处理的能力比较弱,比如用canvas来渲染和应用于WebGL.

    HTML Media Capture只允许你去及时的记录视频和拍照。

    第二阶段:device element

    很多人认为HTML Media Capture太有局限性了,所以一个强大的支持所有设备的元素出现了。好不惊奇的,她的名字就是<device>,她就是getUserMedia要处理的对象。

    Opera、WhatWG、Microsoft等都相继实现此元素与API。

    <device>看起来如下:

    <device type="media" onchange="update(this.data)"></device>
    <video autoplay></video>
    <script>
        function update(stream){
            document.querySelector('video').src = stream.url;
        }
    </script>

    不幸的是,没有发布的浏览器支持此标签。

    尽管如此她还是有两个好处的:

    1. 语义化
    2. 高扩展性不仅仅是audio/video.

    第三阶段:WebRTC

    <device>最终还是流产了。

    多亏了WebRTC才让需找合适的API的步伐得意继续。

    现在的getUserMedia()就是参考的WebRTC,因为这是通往一套API的桥梁。她提供了访问用户本地摄像机和麦克风的能力。

    正式开始

    特性检查

    在使用之前我们应该检查一下我们的设备是否支持此方法。

    function hasGetUserMedia(){
        return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
                  navigator.mozGetUserMedia || navigator.msGetUserMedia);
    }
    if(hasGetUserMedia()){
        alert('Good to go!');
    }else{
        alert('Not supported!');
    }

    获得访问设备的权限

    我们应当发送允许我们使用设备的请求。getUserMedia的第一个参数是一个对象,保存的是我们想要请求的设备。例如,如果我们想用摄像机和麦克风,第一个参数就是{video: true, audio: ture};

    <video autoplay></video>
    <script>
        var errorCallback = function(e){
            console.log('Reeeejected!');
        };
        navigator.getUserMedia = navigator.getUserMedia ||
                                 navigator.webkitGetUserMedia ||
                                 navigator.mozGetUserMedia ||
                                 navigator.msGetUserMedia;
        if(!!navigator.getUserMedia){ //good to go
            console.log('Not Suppoted!');
            navigator.getUserMedia({video: true, audio: ture}, function(localMediaStream){
                var video = document.querySelector('video');
                video.src = window.URL.createObjectURL(localMediaStream);
    
                video.onloadedmetadata = function(e){
                    //Do some stuff
                };
            }, errorCallback);
        }
    </script>

    定制media

    getUserMedia的第一个参数也可以被用实现高清等。

    var hdConstraints = {
        video: {
            minWidth: 1280,
            minHeight: 720
        }
    }
    navigator.getUserMedia(hdConstraints, successCallback, errorCallback);
    
    var vgaConstraints = {
        video: {
            mandatory: {
                maxWidth: 640,
                maxHeight: 360
            }
        }
    }
    navigator.getUserMedia(vgaConstraints, successCallback, errorCallback);

    选择媒体源

    在Chrome 30之后,我们可以使用MediaStreamTrack.getSources() API来选择video/audio的源。

    MediaStreamTrack.getSources(function(sourceInfos){
        var audioSource = null;
        var videoSource = null;
    
        for(var i=0; i!=sourceInfos.length; ++i){
            var souceInfo = sourceInfos[i];
            if(sourceInfo.kind === 'audio'){
                console.log(sourceInfo.id, sourceInfo.label || 'microphone');
                audioSource = sourceInfo.id;
            }else if(sourceInfo.kind === 'video'){
                console.log(sourceInfo.id, sourceInfo.label || 'camera');
                videoSource = sourceInfo.id;
            }else{
                console.log('Some other kind of source: ', sourceInfo);
            }
        }
        sourceSelected(audioSource, videoSource);
    });
    function sourceSelected(audioSource, videoSource){
        var constraints = {
            audio: {
                optional: [{sourceId: audioSource}]
            },
            video: {
                optional: [{sourceId: videoSource}]
            }
        };
        navigator.getUserMedia(constraints, successCallback, errorCallback);
    }

    安全

    当我们调用getUserMedia()时,浏览器会弹出一个对话框来让用户决定接下怎么做,不幸的是,当我们的应用使用的是https时,这将会被拒绝。

    后备方法

    对用不支持getUserMedia的用户来说,我们可以指定一个存在的video或者抛出错误提示。

    function fallback(e){
        video.src = 'fallbackvideo.webm';
    }
    function success(stream){
        video.src = window.URL.createObjectURL(stream);
    }
    
    if(!navigator.getUserMedia){
        fallback();
    }else{
        navigator.getUserMedia({video: true}, success, fallback);
    }

    屏幕截图

    我们可以使用<canvas>捕获<video>的某一帧,这样就可以实现截图了。

    <video autoplay></video>
    <img src="">
    <canvas style="display:none;"></canvas>
    <script>
    var video = document.querySelector('video');
    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    var localMediaStream = null;
    
    function snapshot(){
        if(localMediaStream){
            ctx.drawImage(video, 0, 0);
            document.querySelector('img').src = canvas.toDataURL('image/webp');
        }
    }
    
    video.addEventListener('click', snapshot, false);
    
    navigator.getUserMedia({video: true}, function(stream){
        video.src = window.URL.createObjectURL(stream);
        localMediaStream = stream;
    }, errorCallback);
    </script> 

    应用样式

    使用css过滤器

    <style>
    video {
      width: 307px;
      height: 250px;
      background: rgba(255,255,255,0.5);
      border: 1px solid #ccc;
    }
    .grayscale {
      +filter: grayscale(1);
    }
    .sepia {
      +filter: sepia(1);
    }
    .blur {
      +filter: blur(3px);
    }
    ...
    </style>
    
    <video autoplay></video>
    
    <script>
    var idx = 0;
    var filters = ['grayscale', 'sepia', 'blur', 'brightness',
                   'contrast', 'hue-rotate', 'hue-rotate2',
                   'hue-rotate3', 'saturate', 'invert', ''];
    
    function changeFilter(e) {
      var el = e.target;
      el.className = '';
      var effect = filters[idx++ % filters.length]; // loop through filters.
      if (effect) {
        el.classList.add(effect);
      }
    }
    
    document.querySelector('video').addEventListener(
        'click', changeFilter, false);
    </script>

    WebGL纹理

    有兴趣的可以参考http://learningthreejs.com/blog/2012/02/07/live-video-in-webgl/ 这篇文章。

    使用Audio API

    window.AudioContext = window.AudioContext ||
                          window.webkitAudioContext;
    
    var context = new AudioContext();
    
    navigator.getUserMedia({audio: true}, function(stream) {
      var microphone = context.createMediaStreamSource(stream);
      var filter = context.createBiquadFilter();
    
      // microphone -> filter -> destination.
      microphone.connect(filter);
      filter.connect(context.destination);
    }, errorCallback);
  • 相关阅读:
    Python- 索引 B+数 比如书的目录
    Python-视图 触发器 事务 存储过程
    Python-mysql 权限 pymysql 注入共计
    Shell之Sed常用用法
    python 字符编码讲解
    python enumerate枚举用法总结
    Python第三周 数据类型:集合set、文件的读写、追加操作。
    第二周Python笔记 数据类型 列表 字典
    Python第二周 str的方法
    第二周Python笔记之 变量的三元运算
  • 原文地址:https://www.cnblogs.com/JChen666/p/3665675.html
Copyright © 2020-2023  润新知