前言
在观看视频或者查看监控时,通常会有截屏和录屏的需求,下面来实现一下这两个功能。
一、截图
截图主要是利用 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:captureStream,MediaRecorder
参考代码:
<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 提到了这一点,然而默认就支持无声,暂时没找到问题所在。