录制视频分片存储在indexDB中

const mediaRecorder = ref()

  /**
   * 停止录制
   */
  const stopRecord = () => {
    recordButLoading.value = true
    TimerVisible.value = false
    RecorderVisible.value = true
    mediaRecorder.value?.stop()
  }
  
  

const startRecord = async (data: any, stream: any) => {

    if (!stream) {
      return
    }
    openIndexDB()
    recordedBlobs.value = []
    currentVideoIndex.value = 0
    // === 编码器检测逻辑 ===
    const supportedCodecs = MediaRecorder.isTypeSupported
    let codecOptions

    // 检测支持的编解码器
    if (supportedCodecs('video/webm; codecs=vp9,opus')) {
      codecOptions = 'video/webm; codecs=vp9,opus'
    } else if (supportedCodecs('video/webm; codecs=vp8,opus')) {
      codecOptions = 'video/webm; codecs=vp8,opus'
    } else {
      codecOptions = 'video/webm;codecs=opus'
    }
    console.log('设置的解码器:', codecOptions)

    const options = { mimeType: codecOptions }
    mediaRecorder.value = new MediaRecorder(stream, options)
    // 监听停止录制事件
    const nowTime = Date.now()
    currentVideoName.value = `${nowTime}.webm`
    // 10s判断一下累计的大小是都大于5M
    mediaRecorder.value.start(10000)
    RecorderVisible.value = false
    TimerVisible.value = true
    // 从后端根据文件名称获取uploadId
    await getUploadIdByFileName()

    let recordedSize = 0
    mediaRecorder.value.ondataavailable = (event: any) => {
      // 点击停止之后,先处理ondataavailable之后是onstop
      recordedSize += event.data.size
      if (event.data && event.data.size > 0) {
        recordedBlobs.value.push(event.data)
      }
      // 最后一片或是大于5M就作为一片
      if (recordedSize > 6 * 1024 * 1024 || !TimerVisible.value) {
        currentVideoIndex.value += 1
        const tempData = recordedBlobs.value
        console.log('存储一次分片的数据')
        handleDataAvailable(tempData)
        recordedBlobs.value = []
        recordedSize = 0
      }
    }
    mediaRecorder.value.onstop = () => {
      recordButLoading.value = false
      RecorderVisible.value = true
      if (!successOpenDB.value) {
        return
      }
      // 开启事务,并获取数据存储对象
      const transaction = recordDB.transaction(
        [SLICE_VIDEO_LIST_NAME],
        'readwrite'
      )
      const objectStore = transaction.objectStore(SLICE_VIDEO_LIST_NAME)
      // 使用索引查询 fileName为 'ABC123' 的数据
      const index = objectStore.index('fileNameIndex')
      const updateFinish = index.getAll(
        IDBKeyRange.only(currentVideoName.value)
      )

      updateFinish.onsuccess = function (event: any) {
        const records = event.target.result
        createSuccessMessage('视频录制成功')
        if (records && records.length > 0) {
          records.forEach(function (record: any) {
            // 更新记录的 recordFinish 属性为 true
            record.recordFinish = true
            // 更新记录
            const updateRequest = objectStore.put(record)

            updateRequest.onsuccess = function () {
              console.log('停止之后记录更新成功')
            }

            updateRequest.onerror = function () {
              console.error('停止之后记录更新失败')
            }
          })
        } else {
          console.log('未找到匹配的记录')
        }
      }

      updateFinish.onerror = function (event: any) {
        console.error('查询失败', event.target.error)
      }
    }
  }

MediaRecorder 方法解析

1. mediaRecorder.value.start(10000)

  • 启动媒体录制

  • 参数 10000 表示每 10 秒(10000 毫秒)触发一次 ondataavailable 事件

  • 这样设计是为了定期获取录制的视频数据块

2. mediaRecorder.value.stop()

  • 停止媒体录制

  • 会触发最后的 ondataavailable 事件(获取最后的数据块)

  • 然后触发 onstop 事件

3. mediaRecorder.value.ondataavailable

  • 事件处理器,当有新的录制数据可用时触发

  • 主要功能:

    • 累计记录数据大小 (recordedSize)

    • 将数据块存入 recordedBlobs 数组

    • 判断条件(大于6MB或录制停止)时调用 handleDataAvailable 处理数据

    • 重置记录状态

4. mediaRecorder.value.onstop

  • 事件处理器,当录制完全停止时触发

  • 主要功能:

    • 更新界面状态

    • 检查 IndexedDB 是否成功打开

    • 更新 IndexedDB 中该视频的完成状态

updateFinish 解析

updateFinish 是 IndexedDB 的一个查询操作,主要作用是:

  1. 通过 fileNameIndex 索引查询所有 fileName 等于 currentVideoName.value 的记录

  2. 查询成功后 (onsuccess):

    • 遍历所有匹配的记录

    • 将每条记录的 recordFinish 属性设置为 true(标记为已完成)

    • 使用 objectStore.put() 更新记录

  3. 如果没有找到匹配记录,输出日志

  4. 查询失败时 (onerror) 输出错误信息

整体流程

  1. 开始录制

    • 检测支持的视频编解码器

    • 创建 MediaRecorder 实例

    • 每10秒获取一次数据块

    • 当数据块累计超过6MB或停止录制时,处理并存储数据

  2. 停止录制

    • 停止 MediaRecorder

    • 处理最后的数据块

    • 更新 IndexedDB 中该视频的状态为已完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值