Web前端如何实现录像功能?如何将canvas录制为视频?WebRTC有哪些功能?

申请媒体权限

1.getUserMedia

MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其他轨道类型。

它返回一个 Promise 对象,成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promise会reject回调一个 PermissionDeniedError 或者 NotFoundError 。

通常使用 navigator.mediaDevices 来获取 MediaDevices

 

返回的 promise 对象可能既不会 resolve 也不会 reject,因为用户不是必须选择允许或拒绝。
/**
 * 获取媒体设备
 * @param constraints 定义的约束类型
 * @param success 成功的回调
 * @param error 失败的回调
 */
function getUserMedia(constraints, success, error) {
    if (navigator.mediaDevices.getUserMedia) {
        //最新的标准API
        navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
    } else if (navigator.webkitGetUserMedia) {
        //webkit核心浏览器
        navigator.webkitGetUserMedia(constraints, success, error)
    } else if (navigator.mozGetUserMedia) {
        //firfox浏览器
        navigator.mozGetUserMedia(constraints, success, error);
    } else if (navigator.getUserMedia) {
        //旧版API
        navigator.getUserMedia(constraints, success, error);
    }
}

2.constraints

constraints作为一个MediaStreamConstraints对象,指定了请求的媒体类型和相对应的参数。

constraints的参数是一个包含了video 和 audio两个成员的MediaStreamConstraints 对象,用于说明请求的媒体类型。

//不带任何参数,获取摄像头和麦克风权限
{ audio: true, video: true }

//指定摄像头分辨率
{
  audio: true,
  video: {
    width: { min: 1024, ideal: 1280, max: 1920 },
    height: { min: 776, ideal: 720, max: 1080 }
  }
}

//强制后置摄像头
{ audio: true, video: { facingMode: { exact: "environment" } } }

//优先使用前置摄像头
{ audio: true, video: { facingMode: "user" } }

 

音频常见约束参数:

  • volume 音量约束
  • sampleRate: 采样率
  • sampleSize: 采样大小,采样的位数
  • echoCancellation: 回音消除
  • autoGaincontrol: 增加音量
  • noiseSuppression: 降噪
  • latency : 延迟大小
  • channelCount: 切换声道
  • deviceID: 多个音频输入输出设备的进行切换
  • groupId: 同一个物理设备,是一个分组,但是输入和输出的id不一样

视频常见约束参数

  • width : 宽度约束
  • height :高度约束
  • aspectRatio: 比率
  • frameRate: 帧率
  • facingMode : 摄像头控制,user:前置摄像头,environment :后摄像头,left : 前置左摄像头,right:前置右摄像头
  • resizeMode: 采集的画面需不需要裁剪

媒体流

相关概念:

  • MediaStreamTrack
  • MediaStream
  • source
  • sink
  • MediaTrackConstraints

1.MediaStream

MediaStream 是连接 WebRTC API 和底层物理流的中间层,webRTC将音视频经过Vocie / Video engine进行处理后,再通过MediaStream API给暴露给上层使用。

MediaStream 接口是一个媒体内容的流.。一个流包含几个轨道,比如视频和音频轨道。

Web前端如何实现录像功能?如何将canvas录制为视频?WebRTC有哪些功能?

MediaStream

2.MediaStreamTrack

MediaStreamTrack 接口在 User Agent 中表示一段媒体源,比如音轨或视频。

