vue3手写基于本地摄像头的视频功能

311 阅读1分钟

image.png

先封装video组件

<template>
  <div class="videoBox" :style="style">
    <video ref="videoElement" autoplay playsinline :controls="controlsFlag" style="width: 100%; height: 100%"></video>
  </div>
</template>
<script setup>
const props = defineProps({
  controlsFlag: Boolean,
  style: String,
});

const videoElement = ref(null);

const state = reactive({
  stream: null,
});

const mediaRecorder = ref(null);

const startPlay = async () => {
  state.stream = await navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true,
  });
  if ('srcObject' in videoElement.value) {
    videoElement.value.srcObject = state.stream;
  } else {
    // 防止在新的浏览器里使用它,应为它已经不再支持了
    videoElement.value.src = window.URL.createObjectURL(state.stream);
  }
  videoElement.value.onloadedmetadata = function (e) {
    videoElement.value.play();
  };
};

// 下载图片
function download(src) {
  if (!src) return;
  const a = document.createElement('a');
  a.setAttribute('download', new Date());
  a.href = src;
  a.click();
}
const onPhoto = () => {
  // 通过canvas捕捉video流,生成base64格式图片
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  const { clientWidth, clientHeight } = videoElement.value;
  canvas.width = clientWidth;
  canvas.height = clientHeight;
  context.drawImage(videoElement.value, 0, 0, canvas.width, canvas.height);
  download(canvas.toDataURL('image/jpeg'));
};

//开始录屏
const startLp = () => {
  console.log('开始录屏');
  // 获取video节点
  // const video = document.getElementById('videoFlv');

  // 存储视频流
  const videoData = [];
  // 浏览器兼容Chrome和firefox
  videoElement.value.captureStream = videoElement.value.captureStream || videoElement.value.mozCaptureStream;
  // 生成MediaRecorder对象
  mediaRecorder.value = new MediaRecorder(videoElement.value.captureStream());
  mediaRecorder.value.start();
  // 当 MediaRecorder 将媒体数据传递到您的应用程序以供使用时,将触发该事件
  mediaRecorder.value.ondataavailable = (e) => {
    console.log(e);
    // 添加视频流
    videoData.push(e.data);
  };

  // 录制结束回调
  mediaRecorder.value.onstop = (e) => {
    const blob = new Blob(videoData, { type: 'video/mp4' });

    const videoUrl = window.URL.createObjectURL(blob);
    // open(videoUrl);
    var a = document.createElement('a');
    a.href = videoUrl;
    a.download = 'video.mp4';
    a.click();
  };
};
//停止录屏
const stopLp = () => {
  console.log('停止录屏');
  mediaRecorder.value.stop();
};

defineExpose({
  onPhoto,
  startLp,
  stopLp,
});
onMounted(() => {
  startPlay();
});
onUnmounted(() => {
  state.stream.getTracks().forEach((track) => track.stop());
  state.stream = null;
});
</script>

具体使用 import LocalVideo from '@/components/LocalVideo.vue';

<template>
  <LocalVideo ref="videoRef" :controlsFlag="false" />
</template>

js部分

const videoRef = ref(null)
// 实现拍照功能
const onPhoto = () => {
  videoRef.value.onPhoto()
};

// 实现录屏功能
const onScreenRecord = () => {
videoRef.value.startLp();
// 10秒钟之后停止录屏
 setTimeout(() => {
      videoRef.value.stopLp();
    }, 10000);
  }
};