屏幕录制组件(vue) recordrtc

更新vue录制组件
写在开始:部署后提示Cannot read property 'getDisplayMedia' of undefined,解决方法: 掘金 ,我的解决方式是使用ssl证书

demo预览:https://rec.poshir.top web录屏
来源:简书

如何使用

cmd,粘贴代码,执行 npm install recordrtc

"recordrtc": "^5.6.2",

组件代码

<template>
  <div>
    <div>
      <span @click="startR" class="click-btn"> {{ startTxt }}</span>
    </div>
    <div v-if="startTxt !== '开始录制'">
      <span @click="pauseFn" class="click-btn"> {{ pauseTxt }}</span>
    </div>
  </div>
</template>

<script>
import RecordRTC from 'recordrtc';

export default {
  name: "rec-video",
  data() {
    return {
      startTxt: "开始录制",
      pauseTxt: "暂停",
      start: null,
      isPause: false,
      recorder: {},
    };
  },
  methods: {
    //开始录制
    startR() {
      this.startRecording((start) => {
        this.start = start;
      });
    },
    startRecording(callback) {
      if (this.startTxt === "开始录制") {
        this.captureScreen((screenStream) => {
          this.addStreamStopListener(screenStream, () => {
            console.log("流停止监听");
            // 可执行子组件回调
            // this.$emit("streamStop", {})
            this.stopFn();
          });
          this.isPause = true;
          this.startTxt = "完成录制";
          var options = {
            type: "video",
            mimeType: "video/mp4",
            disableLogs: false, // 日志开关
            getNativeBlob: false,
            ignoreMutedMedia: false,
          };
          this.recorder = RecordRTC(screenStream, options);
          this.recorder.startRecording();
          this.recorder.screen = screenStream;
          this.videoStart = true;
          callback(true);
        });
      } else if (this.startTxt === "完成录制") {
        this.stopFn();
      }
    },
    /**
     * 完成录制
     */
    stopFn() {
      this.startTxt = "开始录制";
      this.isPause = false;
      this.stopRecording((start) => {
        this.start = start;
      });
    },
    /**
     * 完成录制回调
     */
    stopRecording(callback) {
      this.recorder && this.recorder.stopRecording(() => {
        this.fileName = this.getTimeIndex()
        const url = URL.createObjectURL(this.recorder.getBlob());
        this.aTag = document.createElement("a");
        // videoFile:File,可上传 预览 下载
        let videoFile = new File(
          [this.recorder.getBlob()],
          this.fileName + ".mp4",
          {
            type: "video/mp4",
          }
        );
        let downloadUrl = URL.createObjectURL(videoFile);
        document.body.appendChild(this.aTag);
        this.aTag.style.display = "none";
        this.aTag.href = url;
        this.videoFile = videoFile;
        this.previewVideo = downloadUrl;
        // 停止录屏时同时下载到本地
        this.aTag.download = this.fileName + ".mp4";
        this.aTag.click();
        this.recorder.screen.stop();
        this.recorder.destroy();
        this.recorder = null;
        this.videoStart = false;
        this.$message({
          message: "录屏停止",
          type: "success",
        });
        callback(false);
      });
    },
    $message(e) {
      console.log(e);
    },
    pauseFn() {
      if (this.pauseTxt === "暂停") {
        this.$message({
          message: "录屏已暂停",
          type: "success",
        });
        this.recorder.pauseRecording();
        this.pauseTxt = "恢复录制";
      } else if (this.pauseTxt === "恢复录制") {
        this.$message({
          message: "录屏已恢复",
          type: "success",
        });
        this.recorder.resumeRecording();
        this.pauseTxt = "暂停";
      }
    },
    //初始化录制
    captureScreen(callback) {
      if (navigator.getDisplayMedia) {
        //录制结束,文件下载
        navigator
          .getDisplayMedia({
            video: true,
            audio: true,
          })
          .then((screenStream) => {
            navigator.mediaDevices
              .getUserMedia({ video: true, audio: true })
              .then((mic) => {
                screenStream.addTrack(mic.getTracks()[0]);
                callback(screenStream);
              });
          })
          .catch(function (error) {
            console.log("error", error);
          });
      } else if (navigator.mediaDevices.getDisplayMedia) {
        navigator.mediaDevices
          .getDisplayMedia({
            video: true,
            audio: true,
          })
          .then((screenStream) => {
            navigator.mediaDevices.getUserMedia({ audio: true }).then((mic) => {
              screenStream.addTrack(mic.getTracks()[0]);
              callback(screenStream);
            });
          })
          .catch(function (error) {
            console.log("error", error);
          });
      } else {
        var error = "getDisplayMedia API are not supported in this browser.";
        console.log("error", error);
        alert(error);
      }
    },
    //流监听
    addStreamStopListener(stream, callback) {
      stream.addEventListener(
        "ended",
        function () {
          callback();
          callback = function () {
          };
        },
        false
      );
      stream.addEventListener(
        "inactive",
        function () {
          callback();
          callback = function () {
          };
        },
        false
      );
      stream.getTracks().forEach(function (track) {
        track.addEventListener(
          "ended",
          function () {
            callback();
            callback = function () {
            };
          },
          false
        );
        track.addEventListener(
          "inactive",
          function () {
            callback();
            callback = function () {
            };
          },
          false
        );
      });
    },
    getTimeIndex() {
      let now = new Date();
      let yyyy = now.getFullYear();
      let MM = now.getMonth() + 1 > 9 ? now.getMonth() + 1 : `0${now.getMonth() + 1}`;
      let DD = now.getDate() > 9 ? now.getDate() : `0${now.getDate()}`;
      let HH = now.getHours() > 9 ? now.getHours() : `0${now.getHours()}`;
      let mm = now.getMinutes() > 9 ? now.getMinutes() : `0${now.getMinutes()}`;
      let ss = now.getSeconds() > 9 ? now.getSeconds() : `0${now.getSeconds()}`;
      return `${yyyy}${MM}${DD}${HH}${mm}${ss}`;
    }
  },
};
</script>

<style>
:root {
  --font-color: #fff;
  --default-color: #1890ff;
  --hover-color: #359dfe;
  --text-shadow-color: #0000001f;
  --box-shadow-color: #0000000b;
  --normal-distance: 15px;
}

.click-btn {
  display: inline-block;
  transition: .1s;
  cursor: pointer;
  user-select: none;
  padding: 5px var(--normal-distance);
  margin-bottom: var(--normal-distance);
  border-radius: 2px;
  color: var(--font-color);
  background: var(--default-color);
  border-color: var(--default-color);
  text-shadow: 0 -1px 0 var(--text-shadow-color);
  box-shadow: 0 2px var(--box-shadow-color);
}

.click-btn:hover {
  background: var(--hover-color);
  border-color: var(--hover-color);
}
</style>

使用:
父组件内:

<RecVideo/>
...

import RecVideo'@/components/screen.vue';

components: {
    RecVideo
  }

预览:

录制前

选择要录制内容

选择要录制内容

录制中

录制中

完成录制

完成录制

评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值