为什么我的上传函数被调用了两次

问题描述 投票:0回答:1

我只是想构建一些类似实时录像机的东西(实际上不是),只是想每隔几秒在云端保存视频。

我在reactjs中编写了一些代码,当我的网络摄像头安装时,我启动摄像头并开始使用

mediaRecorder
进行录制,并希望在摄像头卸载时停止录制

我的代码:

import React, { useRef, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { axiosServerInstance } from "@/utils/api/instances";
import { serverRoutes } from "@/utils/api/routes";

const cloudinaryUploadUrl = "https://api.cloudinary.com/v1_1/-----/video/upload";

const WebCam = () => {
  const videoRef = useRef(null);
  const mediaRecorderRef = useRef(null);
  const recordedChunksRef = useRef([]);
  const uploadIntervalRef = useRef(null);
  const [isUploading,setIsUploading]=useState(false)
  const isComponentMounted = useRef(true); 
  const proctorId = useSelector((state) => state?.assessment?.assessmentTestData?.report?.proctorId);

  const updateProctorVideoUrl = async (chunks) => {
    try {
     
        await axiosServerInstance.put(serverRoutes.submitVideoUrl, {
          proctorId,
          ...chunks,
        });
      
    } catch (error) {
      console.error("Error updating proctor:", error.response?.data || error.message);
    }
  };

  const uploadToCloudinary = async (blob) => {
    if (!isComponentMounted.current) return; 

    const formData = new FormData();
    formData.append("file", blob);
    formData.append("upload_preset", "-----");

    try {
      const response = await fetch(cloudinaryUploadUrl, {
        method: "POST",
        body: formData,
      });
      const data = await response.json();
      await updateProctorVideoUrl({
        asset_id: data.asset_id,
        public_id: data.public_id,
        url: data.url,
        proctorId,
      });
    } catch (error) {
      console.error("Error uploading video:", error);
    }
  };

  const startCamera = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ video: true });
      if (videoRef.current) {
        videoRef.current.srcObject = stream;
      }
      return stream;
    } catch (error) {
      console.error("Error accessing camera:", error);
      throw error;
    }
  };

  const startRecording = (stream) => {
    recordedChunksRef.current = [];
    const mediaRecorder = new MediaRecorder(stream, { mimeType: "video/mp4" });
    mediaRecorder.ondataavailable = (event) => {
      if (event.data.size > 0) {
        recordedChunksRef.current.push(event.data);
      }
    };
    mediaRecorder.onstop = async () => {
      if (recordedChunksRef.current.length > 0 && !isUploading) {
        setIsUploading(true);
        const blob = new Blob(recordedChunksRef.current, { type: "video/mp4" });
        await uploadToCloudinary(blob);
        recordedChunksRef.current = [];
        mediaRecorder.start();
        setIsUploading(false);
      }
    };
    
    mediaRecorder.start();
    mediaRecorderRef.current = mediaRecorder;
    
    uploadIntervalRef.current = setInterval(() => {
      if (mediaRecorder.state === "recording" && !isUploading) {
        mediaRecorder.stop();
      }
    }, 5000);
  };

  useEffect(() => {
    let stream;

    const init = async () => {
      isComponentMounted.current = true; 
      stream = await startCamera();
      startRecording(stream);
    };

    init();

    return () => {
      isComponentMounted.current = false; 

      if (uploadIntervalRef.current) {
        clearInterval(uploadIntervalRef.current);
      }

      if (stream) {
        stream.getTracks().forEach((track) => track.stop());
      }

      if (videoRef.current) {
        videoRef.current.srcObject = null;
      }
    };
  }, []);

  return <video ref={videoRef} autoPlay muted className="w-full h-full object-cover" />;
};

export default WebCam;

我面临的问题

  1. 我的上传函数在上传时被调用两次

在此输入图片描述

  1. 还想知道,因为我在后端合并视频,是否可以仅按一个顺序推送视频,因为有时一个视频块仍在上传,而其他视频块正在上传

ps:如果有更便宜的实时录音机可以推荐一下

reactjs cloudinary mediarecorder
1个回答
0
投票

您的 uploadToCloudinary 函数可能会被多次调用,因为 setInterval 内的 mediaRecorder.stop() 调用会触发 mediaRecorder.onstop 事件,该事件又会开始新的录制并设置另一个间隔,可能会导致重叠调用。

1.确保单次上传触发

使用标志来确保上传过程(如果已经在进行中)不会再次启动。您已经在使用 isUploading,但让我们改进它的用法。

2.更仔细地管理录音和上传

为避免重叠调用,请确保正确管理录制和上传逻辑,并避免在 onstop 事件处理程序内立即重新启动录制(如果已经有正在进行的上传)。

© www.soinside.com 2019 - 2024. All rights reserved.