Skip to content

Videoframe distoring and blinking @1.6.0 #128

@inzamam-reachfirst

Description

@inzamam-reachfirst

alt text

I've encountered an issue. When I click on the handleStartRecording function, it triggers the startTimer() function, which is used to calculate the video recording time.

Unfortunately, this startTimer function is causing some problems. Specifically, it distorts the VideoFrame. I can't name the exact error, but what happens is that the webcam frame starts blinking and distorting. Interestingly, when I commented out the startTimer function within the handleStartRecording function, everything works ok.

I've attempted to solve this issue either by checking the recording status in the startTimer, but it seems that the timer runs a bit faster than the webcam.

import { useReactMediaRecorder } from 'react-media-recorder';

const VideoPreview = ({ stream }) => {
  const videoRef = useRef(null);
  useEffect(() => {
    console.log(stream);
    const videoElement = videoRef.current;
    if (videoElement && stream) {
      videoElement.srcObject = stream;
    }

    return () => {
      if (videoElement) {
        videoElement.srcObject = null;
      }
    };
  }, [stream]);
  if (!stream) {
    return null;
  }

  const videoWidth = stream.getVideoTracks()[0].getSettings().width;
  const videoHeight = stream.getVideoTracks()[0].getSettings().height;
  const aspectRatio = videoWidth / videoHeight;

  return (
    <video
      ref={videoRef}
      autoPlay
      style={{ width: '100%', height: `calc(100% / ${aspectRatio})`, objectFit: 'cover' }}
    />
  );
};

const Index = (props) => {
  const { status, startRecording, stopRecording, previewStream, mediaBlobUrl } = useReactMediaRecorder({ video: true });

  let history = useHistory();
  const [timer, setTimer] = useState(0);
  const [video, setVideo] = useState(null);
  const [isRecording, setIsRecording] = useState(false);
  const [showStartAgain, setShowStartAgain] = useState(false);
  const [isVideoComplete, setIsVideoComplete] = useState(false);
  const timeIntervalRef = useRef(null);
  const maxRecordingTime = 180;

  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 handleStopRecording = () => {
    setIsVideoComplete(true);
    setShowStartAgain(true);
    stopTimer();
    if (isRecording) {
      setIsRecording(false);
      setVideo(mediaBlobUrl);
      stopRecording();
    }
  };

  const startTimer = () => {
    console.log(status !== 'idle' || status !== 'stopped' || status !== 'acquiring_media');
    if (status !== 'idle' || status !== 'stopped' || status !== 'acquiring_media') {
      setTimer(0);
      timeIntervalRef.current = setInterval(() => {
        setTimer((prevTimer) => {
          if (prevTimer >= maxRecordingTime) {
            clearInterval(timeIntervalRef.current);
            handleStopRecording();
            return prevTimer;
          }
          return prevTimer + 1;
        });
      }, 1000);
    }
  };

  const handleStartRecording = () => {
    setShowStartAgain(false);
    setIsVideoComplete(false);
    if (!isRecording) {
      setIsRecording(true);
      startRecording();
      startTimer();
    }
  };

  const handleCompleteRecording = () => {
    setShowStartAgain(true);
    if (video) {
      sendVideo(video);
    }
  };

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

  return (
              <Grid container>
                <Grid item xs={12} md={12} className={classes.recordingScreen}>
                  <div>
                    {isRecording ? (
                      <VideoPreview stream={previewStream} />
                    ) : (
                      <video
                        src={mediaBlobUrl}
                        controls
                        // autoPlay
                        style={{
                          width: '100%',
                          height: 'auto',
                          objectFit: 'cover',
                        }}
                      />
                    )}
                    {status}
                  </div>
                </Grid>
              </Grid>
  );
};

const materialStyles = (theme) => ({
  recordingScreen: {
    margin: '1.875rem 0 1.875rem 0',
  },
});

export default withStyles(materialStyles)(Index);

p.s: react version "react": "^16.13.1"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions