使用 mediaDevices.getUserMedia 在浏览器录制视频

使用 mediaDevices.getUserMedia 录制视频

MediaDevices 接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。它可以使你取得任何硬件资源的媒体数据。

使用 mediaDevices.getUserMedia 函数可以调用设备相机和麦克风等设备用于录制视频或视频通话, 具体可以查看 MDN 文档

语法使用说明

mediaDevicesnavigator 下的一个对象, 使用 navigator.mediaDevices.getUserMedia(...) 调用,
该函数接收一个 MediaStreamConstraints 类型参数, 用于指定请求的媒体类型, 返回一个 MediaStream 类型的 Promise 对象

// MediaStreamConstraints 类型定义
interface MediaStreamConstraints {
  audio?: boolean | MediaTrackConstraints;
  video?: boolean | MediaTrackConstraints;
}

audiovideo 属性一般接收一个布尔值, 用于指定是否需要录制音频和视频, true 代表需要录制, 默认为 false; 也可以使用一个 MediaTrackConstraints 类型对象, 用于阅读每个功能的精度和范围等, 以及指定使用前置后置摄像头, 这里不详细说明;

注意: audiovideo 属性必须有一个为 true 才能正确调用 getUserMedia 函数

const mediaStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true,
});

获取视频示例

页面布局

首先放置一个 video 元素用于呈现录制的视频内容, 放置一个 button 用于开始屏幕录制

界面代码

<style>
    body {
      padding: 0;
      margin: 0;
      display: flex;
      flex-direction: column;
      height: 100vh;
    }
    video {
      flex: 1;
      border: 1px solid #000;
      margin: 10px;
      border-radius: 4px;
    }
    div {
      height: 40px;
      margin: 10px;
      display: flex;
    }
    button {
      flex: 1;
      margin: 0 10px;
    }
  </style>

<body>
  <video></video>
  <div>
    <button class="start">开始</button>
    <button class="stop">结束</button>
  </div>
</body>

页面效果
上面为 video 元素,作为视频预览;两个操作按钮控制开始录制和结束录制
在这里插入图片描述

获取元素,添加按钮事件

接下来获取 video 以及 start 和 stop 等元素, 并添加相应的事件函数

示例代码

const videoEl = document.querySelector('video');
const startBtnEl = document.querySelector('.start');
const stopBtnEl = document.querySelector('.stop');

/**
 * 在外部声明 mediaScream 对象
 * 因为再 start 中获取后在 stop 函数中需要用到该对象去关闭播放轨道
 */
let mediaScream;

const start = () => {
  ...
}

const stop = () => {
  ...
}

startBtnEl.onclick = start;
stopBtnEl.onclick = stop;

获取媒体设备实现预览效果

在 start 中获取摄像头和麦克风使用并输出到 video 元素中, 再 stop 中关闭播放轨道以及停止 video 播放

逻辑代码

const start = async () => {
  // 获取 mediaScream 对象, 指定同时获取音频和视频
  mediaScream = await navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true,
  });

  // 将获取到的源赋予给 videoEl
  videoEl.srcObject = mediaScream;
  videoEl.play(); // 开始播放
}

const stop = () => {
  /**
   * mediaScream.getTracks 用于获取改源中的 MediaStreamTrack 列表
   * MediaStreamTrack 一般为音轨和视频
   * 获取后遍历并关闭该轨道
   */
  mediaScream.getTracks().forEach(item => item.stop());
  videoEl.pause(); // 停止播放
  videoEl.srcObject = null;
}

界面效果
现在点击开始按钮,video 元素将会呈现摄像头记录的东西, 点击停止按钮会停止摄像头工作并返回原始状态

在这里插入图片描述

记录视频数据并下载

我们可以利用 MediaRecorder 对象,将 mediaStream 数据装换位 MediaRecorder 对象;
再 MediaRecorder 对象加载完成时将加载的数据存到一个 chunks 中;
最后再录制结束时,关闭MediaRecorder 对象并将 chunks 数据转换成 blob 数据,然后下载;

MediaRecorder 可以参考 MDN文档

/** @type MediaStream */
let mediaScream;
/** @type MediaRecorder */
let mediaRecorder;
let chunks = [];

const start = async () => {
  // 获取 mediaScream 对象, 指定同时获取音频和视频
  mediaScream = await navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true,
  });

  // 将获取到的源赋予给 videoEl
  videoEl.srcObject = mediaScream;
  videoEl.play();

  // 创建一个 mediaRecorder 对象
  mediaRecorder = new MediaRecorder(mediaScream, {
    mimeType : 'video/webm',
  });
  // 在 dataavailable 时间中去记录视频数据到 chunks
  mediaRecorder.ondataavailable = (event) => {
    chunks.push(event.data);
  }
  mediaRecorder.start();
}

// 用于将记录的 chunks 转换并下载
const download = () => {
  const blob = new Blob(chunks);
  const aEl = document.createElement('a');
  aEl.href = URL.createObjectURL(blob);
  aEl.download = 'video.webm';
  aEl.style.display = 'none';
  document.body.appendChild(aEl);
  aEl.click();
  chunks = [];
}

const stop = () => {
  // 在 mediaRecorder 的 stop 时间中执行下载任务
  mediaRecorder.onstop = download;
  mediaRecorder.stop(); // 停止记录
  /**
   * mediaScream.getTracks 用于获取改源中的 MediaStreamTrack 列表
   * MediaStreamTrack 一般为音轨和视频
   * 获取后遍历并关闭该轨道
   */
  mediaScream.getTracks().forEach(item => item.stop());
  videoEl.pause();
  videoEl.srcObject = null;
}

界面效果
视频开始录制后,当点击结束时,便会跳出下载保存窗口
在这里插入图片描述

将录制程序制作成一个工具类

可以将上述功能封装成一个工具类 RecordVideo

RecordVideo 代码

class RecordVideo {
  constructor(videoEl) {
    this.videoEl = videoEl;
    this.mediaScream = null;
    this.mediaRecorder = null;
    this.chunks = [];
  }

  download() {
    const aEl = document.createElement('a');
    aEl.href = URL.createObjectURL(new Blob(this.chunks));
    aEl.download = 'video.webm';
    aEl.style.display = 'none';
    document.body.appendChild(aEl);
    aEl.click();
    this.chunks = [];
  }

  async start() {
    this.mediaScream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true,
    });
    this.videoEl.srcObject = this.mediaScream;
    this.videoEl.play();

    this.mediaRecorder = new MediaRecorder(this.mediaScream, {
      mimeType : 'video/webm',
    });
    this.mediaRecorder.ondataavailable = (event) => {
      this.chunks.push(event.data);
    }
    this.mediaRecorder.start();
  }

  stop() {
    this.mediaRecorder.onstop = () => this.download();
    this.mediaScream.getTracks().forEach(item => item.stop());
    this.videoEl.pause();
    this.videoEl.srcObject = null;
  }
}

使用 RecordVideo 类实现

上述的案例就可以简单的使用 RecordVideo 类来实现了

const videoEl = document.querySelector('video');
const startBtnEl = document.querySelector('.start');
const stopBtnEl = document.querySelector('.stop');

const recordVideo = new RecordVideo(document.querySelector('video'));
startBtnEl.onclick = () => recordVideo.start();
stopBtnEl.onclick = () => recordVideo.stop();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值