WebRTC-使用浏览器拍照

使用webRTC进行拍照

本节主要讲解图中红色框内容。

非编码帧 vs 编码帧

从摄像头里采集的帧或通过解码器之后的帧都是非编码帧,一般格式是YUV格式或者RGB格式。

通过编码器(H264/H265\ VP8/VP9)压缩后的帧称为编码帧。

从播放器里获取的视频帧一定是非编码帧,即拍照的过程其实是从连续播放的一幅幅画面中抽取出正在显示的那张画面。

如果获取视频流

HTML代码:

<html>
  <head>
    <title>WebRTC Taking a Photo</title>
  </head>

  <body>
    <video autoplay playsinline id="player"></video>
    <p></p>
    <canvas id="photo"></canvas>
    <button id="TakePhoto">Take</button>
    <button id="SavePhoto">Save</button>
  </body>
  <script src="./js/taking_a_photo.js"></script>
</html>

JavaScript代码:

'use strict'

// 获取 HTML 页面中的 video 标签  
var videoplay = document.querySelector('video#player');

// 播放视频流
function gotMediaStream(stream){
        videoplay.srcObject = stream;
}

function handleError(err){
        console.log('getUserMedia error:', err);
}

// 对采集的数据做一些限制
var constraints = {
                        video : {
                                width: 1280,
                                height: 720,
                                frameRate:15,
                        },
                        audio : false
                   }

// 采集音视频数据流
navigator.mediaDevices.getUserMedia(constraints)
                        .then(gotMediaStream)
                        .catch(handleError);

脚本代码中调用了getUserMedia方法,该方法会打开摄像头,并通过它采集音视频流,然后将采集到的视频流赋值给HTML中定义的Video标签的srcObject字段,video标签就可以从摄像头不断地获取视频帧,将它播放出来。

如何拍照

浏览器提供了Canvas,可以想象成一块画布,既可以在这块画布上画上点、线或者各种图形,也可以将一副画直接绘制到上面。

当点击Take按钮时,执行该函数拍照并赋值给canvas显示,在JavaScript中增加以下代码:

// 获取图片
document.querySelector("button#TakePhoto").onclick = function() {
  // 获得HTML中的canvas标签,设置其宽高
  var photo = document.querySelector("canvas#Photo");
  photo.width = 640;
  photo.height = 480;

  // 利用drawImage方法抓取视频流中当前正在显示的图片
  photo.getContext("2d").drawImage(videoplay, 0, 0, photo.width, photo.height);
};

其中关键的是drawImage方法,其方法格式如下:

void ctx.drawImage(image, x, y, width, height);
  • image:可以是一幅图片或者HTML的VideoElement
  • x, y: 图片起点的x,y坐标
  • width:图片的宽度
  • height: 图片的高度

如何保存图片

在JavaScript中增加以下代码:


// 保存图片
function downLoad(url) {
  var oA = document.createElement("a");

  // 设置下载的文件名,默认是“下载”
  oA.download = "photo";
  oA.href = url;
  document.body.appendChild(oA);
  oA.click();

  // 下载之后把创建的元素删除
  oA.remove();
}

document.querySelector("button#SavePhoto").onclick = function() {
  var canvas = document.querySelector("canvas");
  downLoad(canvas.toDataURL("image/jpeg"));
};

当用户点击保存按钮时,会调用一个匿名函数,该函数逻辑如下:

  • 通过Canvas的toDataURL方法获得图片的URL地址
  • 将该URL地址当做参数传给downLoad函数
  • 在downLoad函数中,先创建一个<a>标签,然后下载该标签并且删除该标签

如何实现滤镜

在浏览器中对于图片的滤镜处理是通过CSS来控制的。在HTML中增加CSS代码如下:

<style>
      /* 定义四种滤镜 */
      .none {
        -webkit-filter: none;
        filter: none;
      }
      /* 模糊度 */
      .blur {
        -webkit-filter: blur(3px);
        filter: blur(3px);
      }
      /* 灰度 */
      .grayscale {
        -webkit-filter: grayscale(1);
        filter: grayscale(1);
      }

      /* 反转 */
      .invert {
        -webkit-filter: invert(1);
        filter: invert(1);
      }

      /* 深褐色 */
      .sepia {
        -webkit-filter: sepia(1);
        filter: sepia(1);
      }
    </style>

然后再JavaScript中TakePhoto按钮的点击函数中添加如下代码;

// 获取下拉菜单select标签
  var filtersSelect = document.querySelector("select#filter");
  // 设置视频滤镜
  photo.className = filtersSelect.value;

这样就实现了利用浏览器拍摄照片并且下载的功能。

注:本文是《从0打造音视频直播系统》的读书笔记,配套代码地址GitHub。本文仅限个人学习,请勿用作商业用途,谢谢。

强烈建议购买李超老师的课,扫描下方二维码还有优惠:

Note: Cover Picture