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

使用 mediaDevices.getUserMedia 录制视频

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

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

语法使用说明

mediaDevicesnavigator 下的一个对象, 使用 navigator.mediaDevices.getUserMedia(...) 调用,

该函数接收一个 MediaStreamConstraints 类型参数, 用于指定请求的媒体类型, 返回一个 MediaStream 类型的 Promise 对象

ts 复制代码
// MediaStreamConstraints 类型定义
interface MediaStreamConstraints {
  audio?: boolean | MediaTrackConstraints;
  video?: boolean | MediaTrackConstraints;
}

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

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

js 复制代码
const mediaStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true,
});

获取视频示例

页面布局

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

界面代码

html 复制代码
<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 等元素, 并添加相应的事件函数

示例代码

js 复制代码
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 播放

逻辑代码

js 复制代码
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文档

js 复制代码
/** @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 代码

js 复制代码
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 类来实现了

js 复制代码
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();
相关推荐
LNTON羚通14 分钟前
摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现
算法·目标检测·音视频·监控·视频监控
y先森18 分钟前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy18 分钟前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu108301891121 分钟前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿1 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡2 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js