video视频的录制
准备h5可以播放的test.mp4 , mp4需要是h264录制的
实现步骤
- onloadedmetadata 在video加载完视频源之后拦截
- 使用video.captureStream 对视频流进行抓取 , 并生成MediaRecorder对象 .
- mediaRecorder对象使用 ondataavailable将二进制数据写入videoData
- 根据videoData生成blob对象
- 根据blob对象生成录制的视频 videoUrl ,并进行播放
ps: RecIntervalListener 类 只是为了增加渲染效果非核心代码
完整GIF 示例代码
<html>
<head>
<title>video录屏</title>
<style type="text/css">
.block-area {
display: inline-block;
width: 800px;
height: 600px;
margin-left: 100px;
overflow-y: auto;
border: 1px solid #ccc;
}
.block-area video {
margin-left: 100px;
width: 600;
height: 300;
}
blockquote {
margin-left: 0;
margin-right: 0;
padding: 0 15px;
color: #424242;
border-left: 4px solid #ddd;
}
.captureHoverArea {
position: absolute;
z-index: 100;
left: 600px;
top: 145px;
color: red;
display: none;
}
.captureHoverArea button {
background-color: red;
border-color: red;
border-radius: 50%;
width: 15px;
height: 15px;
}
</style>
</head>
<body>
<blockquote>
<h3>ps:请使用server模式测试</h3>
</blockquote>
<div class="captureHoverArea">
<label id="blinkRec"><button></button><b> REC </b></label>
<label id="recorderTime"></label>
</div>
<div class="block-area">
<h4>原始视频:
<button id="btnStart" onclick="startCapture()">Start</button>
<button id="btnStop" disabled='disabled' onclick="endCapture()">Stop</button>
</h4>
<video id="mainVideo" playsinline="" webkit-playsinline="1" controls="1" onloadedmetadata="initMediaRecorder()">
<source src="test.mp4" type="video/mp4">
</video>
</div>
<div class="block-area">
<h4>
录制结果:
<span id="captureResult" style="display:none">
<span id="captureTime"></span>
<button id="btnResult" onclick="showCapture()">ShowCapture</button>
</span>
</h4>
<video id="displayVideo" autoplay="autoplay" playsinline="" webkit-playsinline="1" controls="1"></video>
</div>
</body>
<script>
var mainVideo = document.getElementById("mainVideo");
var displayVideo = document.getElementById("displayVideo");
var videoData = [];
var recListener;
var mediaRecorder;
/**
* 录屏记录器
* 样式效果代码
*/
class RecIntervalListener {
constructor() {
this.start = new Date();
this.end = null;
this.btnStart = document.getElementById("btnStart");
this.btnStop = document.getElementById("btnStop");
this.recorderTime = document.getElementById("recorderTime");
this.blinkRec = document.getElementById("blinkRec");
this.captureTime = document.getElementById("captureTime");
this.repeat = setInterval(() => {
this.recorderTime.innerText = parseInt(new Date() - this.start) / 1000 + "s"
});
this.repeatBlink = setInterval(() => {
this.toggleBlink()
}, 400);
this.toggleRecArea(true)
this.toggleDisableButton(true);
}
/*
* 停止
*/
stop() {
this.end = new Date();
clearInterval(this.repeat);
clearInterval(this.repeatBlink);
this.toggleRecArea(false)
this.toggleDisableButton(false);
this.captureTime.innerText = `Capture Video:${recListener.getLastTime()} s`;
}
/*
* 获取最后时间
*/
getLastTime() {
return parseInt(this.end - this.start) / 1000
}
/*
* 控制录屏显示隐藏
*/
toggleRecArea(isShow) {
let displayHoverArea = isShow ? 'inline' : 'none'
let displayCaptureResult = isShow ? 'none' : 'inline'
document.querySelector('.captureHoverArea').style.display = displayHoverArea;
document.getElementById("captureResult").style.display = displayCaptureResult;
}
/*
* 控制录屏标识闪烁
*/
toggleBlink() {
this.blinkShow = !this.blinkShow;
let displayAttr = this.blinkShow ? 'hidden' : ''
this.blinkRec.style.visibility = displayAttr;
}
/*
* 控制按钮是否可用
*/
toggleDisableButton(isStart) {
if (isStart) {
this.btnStart.setAttribute('disabled', 'disabled');
this.btnStop.removeAttribute('disabled');
} else {
this.btnStart.removeAttribute('disabled');
this.btnStop.setAttribute('disabled', 'disabled');
}
}
}
/*
* 拦截二进制流数据
*/
var initMediaRecorder = function () {
// Record with 25 fps
mediaRecorder = new MediaRecorder(mainVideo.captureStream(25));
mediaRecorder.ondataavailable = function (e) {
videoData.push(e.data);
};
}
/*
* 录制
*/
function startCapture() {
videoData = [];
mainVideo.play();
mediaRecorder.start();
recListener = new RecIntervalListener();
};
/*
* 停止
*/
function endCapture() {
mediaRecorder.stop();
mainVideo.pause();
recListener.stop();
};
/*
* 播放录制
*/
function showCapture() {
return new Promise(resolve => {
setTimeout(() => {
// Wrapping this in setTimeout, so its processed in the next RAF
let blob = new Blob(videoData, {
'type': 'video/mp4'
});
let videoUrl = window.URL.createObjectURL(blob);
displayVideo.src = videoUrl;
resolve();
}, 0);
});
};
</script>
</html>