前端实现录屏功能(进阶)

274 阅读2分钟

实现功能

前端页面,点击开始录屏,视频录制,点击停止录屏,视频录制结束,并生成视频下载到本地 相对上个版本,解决了,在页面内点停止按钮,可直接触发浏览器的停止共享按钮,两个按钮直接同步

image.png

实现代码

vue3+ts

<template>
  <!-- <ContentWrap> -->
  <!-- 屏幕共享控制按钮 -->
  <BaseButton size="small" type="primary" class="btn mt-2px" @click="toggleScreenShare">
    {{ isRecording ? '停止录制' : '开始录制' }}
  </BaseButton>

  <!-- 权限错误提示 -->
  <p v-if="permissionError" class="error-message">请允许屏幕共享权限以便继续。</p>
  <!-- </ContentWrap> -->
</template>

<script setup lang="ts">
// import { ContentWrap } from '@/components/ContentWrap'
import { ref } from 'vue'

// 声明变量以跟踪媒体记录器状态、数据块、是否正在录制及权限错误
const mediaRecorder = ref<MediaRecorder | null>(null)
const chunks = ref<BlobPart[]>([])
const isRecording = ref(false)
const permissionError = ref(false)

// 切换屏幕共享状态
async function toggleScreenShare() {
  if (!isRecording.value) {
    await startScreenShare()
  } else {
    stopScreenShare()
  }
}

// 初始化屏幕共享流
let screenStream = ref<MediaStream | null>(null)

// 开始屏幕共享录制
async function startScreenShare() {
  try {
    // 请求显示媒体流(屏幕共享)
    screenStream.value = await navigator.mediaDevices.getDisplayMedia({ video: true })
    if (!screenStream.value) throw new Error('用户未授权屏幕共享。')

    // 设置视频编码(优先H264,否则默认)
    const mimeType = MediaRecorder.isTypeSupported('video/webm;codecs=h264')
      ? 'video/webm;codecs=h264'
      : 'video/webm'

    // 初始化媒体记录器
    mediaRecorder.value = new MediaRecorder(screenStream.value, { mimeType })

    // 监听数据可用事件,收集录制的数据块
    mediaRecorder.value.addEventListener('dataavailable', handleDataAvailable)
    // 监听停止事件,处理录制完成后的操作
    mediaRecorder.value.addEventListener('stop', onMediaRecorderStop)

    // 开始录制
    mediaRecorder.value.start()
    isRecording.value = true
  } catch (error) {
    console.error('屏幕共享启动失败:', error)
    if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
      permissionError.value = true
    }
  }
}

// 数据块处理函数
function handleDataAvailable(event: BlobEvent) {
  // 收集每个数据块到chunks数组中
  chunks.value.push(event.data)
}

// 停止屏幕共享录制
function stopScreenShare() {
  if (mediaRecorder.value && mediaRecorder.value.state !== 'inactive') {
    mediaRecorder.value.stop()
    // 停止所有轨道,//直接触发浏览器的停止分享按钮
    screenStream.value?.getTracks().forEach((track) => track.stop())
    screenStream.value = null
  }
}

// 录制完成后处理函数
function onMediaRecorderStop() {
  if (chunks.value.length) {
    // 将数据块转换为Blob,创建下载链接
    const blob = new Blob(chunks.value, { type: chunks.value[0].type })
    const url = URL.createObjectURL(blob)
    const downloadLink = document.createElement('a')
    downloadLink.href = url
    downloadLink.download = 'screen_recording.webm'
    document.body.appendChild(downloadLink)
    downloadLink.click()
    document.body.removeChild(downloadLink)

    // 清理资源
    chunks.value = []
    mediaRecorder.value = null
    isRecording.value = false
  }
}
</script>

<style scoped>
.error-message {
  color: red;
  margin-top: 10px;
}
</style>

存在问题

在切换页面的时候,在切回来,原页面的停止按钮他会初始化成 开始录制,点击的话他又重新录,但上个媒体还在进行,这样肯定有问题,如果存在需要切换页面的情况,建议直接使用浏览器的停止共享按钮

参考

// getTracks() developer.mozilla.org/zh-CN/docs/…