前端工程记录:用RecordRTC实现对<video>标签的录像功能

news/2024/7/10 3:02:10 标签: 前端, vue

项目需求:后端给一个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流。

解决方案是为recorder.startRecording加一个定时器,将上面的startRecord函数改成如下内容:

startRecord() {
    setTimeout(() => {
        this.recordRTC.startRecording();
        this.isRecording = true;
    }, 500);        
}


http://www.niftyadmin.cn/n/5330366.html

相关文章

虚拟机 以及 Centos 7的 安装全过程

目录 安装VMwere Workstion 虚拟机的操作过程 CentOS 7 安装过程 install CentOS 7 安装操作系统 安装VMwere Workstion 虚拟机的操作过程 更改安装位置 到下面图片中的这一个步骤&#xff0c;可以点击许可证&#xff0c;输入密钥就可以使用了&#xff0c; 密钥可以去某度或…

mac 系统中vscode 返回上一次文件编辑位置快捷键

mac 系统中vscode 返回上一次文件编辑位置快捷键 以下内容由chatgpt中文网 动态生成,助力开发找我 方式1&#xff1a; Command -&#xff1a;返回到上一个编辑位置。 方式2 control -&#xff1a;返回到上一个编辑位置。

opencv_角点检测

文章内容 一个opencv检测角点的程序 运行效果 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream>using namespace cv; using namespace std;void detectCorners(M…

基于域账户及西门子simatic logon的集中权限管理的实现(二)

上次我们完成了域环境及simatic logon服务器的搭建&#xff0c;今天我们将在wincc及HMI上进行组态&#xff0c;实现用域账户进行登录。 3.WINCC用户管理组态引文&#xff1a;博途工控人平时在哪里技术交流博途工控人社群 3.1 首先将要安装WINCC的服务器加入域。 3.2 在wincc…

微服务治理:微服务安全详解

微服务安全旨在保护微服务架构中每一个独立的服务。与传统单体应用程序不同&#xff0c;它们在单点应用安全措施&#xff0c;微服务由于其独立性&#xff0c;需要分布式安全方法。 为何关注微服务安全&#xff1f; 攻击面扩大: 更多服务暴露在外&#xff0c;意味着攻击者拥有…

Kafka系列(四)

本文接kafka三&#xff0c;代码实践kafkaStream的应用&#xff0c;用来完成流式计算。 kafkastream 关于流式计算也就是实时处理&#xff0c;无时间概念边界的处理一些数据。想要更有性价比地和java程序进行结合&#xff0c;因此了解了kafka。但是本人阅读了kafka地官网&#…

VitePress-01-从零开始的项目创建(npm版)

说明 本文介绍一下 VitePress的项目创建的步骤。 主要用到的命令工具是 npm。 本文的操作步骤是从无到有的创建一个完整的基本的【VitePress】项目。 环境准备 根据官方文档的介绍&#xff0c;截止本文发稿时&#xff0c;需要使用node.js 18 的版本。 可以使用node -v 的命令查…

【51单片机系列】单片机与PC进行串行通信

一、单片机与PC机串行通信的设计 工业现场的测控系统中&#xff0c;常使用单片机进行监测点的数据采集&#xff0c;然后单片机通过串口与PC通信&#xff0c;把采集的数据串行传送到PC机上&#xff0c;再在PC机上进行数据处理。 PC机配置的都是RS-232标准串口&#xff0c;为D型…