web 端 video 截图和录屏功能的实现

web 端 video 截图和录屏功能的实现


前言

在观看视频或者查看监控时,通常会有截屏和录屏的需求,下面来实现一下这两个功能。


一、截图

截图主要是利用 canvas 的 drawImage 和 toDataURL 两个方法。将获取到的 video 标签加入到canvas 中,然后再将 canvas 导出为图片。

  • drawImage

    一旦获得了源图对象,我们就可以使用 drawImage 方法将它渲染到 canvas 里。它能够绘制图像的某些部分(裁剪),以及增加或减少图像的尺寸(缩放);

    • 可以使用下面这些类型中的一种作为图片的源:在这里插入图片描述

    • 语法:drawImage(image, dx, dy, dWidth, dHeight)
      在这里插入图片描述
      在这里插入图片描述

    • 使用 ctx.drawImage(this, 0, 0, this.width, this.height);

  • toDataURL: 返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为 96dpi。

    • 语法:canvas.toDataURL(type, encoderOptions);
      在这里插入图片描述
    • 使用:canvas.toDataURL('image/jpeg')

参考代码:

<video
  ref="videoPlayback"
  id="videoPlayback"
  src="https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4"
  muted
  controls
></video>

<div class="controls">
  <span title="截屏">
    <svg-icon
      iconClass="screenshots"
      @click.native="handleScreenshot"
    />
  </span>

  <canvas ref="canvasRef" v-show="false"></canvas>
</div>
// 截图
handleScreenshot() {
  // 获取video节点
  const video = this.$refs.videoPlayback;
  // 创建canvas节点
  const canvas = this.$refs.canvasRef;

  // 获取 video 宽高
  const width = video.clientWidth;
  canvas.width = width;

  const height = video.clientHeight;
  canvas.height = height;

  const ctx = canvas.getContext('2d');
  // video写入到canvas
  ctx.drawImage(video, 0, 0, width, height);

  // 生成截图地址
  const imgUrl = canvas.toDataURL('image/png');

  //下载截图
  this.downFile(imgUrl, '截图.jpg');
}

//下载截图
downFile(data, fileName) {
  const link = document.createElement('a');

  link.href = data;
  link.download = fileName;
  link.click();

  //释放内存
  window.URL.revokeObjectURL(link.href);
}

二、录屏

录制主要利用 captureStream 和 MediaRecorder 这两个 API。通过捕获 video 的实时视频流,再将视频流生成一个可以录制的对象,最后将录制对象转成一个本地的视频地址。

这两个 API 的使用可以参考 MDN:captureStreamMediaRecorder

参考代码:

<video
  ref="videoPlayback"
  id="videoPlayback"
  src="@/assets/test.mp4"
  muted
  controls
  @loadedmetadata="handleLoadedmeta"
></video>

<div class="controls">
  <span title="录屏">
    <svg-icon
      iconClass="screenshots"
      @click.native="handleRecording"
    />
  </span>
</div>
// 录制
handleRecording() {
  this.recording = !this.recording;
  if (this.recording) {
    this.$message.success('开始录制');
    this.mediaRecorder.start();
  } else {
    this.$message.success('结束录制');
    this.mediaRecorder.stop();
  }
}

// video 元数据加载后触发
handleLoadedmeta() {
  // 获取video节点
  const video = this.$refs.videoPlayback;

  // 存储视频流
  const videoData = [];

  // 生成速率25的MediaRecorder对象
  this.mediaRecorder = new MediaRecorder(video.captureStream(25));

  // 当 MediaRecorder 将媒体数据传递到您的应用程序以供使用时,将触发该事件
  this.mediaRecorder.ondataavailable = (e) => {
    // 添加视频流
    videoData.push(e.data);
  };

  // 录制结束回调
  this.mediaRecorder.onstop = (e) => {
    const blob = new Blob(videoData, { type: 'video/mp4' });

    const videoUrl = window.URL.createObjectURL(blob);

    this.downFile(videoUrl, '视频.mp4');
  };
}

PS: 录制视频时,音量必须打开。

MediaRecorder 对象的配置项 ignoreMutedMedia 提到了这一点,然而默认就支持无声,暂时没找到问题所在。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值