WebRTC源码研究(12)视频约束

1,285 阅读6分钟

WebRTC系列文章

  1. WebRTC源码研究(1)WebRTC架构

  2. WebRTC源码研究(2)webrtc源码目录结构

  3. WebRTC源码研究(3)webrtc运行机制

4.WebRTC源码研究(4)web服务器工作原理和常用协议基础

  1. [WebRTC源码研究(5)Nodejs搭建环境

  2. [WebRTC源码研究(6)创建简单的HTTP服务

  3. [WebRTC源码研究(7)

  4. [WebRTC源码研究(8)

  5. [WebRTC源码研究(9)

  6. [WebRTC源码研究(10)

  7. [WebRTC源码研究(11)获取音视频设备的访问权限

  8. [WebRTC源码研究(12)视频约束

  9. [WebRTC源码研究(13)音频约束

  10. [WebRTC源码研究(14)视频特效

  11. [WebRTC源码研究(15)从视频中获取图

  12. [WebRTC源码研究(16)只采集音频数据

  13. [WebRTC源码研究(17)MediaStreamAPI 获取视频约束

  14. [WebRTC源码研究(18)WebRTC录制视频原理

  15. [WebRTC源码研究(19)WebRTC录采集平面数据

  16. [WebRTC源码研究(20)WebRTC信令服务器原理

  17. WebRTC源码研究(21)WebRTC信令服务器实现

WebRTC源码研究(12)视频约束

1. WebRTC 视频相关api简介

2. WebRTC 视频参数设置

通过WebRTC提供的视频属性设置api ,我们可以精确的控制音频和视频的采集数据,接下来看看,这些属性的含义和使用方法:

属性含义用途
width视频的宽度
height视频的高度宽高有两种比例 :一种是4:3,另一种是16:9;像320 - 240的,640 - 480,这都属于4:3的比例,就是它更方一些。还有一种是16:9,比如是720P的,就是1280 - 720,这就是16:9的比例。它显得更长一些,但是对于我们的手机来说,它就翻过来了,如果我们竖屏拍摄那它高度就是16,比如1280 - 720,宽度就变成了720,这是宽和高,通过这个约束我们就可以控制这个分辨率,你想设置多少,就可以根据自己的情况去调节。
aspectRatio比例一般情况下我们只需要设置宽和高就可以了,这个aspectRatio通过宽高进行一个除,宽除以高,1.333,这个4:3的比例,这里这里我们一般不会设置这个值。
frameRate帧率我们可以通过帧率的多少来控制我们的码流,当然帧率低的话,你会看这个画面不太平滑,帧率高的话画面就很平滑,我们看电影也能看出这个效果,如果每秒钟只有十几帧的话,眼睛比较敏感的人它会看到一卡一卡的现象,但是对于 比如30帧或60帧的,就特别平滑,现在的高清电影一般都是60帧。从另外一方面讲如果你帧率过高了,那你码流就会过大,相当于你1秒钟采集的数据多了。
facingMode镜像模式它是用来控制我们的摄像头翻转的。正常情况下我们 用的是前置摄像头对着自己拍,那你也可以设置成后置摄像头,就是往外拍;还可以打开 前置 的左边的摄像头和前置的右边摄像头,如果你是双 摄像头的话,这都可以做到。在PC上一般是没有前后摄像头的,所以这个设置就会不起作用,它会忽略。而对于手机来说就可以看出它的区别来。facingMode 有四种模式:user: 前置摄像头,environment:后置摄像头 ,left:前置左侧摄像头,right:前置右侧摄像头
resizeMode大小模式它表示采集的画面要不要裁剪,它可以设置为null,就是原封不动的,就是采集什么样他就是什么样。还有一种就是利用裁剪,把他 裁掉 一块去,这个用的不是太多,具体根据业务需求来看了。

3. WebRTC视频约束代码实现

3.1 浏览器中设置视频约束的代码实现

我们先来看看,在浏览器中怎么实现视频约束参数的设置,代码如下:

'use strict'
 
var audioSource = document.querySelector('select#audioSource');
var audioOutput = document.querySelector('select#audioOutput');
var videoSource = document.querySelector('select#videoSource');
// 获取video标签
var videoplay = document.querySelector('video#player');
 
// deviceInfos是设备信息的数组
function gotDevices(deviceInfos){
  // 遍历设备信息数组, 函数里面也有个参数是每一项的deviceinfo, 这样我们就拿到每个设备的信息了
	deviceInfos.forEach(function(deviceinfo){
    // 创建每一项
		var option = document.createElement('option');
		option.text = deviceinfo.label;
		option.value = deviceinfo.deviceId;
	
		if(deviceinfo.kind === 'audioinput'){ // 音频输入
			audioSource.appendChild(option);
		}else if(deviceinfo.kind === 'audiooutput'){ // 音频输出
			audioOutput.appendChild(option);
		}else if(deviceinfo.kind === 'videoinput'){ // 视频输入
			videoSource.appendChild(option);
		}
	})
}
 
// 获取到流做什么, 在gotMediaStream方面里面我们要传人一个参数,也就是流,
// 这个流里面实际上包含了音频轨和视频轨,因为我们通过constraints设置了要采集视频和音频
// 我们直接吧这个流赋值给HTML中赋值的video标签
// 当时拿到这个流了,说明用户已经同意去访问音视频设备了
function gotMediaStream(stream){  
  videoplay.srcObject = stream; // 指定数据源来自stream,这样视频标签采集到这个数据之后就可以将视频和音频播放出来
  // 当我们采集到音视频的数据之后,我们返回一个Promise
  return navigator.mediaDevices.enumerateDevices();
}
 
function handleError(err){
	console.log('getUserMedia error:', err);
}
 
// 判断浏览器是否支持
if(!navigator.mediaDevices ||
  !navigator.mediaDevices.getUserMedia){
  console.log('getUserMedia is not supported!');
}else{
  // 这里是约束参数,正常情况下我们只需要是否使用视频是否使用音频
  // 对于视频就可以按我们刚才所说的做一些限制
  var constraints = { // 表示同时采集视频金和音频
    video : {
      width: 640,	// 宽带
      height: 480,  // 高度
      frameRate:15, // 帧率
      facingMode: 'enviroment', //  设置为后置摄像头
      deviceId : deviceId ? {exact:deviceId} : undefined // 
    }, 
    audio : false 
  }
  navigator.mediaDevices.getUserMedia(constraints)
    .then(gotMediaStream)  // 使用Promise串联的方式,获取流成功了
    .then(gotDevices)
    .catch(handleError);
}

4. WebRTC视频截取图片代码实现

通过WebRTC api我们很容易就能实现从视频流总截取一张图片

主要是利用html5浏览器的一个api : canvas, 主需要一行代码就可以实现获取图片:

button.onclick = function() {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
};

具体完整代码如果下:

test.html内容如下:

<!DOCTYPE html>

<html>
<head>

    <meta charset="utf-8">
    <meta name="mobile-web-app-capable" content="yes">
    <meta id="theme-color" name="theme-color" content="#ffffff">
    <base target="_blank">
    <title>getUserMedia to canvas</title>

</head>

<body>

<div id="container">

    <h1><a href="https://github.com/kongyuluEleven/WebRTCPro" title="WebRTC snap picture kongyulu">WebRTC samples</a> <span>getUserMedia ⇒ canvas</span>
    </h1>

    <video playsinline autoplay></video>
    <button>Take snapshot</button>
    <canvas></canvas>

    <p>Draw a frame from the video onto the canvas element using the <code>drawImage()</code> method.</p>

    <p>The variables <code>canvas</code>, <code>video</code> and <code>stream</code> are in global scope, so you can
        inspect them from the console.</p>

    <a href="https://github.com/kongyuluEleven/WebRTCPro/tree/master/demos/js/webrtc_js_003_snap/canvas"
       title="View source for this page on kongyulu's GitHub" id="viewSource">View source on GitHub</a>

</div>

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="js/test.js" async></script>

</body>
</html>

test.js内容如下:

'use strict';

// Put variables in global scope to make them available to the browser console.
const video = document.querySelector('video');
const canvas = window.canvas = document.querySelector('canvas');
canvas.width = 480;
canvas.height = 360;

const button = document.querySelector('button');
button.onclick = function() {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
};

const constraints = {
  audio: false,
  video: true
};

function handleSuccess(stream) {
  window.stream = stream; // make stream available to browser console
  video.srcObject = stream;
}

function handleError(error) {
  console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
}

navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);

运行结果如下:

运行结果如下