项目需求:后端给一个mp4视频的链接,在前端播放,同时支持用户的录制视频操作。
一、技术选择
1. 毫无关系的getUserMedia
官方介绍文档:MediaDevices.getUserMedia() - Web API 接口参考 | MDN
在网上搜索“前端如何录像”,AI非常贴心地提供了这个函数,代码也写得有模有样,仔细一看发现和目的毫不相干,浏览器提供的 navigator.mediaDecives.getUserMedia() 是用来调用摄像头和麦克风的,与其相仿的 navigator.mediaDecives.getDisplayMedia() 则能够实现共享窗口和屏幕。
起初我想利用 navigator.mediaDecives.getDisplayMedia 对页面进行录制,但是在浏览器中,被共享的内容可以是浏览器的其他页面、正在使用的其他窗口、整个屏幕,唯独没有调用此函数的界面,遂放弃此想法。
2. rrweb
官网使用文档:https://github.com/rrweb-io/rrweb/blob/master/guide.zh_CN.md
这个库也是在网上看到的,用的人很多,然而不适用本工作场景,rrweb关注整个页面以及用户在页面上的各种操作,会记录页面DOM节点的变动,适合录制网课这类的场景,用来处理单独的video元素,有种杀鸡用牛刀的感觉。
3. recordrtc - canvas用法
github地址:https://github.com/muaz-khan/RecordRTC
recordrtc是基于webRTC的实现录屏的库,支持audio, video, canvas, gif四种类型。
具体使用流程如下(以普通html文件为例):
(1)引入
<script src="https://cdn.WebRTC-Experiment.com/RecordRTC.js"></script>
<script src="https://cdn.webrtc-experiment.com/screenshot.js"></script>
(2)创建对象
let element = document.getElementById('canvas');
let recordRTC = RecordRTC(element, {
type: 'canvas'
});
(3)开始录制和结束录制
function start() {
recordRTC.startRecording();
}
function stop() {
recordRTC.stopRecording(function(videoURL) {
var a = document.createElement('a');
a.href = videoURL;
a.download = 'a.mp4';
a.click();
});
}
在结束录制函数stopRecording中,videoURL返回的是一个blob url,将其赋值给video元素的src,可以直接播放出录制的视频。本项目中需要下载录制视频,因此将videoURL赋值给新建的a标签,从而实现对录制视频的下载
(4)将video内容绘制到canvas上
let ctx = canvas.getContext('2d');
let video = document.getElementById('video');
video.addEventListener('play', function() {
setInterval(() => {
ctx.drawImage(content, 0, 0, 500, 300);
}, 100);
}, false);
在type="canvas"的配置下,recordrtc会对canvas进行录制,而canvas不能直接包含video标签,所以为了录制视频,监听视频的播放操作,在play状态下将画面逐帧绘制到canvas上,我采用了setInterval,用requestAnimationFrame是同样的效果。
(5)html内容
<canvas id="elementToShare" width="500" height="300">
</canvas>
<video width="500" height="300" controls id="video" src="./test.mp4">
</video>
<div>
<button onclick="start()">开始录制</button>
<button onclick="stop()">结束录制</button>
</div>
以上代码能成功实现对video的录制,而且完全没有后期出现的录制视频卡顿的问题。但是,没声音。canvas只能录制画面,而我的需求是录制带声音的视频。
二、实际使用
1. 技术方案:recordrtc
在recordrtc的官方案例中,给出的是这样一个例子
let stream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
let recorder = RecordRTC(stream, {
type: 'video'
});
其中,RecordRTC接收的第一个参数是来自媒体设备传来的视频流。
我起初尝试仿照canvas,直接将video节点传入,然而不行,在type为video的情况下,RecordRTC接收的第一个参数必须是流。
在网上搜了半天,找到了一个函数captureStream,在浏览器上的兼容性一般,但是能够实现将获取video流的效果。
2. 代码
<template>
<div v-if="isShow" :style="domStyle" >
<div class="control-box>
<Button v-show="!isRecording" @click="startRecord">录制</Button>
<Button v-show="isRecording" @click="stopRecord">停止录制</Button>
</div>
<div class="video-box">
<video controls ref="video">
</video>
</div>
<a ref="link"></a>
</div>
</template>
<script>
import RecordRTC from 'recordrtc';
export default {
data() {
return {
isRecording: false,
recordRTC: null,
};
},
created() {
// ...
},
mounted() {
// ...
this.initRecordRTC();
},
methods: {
// 初始化recordRTC
initRecordRTC() {
this.recordRTC = null;
let stream = null;
const video = this.$refs.video;
if (video.captureStream) { // 适用于chrome内核
stream = video.captureStream();
} else if (video.mozCaptureStream) { // 适用于firefox内核
stream = video.mozCaptureStream();
} else {
this.$Message.warning('不支持captureStream,无法录制!');
return;
}
this.recordRTC = RecordRTC(stream, {
type: 'video'
});
},
// 录制
startRecord() {
this.recordRTC.startRecording();
this.isRecording = true;
},
// 停止录制
stopRecord() {
this.recordRTC.stopRecording((videoURL) => {
let a = this.$refs.link;
a.href = videoURL;
a.download = 'test.mp4';
a.click();
});
this.isRecording = false;
},
}
};
</script>
<style scoped>
.video-box {
padding: 10px;
}
</style>
3. 细节问题
由于项目中的播放器支持用户改变文件路径,出现一个问题是,在修改video的src后,如果在播放视频前点击录制,项目会报一个错误,原因是在startRecording之前获取不到stream流。文章来源:https://www.toymoban.com/news/detail-813358.html
解决方案是为recorder.startRecording加一个定时器,将上面的startRecord函数改成如下内容:文章来源地址https://www.toymoban.com/news/detail-813358.html
startRecord() {
setTimeout(() => {
this.recordRTC.startRecording();
this.isRecording = true;
}, 500);
}
到了这里,关于前端工程记录:用RecordRTC实现对<video>标签的录像功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!