前言
平常在用视频app,特别是一些摄像头监控软件的时候,经常会对直播、回放的视频进行抓拍录屏的操作。今天就来实现一下这两个功能
思路
- 截图: 主要是利用canvas的
drawImage 和toDataURL 两个方法。将获取到的video标签加入到canvas中,然后再将canvas导出为图片。
drawImage: 可以在画布上绘制图像、画布或视频;也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸;
toDataURL: 返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。
- 录制 : 主要利用
captureStream 和MediaRecorder 。通过捕获video的实时视频流,再将视频流生成一个可以录制的对象,最后将录制对象转成一个本地的视频地址。
captureStream:可以截取到截取到媒体流。captureStream(frameRate) frameRate:设置双精准度浮点值为每个帧的捕获速率。 MDN对captureStream描述>>。
MediaRecorder:可以创建一个针对指定视频流进行录制的对象。MDN对MediaRecorder描述>>。
代码
<template>
<div>
<video
crossOrigin="anonymous"
src="https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4"
width="550"
autoplay
controls
@loadedmetadata="onloadedmetadata"
></video>
<div class="controls">
<el-button type="primary" @click="handleScreenshot">截图</el-button>
<el-button
type="primary"
@click="handleRecording"
:icon="recording ? 'el-icon-loading' : ''"
>{{ recording ? "录制中" : "录制" }}</el-button
>
<el-button type="primary" @click="reset">重置</el-button>
</div>
<div class="preview">
<div class="preview-box">
<img v-if="imgUrl" width="550" :src="imgUrl" alt="" />
<span v-else>截图预览</span>
</div>
<div class="preview-box">
<video
v-if="videoUrl"
:src="videoUrl"
width="550"
autoplay
controls
></video>
<span v-else>录制预览</span>
</div>
</div>
</div>
</template>
<script>
var mediaRecorder
export default {
data() {
return {
imgUrl: "",
recording: false,
videoData: [],
videoUrl: "",
};
},
methods: {
reset() {
this.imgUrl = this.videoUrl = ""
this.recording = false
},
handleScreenshot() {
let video = document.getElementsByTagName("video")[0]
let canvas = document.createElement("canvas")
let w = window.innerWidth
let h = (window.innerWidth / 16) * 9
canvas.width = w
canvas.height = h
const ctx = canvas.getContext("2d")
ctx.drawImage(video, 0, 0, w, h)
this.imgUrl = canvas.toDataURL("image/png")
},
handleRecording() {
this.recording = !this.recording
if (this.recording) {
this.$message.success("开始录制")
mediaRecorder.start()
} else {
this.$message.success("结束录制")
mediaRecorder.stop()
this.showCapture()
}
},
onloadedmetadata() {
let video = document.getElementsByTagName("video")[0]
mediaRecorder = new MediaRecorder(video.captureStream(25))
const _this = this
mediaRecorder.ondataavailable = function (e) {
_this.videoData.push(e.data)
}
},
showCapture() {
return new Promise((resolve) => {
setTimeout(() => {
let blob = new Blob(this.videoData, {
type: "video/mp4",
});
this.videoUrl = window.URL.createObjectURL(blob)
resolve()
})
})
}
}
}
</script>
<style lang='scss' scoped>
.controls {
margin: 20px 0;
}
.preview {
height: 310px;
display: flex;
justify-content: center;
.preview-box {
height: 100%;
width: 550px;
border: 1px solid #000;
margin-right: 5px;
}
}
</style>
效果
在线demo地址: 前往预览.
|