React 录制的视频未在视频标签中播放

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

我正在创建一个 React 应用程序,用于对候选人进行网络摄像头面试。候选人还可以“重新开始”或“完成”他们的面试。

为了显示录制的数据,我尝试将其显示为 HTML 视频。但是,我遇到了录制后视频不出现的问题。视频数据当前为 blob 格式。

此外,我还添加了一个下载按钮;当用户下载视频时,它可以正常工作并保存在本地。

我尝试了一些解决方案来解决显示问题。我尝试在 src 属性中使用 .mp4 或 .webm 扩展名直接嵌入视频。我还尝试过第三方 React 视频播放器 npm 包。不幸的是,到目前为止,这些方法都没有成功。

import Webcam from 'react-webcam';
const Index = (props) => {
  const [timer, setTimer] = useState(0);
  const [totalTime, setTotalTime] = useState(0);
  const [video, setVideo] = useState(null);
  const [isRecording, setIsRecording] = useState(false);

  const [isVideoComplete, setIsVideoComplete] = useState(false);
  const [webcamLoading, setWebcamLoading] = useState(true);

  const webcamRef = useRef(null);
  const mediaRecorderRef = useRef(null);
  const timeIntervalRef = useRef(null);
  const [recordedChunks, setRecordedChunks] = useState([]);

  const maxRecordingTime = 180;

  const videoConstraints = {
    aspectRatio: 0.6666666667,
    width: 1280,
    height: 720,
    facingMode: 'user',
  };

  const audioConstraints = {
    suppressLocalAudioPlayback: true,
    noiseSuppression: true,
    echoCancellation: true,
  };


  const stopTimer = () => {
    clearInterval(timeIntervalRef.current);
  };

  const formatTime = (seconds) => {
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = seconds % 60;
    return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`;
  };

  const handleDataAvailable = React.useCallback(
    ({ data }) => {
      if (data.size > 0) {
        setRecordedChunks((prev) => prev.concat(data));
      }
    },
    [setRecordedChunks]
  );
  // Stop Recording
  const handleStopRecording = useCallback(() => {
    setIsVideoComplete(true);
    setShowStats(true);
    stopTimer();
    console.log(isRecording, mediaRecorderRef.current);
    if (isRecording && mediaRecorderRef.current) {
      setIsRecording(false);
      const blob = new Blob(recordedChunks, { type: 'video/webm' });
      // Blob { size: 0, type: 'video/webm' }
      console.log(blob);
      setVideo(blob);

      mediaRecorderRef.current.stop();
    }
  }, [isRecording, recordedChunks]);

  const startTimer = useCallback(() => {
    setTimer(0);
    timeIntervalRef.current = setInterval(() => {
      setTimer((prevTimer) => {
        if (prevTimer >= maxRecordingTime) {
          handleStopRecording();
          return prevTimer;
        }
        return prevTimer + 1;
      });
    }, 1000);
  }, [handleStopRecording]);
  
  // Start Recording
  const handleStartRecording = useCallback(() => {
    setShowStats(false);
    setIsVideoComplete(false);
    if (!isRecording) {
      setIsRecording(true);
      startTimer();
      if (webcamRef.current && webcamRef.current.video.srcObject) {
        const stream = webcamRef.current.video.srcObject;
        mediaRecorderRef.current = new MediaRecorder(stream, {
          mimeType: 'video/webm',
        });
        mediaRecorderRef.current.addEventListener('dataavailable', handleDataAvailable);
        mediaRecorderRef.current.start();
      }
    }
  }, [handleDataAvailable, isRecording, startTimer]);

  const handleCompleteRecording = () => {
    setShowStats(true);
    if (video) {
      sendVideo(video);
    }
  };
   
   // Download Video
   const handleDownload = React.useCallback(() => {
     if (recordedChunks.length) {
       const blob = new Blob(recordedChunks, {
         type: 'video/webm',
       });
       const url = URL.createObjectURL(blob);
       const a = document.createElement('a');
       document.body.appendChild(a);
       a.style = 'display: none';
       a.href = url;
       a.download = 'react-webcam-stream-capture.webm';
       a.click();
       window.URL.revokeObjectURL(url);
       setRecordedChunks([]);
     }
   }, [recordedChunks]);

  const handleStartAgain = () => {
    setIsRecording(false);
    setShowStats(false);
    setIsVideoComplete(false);
    setVideo(null);
    stopTimer();
    setTimer(0);
  };

  const sendVideo = (video) => {
    const formData = new FormData();
    formData.append('video', video, 'interview.webm');

    console.log('Posting Video...', video);
  };

  return (
    <div className={classes.mainContent}>
        <>
          <Grid container>
            <Grid item xs={8} className={classes.rightSection}>
              <Grid container>
                {/* Record Section */}
                <Grid item xs={12} md={12} className={classes.recordingScreen}>
                  <div style={{ height: '480px', width: '100%', position: 'relative' }}>
                    {/* {webcam && ( */}
                    {!video ? (
                      webcamLoading ? (
                        <CircularProgress style={{ height: '2.5rem', width: '2.5rem' }} color="inherit" />
                      ) : (
                        <div className={`webcamContainer ${webcamLoading ? 'webccamLoading' : ''}`}>
                          <Webcam
                            ref={webcamRef}
                            audio={true}
                            mirrored={true}
                            muted={true}
                            onUserMedia={handleUserMedia}
                            style={{ width: '100%', height: '100%', objectFit: 'cover' }}
                            videoConstraints={videoConstraints}
                            audioConstraints={audioConstraints}
                          />
                        </div>
                      )
                    ) : (
                      <>
                        {video && (
                          <>
                            <video
                              src={video ? URL.createObjectURL(video) : ''}
                              controls
                              style={{ width: '100%', height: '100%', objectFit: 'cover' }}
                              onError={(e) => {
                                console.log('Error', e);
                              }}
                            />
                            {recordedChunks.length > 0 && <button onClick={handleDownload}>Download</button>}
                          </>
                        )}
                      </>
                    )}
                  </div>
                </Grid>

});

export default withStyles(materialStyles)(Index);
javascript reactjs video material-ui webcam
1个回答
0
投票

注意:我不使用 React,所以请尝试修复以下错误:

解决方案是将视频标签的源替换为您的 blob。

您可以尝试的起点(关于上述概念)...

(1)。使用它作为您的

<video>
标签设置(例如: 您必须为此元素设置 ref):

<video
  ref={videoRef}
  type="video/mp4"
  src=""
  controls
  style={{ width: '100%', height: '100%', objectFit: 'cover' }}
  onError={(e) => { console.log('Error', e); }}
/>

(2) 然后使用

\\Download Video
函数来播放 blob(因为你说它有有效数据):

//# Download Video
const handleDownload = React.useCallback(() => {
 if (recordedChunks.length) 
 {
   const blob = new Blob(recordedChunks, { type: 'video/webm' });
   const url = URL.createObjectURL(blob);
   
   //# test playback ...
   videoRef.current.src = url;
   videoRef.current.load();
   videoRef.current.play();
   
   //# save as file
   const a = document.createElement('a');
   document.body.appendChild(a);
   a.style = 'display: none';
   a.href = url;
   a.download = 'react-webcam-stream-capture.webm';
   a.click();
   window.URL.revokeObjectURL(url);
   setRecordedChunks([]);
 }
}, [recordedChunks] );

PS: 另一件需要注意的事情是,在 Apple 硬件上,您可能会以

video/mp4
类型而不是
video/webm
类型获取视频。我知道 iOS 上的 Safari 浏览器会创建 MP4 视频。只是说,如果 HTML 标记仍然不起作用,请考虑您的操作系统和/或浏览器是否影响结果。
例如:是否因为您在 Mac / Ipad / Iphone 上的 Safari 中设置为
video/webm
而无法工作?

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