获取媒体流中的Track:

  • MediaStream.addTrack(),存储传入参数 MediaStreamTrack 的一个副本。如果这个轨道已经被添加到了这个媒体流,什么也不会发生; 如果目标轨道为“完成”状态(也就是已经到尾部了),一个 INVALID_STATE_RAISE 异常会产生。
  • MediaStream.getTracks(),返回流中所有的MediaStreamTrack列表。
  • MediaStream.getAudioTracks(),返回流中 kind 属性为"audio"的MediaStreamTrack列表。顺序是不确定的,不同浏览器间会有不同,每次调用也有可能不同。
  • MediaStream.getTrackById() ,返回给定 ID 的轨道。如果没有参数或者没有指定 ID 的轨道,将返回 null。如果有几个轨道有同一个 ID,将返回第一个。
  • MediaStream.getVideoTracks() ,返回流中 kind 属性为"video"的MediaStreamTrack列表。顺序是不确定的,不同浏览器间会有不同,每次调用也有可能不同。
  • MediaStream.removeTrack() ,移除作为参数传入的 MediaStreamTrack。如果这个轨道不在 MediaStream 对象中什么也不会发生; 如果目标轨道为“完成”状态,一个 INVALID_STATE_RAISE 异常会产生。

相关操作方法:

  • MediaStreamTrack.getConstraints(),获取相关的约束参数
  • MediaStreamTrack.applyConstraints() ,应该一个新的约束参数
  • MediaStreamTrack.getSettings()
  • MediaStreamTrack.getCapabilities()
  • MediaStreamTrack.clone()
  • MediaStreamTrack.stop()

媒体录制

1.MediaRecorder

MediaRecorder 是 MediaStream Recording API 提供的用来进行媒体轻松录制的接口,他需要通过调用 MediaRecorder() 构造方法进行实例化。

MediaStream Recording API 由一个主接口MediaRecorder组成,这个接口负责的所有工作是从MediaStream获取数据并将其传递给你进行处理。数据通过一系列 dataavailable 事件传递,这些数据已经成为你创建 MediaRecorder 时所声明的格式。

//录制完毕,数据可用时触发的事件
MediaRecorder.ondataavailable= dataavailable(e) => {
    const blob = new Blob([e.data], {'type': 'video/mp4'})
    const fd = new FormData();
    fd.append("video", blob);
    ...
}

2.录制过程

  1. 建立一个 MediaStream或者HTMLMediaElement (以 <audio> 或 <video> 元素的形式) 来充当媒体数据的源。
  2. 创建一个 MediaRecorder 对象,指定源以及任何有需求的的选项 (比如容器的 MIME 类型或它轨道所需的比特率).
  3. 给 dataavailable 事件设置MediaRecorder.ondataavailable 事件处理函数; 会在数据可利用时候调用。
  4. 一旦媒体源播放,你已经准备好录制,使用 MediaRecorder.start() (en-US) 开始录制。
  5. dataavailable 事件处理函数正如你所愿的在每次数据准备好时调用; 这个事件有一个值为包含媒体数据的Blob 类型的 data 属性。你可以强制 dataavailable 事件发生,因此会给你传递最新的声音以至于可以让你过滤、保存或者做一些其他的事情。
  6. 当源媒体停止播放时候,录制自动结束。
  7. 你可以随时结束录制通过使用 MediaRecorder.stop().

3.将媒体流显示到video元素

HTMLMediaElement 接口的 srcObject 属性设定或返回一个对象,这个对象提供了一个与HTMLMediaElement关联的媒体源,这个对象通常是 MediaStream。

var mediaStream = HTMLMediaElement.srcObject
HTMLMediaElement.srcObject = mediaStream

//如果不支持上述接口
HTMLMediaElement.src = URL.createObjectURL(mediaStream);

4.将video的画面绘制到canvas

const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

//绘制video当前显示的画面
context.drawImage(videoNode, 0, 0, canvas.width, canvas.height);

5.captureStream

captureStream([frameRate ]) 方法返回的 CanvasCaptureMediaStream 是一个实时视频捕获的画布。

  • frameRate 设置双精准度浮点值为每个帧的捕获速率。如果未设置,则每次画布更改时都会捕获一个新帧。如果设置为0,则会捕获单个帧。
//获取所需要截取媒体流的 canvas element
var canvasElt = document.querySelector('canvas');

//截取到媒体流
var stream = canvasElt.captureStream(25); // 25 FPS
提示Tips
可通过该功能对视频进行处理然后导出