stop/close Microphone and Camera after Recording

164 Views Asked by At

I have been trying to stop/close my camera and microphone after recording in my ReactJs App since last 3 weeks, I have tried each and every content of StackOverflow, mediaRecorder from MDN, and used every technique, but still no progress.

It stops only when I refresh my browser in my ReactJs app on some other page rather than a used component page.

Here is my Reactjs Component:

import { useState, useRef, useEffect } from "react";
import { Logos } from "../../assets";
import "./ReplyVideoPreview.css";
import React from "react";
import { Link } from "react-router-dom";
import { useNavigate } from "react-router";
import { postVideo } from "../../hooks/useVideo";
// import { sendFileMessage } from "../../hooks/useConversation";
import {
  useUploadConversationFiles,
  sendFileMessage,
} from "../../hooks/useConversation";
const mimeType = 'video/webm; codecs="opus,vp8"';
import { useStoreConversation } from "../../store/conversation";
import { useGlobalInfo } from "../../contexts/GlobalContext";
import GlobalLoaderCopy from "../GloabalLoaderCopy/GloabalLoaderCopy";

const VideoRecorder = () => {
  let localVideoChunks = [];
  const mediaRecorder = useRef(null);
  const liveVideoFeed = useRef(null);
  const [recordingStatus, setRecordingStatus] = useState("inactive");
  const [recordedVideo, setRecordedVideo] = useState(null);
  const [videoChunks, setVideoChunks] = useState([]);
  const [isRecording, setIsRecording] = useState(false);
  const [isRecordingStop, setIsRecordingStop] = useState(false);
  const { loading, setLoading } = useGlobalInfo();
  const [sendChat, setSendChat] = useState();
  const navigate = useNavigate();
  const { mutate, isLoading, isError } = useUploadConversationFiles();
  const setFileData = useStoreConversation((state) => state.setFileData);
  const getFileData = useStoreConversation((state) => state.fileData);
  const fileData = useRef(null);

  const pauseRecording = async () => {
    // console.log(mediaRecorder.current.state);
    if (mediaRecorder && mediaRecorder.current.state === "recording") {
      mediaRecorder.current.pause();
    }
  };

  const resumeRecording = async () => {
    if (mediaRecorder && mediaRecorder.current.state === "paused") {
      mediaRecorder.current.resume();
    }
  };

  const [isFirstFunction, setIsFirstFunction] = useState(true);
  const [isPlaying, setIsPlaying] = useState(false);

  const getPlayPauseIcon = () => {
    return isPlaying ? Logos.VideoPLayBtn : Logos.VideoPreviewPlay;
  };


  const handleClick = () => {
    setIsPlaying((prevState) => !prevState);
    if (isFirstFunction) {
      // Call the first function
      pauseRecording();
    } else {
      // Call the second function
      resumeRecording();
    }
    // Toggle the state variable for the next click
    setIsFirstFunction(!isFirstFunction);
  };

  useEffect(() => {
    const getCameraPermission = async () => {
      let stream;
      if ("MediaRecorder" in window) {
        try {
          const videoConstraints = {
            audio: false,
            video: true,
          };
          const audioConstraints = { audio: true };

          const audioStream = await navigator.mediaDevices.getUserMedia(
            audioConstraints
          );
          const videoStream = await navigator.mediaDevices.getUserMedia(
            videoConstraints
          );

          stream = new MediaStream([
            ...videoStream.getVideoTracks(),
            ...audioStream.getAudioTracks(),
          ]);

          liveVideoFeed.current.srcObject = videoStream;
        } catch (err) {
          // alert(err.message);
        }
      } else {
        // alert("The MediaRecorder API is not supported in your browser.");
      }

      return stream;
    };

    const startRecording = async (stream) => {
      setRecordingStatus("recording");

      const media = new MediaRecorder(stream, { mimeType });

      mediaRecorder.current = media;

      mediaRecorder.current.start();

      // let localVideoChunks = [];

      mediaRecorder.current.ondataavailable = (event) => {
        if (typeof event.data === "undefined") return;
        if (event.data.size === 0) return;
        localVideoChunks.push(event.data);
      };

      setVideoChunks(localVideoChunks);
      setIsRecording(true);
    };

    const initializeRecording = async () => {
      const stream = await getCameraPermission();
      await startRecording(stream);
    };

    initializeRecording();
  }, []);

  // const closeCamera = async () => {
  //   const videoStream = liveVideoFeed.current.srcObject;
  //   // Stop the camera stream
  //   if (videoStream) {
  //     videoStream.getTracks().forEach((track) => track.stop());
  //   }
  //   // Reset the recorded video and video chunks
  //   // setRecordedVideo(null);
  //   setVideoChunks([]);
  //   // Perform any additional cleanup tasks
  //   // ...
  //   // Optionally, you can update the recording status and other related states
  //   setRecordingStatus("inactive");
  //   setIsRecording(false);
  // };

  const stopRecording = () => {
    setRecordingStatus("inactive");
    mediaRecorder.current.stop();

    const stream = mediaRecorder.current.stream;

    stream.getTracks().forEach((track) => track.stop());

    mediaRecorder.current.onstop = async () => {
      const videoBlob = new Blob(videoChunks, { type: mimeType });
      const videoUrl = URL.createObjectURL(videoBlob);

      setRecordedVideo(videoUrl);
      
      setVideoChunks([]);
      setIsRecording(false);

      // Call the external stopRecordingCallback if it's provided
      if (typeof stopRecordingCallback === "function") {
        stopRecordingCallback();
      }

      const formData = new FormData();
      formData.append("file", videoBlob, "video.mp4");
      formData.append("type", "conversation");
      // const videoResponse = await postVideo(formData);
      fileData.current = formData;
      if (fileData.current) {
        setLoading(true)
        mutate(fileData.current, {
          onSuccess: async (data) => {
            await setFileData(data.data);
            setLoading(false)
          },
          onError: (error) => {
            showError();
            setLoading(false)
          },
        });
      }
      setSendChat(videoResponse);
      // sendMessage(videoResponse);

    };

    setIsRecordingStop(true);
  };

  const uploadFile = () => {
    setLoading(true)
    sendMessage();
  };
  const sendMessage = async () => {
    setLoading(true)

    // debugger;
    // const data = await sendFileMessage(videoResponse);
    // data.messageHistoryPreviewThumbnail = "test";
    // data.messagePreviewThumbnail = "test";

    // if (data) {
    //   navigate("/conversation");
    // }

    const payload = getFileData;
    const data = sendFileMessage(payload);
    if (data) {
      navigate("/conversation");
      setLoading(false)
    }
    // setLoading(false) 
  };

  function VideoHandler() {
    navigate("/reply-video-preview");
  }

  return (
    <>
      {loading ? <GlobalLoaderCopy /> : <div>
        <div className="flex items-center p-2 justify-between">
          <div className="flex items-center gap-2">
            <img
              src={Logos.ArrowLeft}
              alt=""
              className="cursor-pointer w-[20px] xxxxl:w-[30px]"
              onClick={() => {
                VideoHandler();
              }}
            />
            <h1 className=" text-[18px] font-[500] leading-[30px] text-[#262626] xxxxl:text-[30px]">
              Video Preview
            </h1>
          </div>
          <Link to="/reply-video-preview">
            <img src={Logos.Rectangule} alt="" className="icon-size" />
          </Link>
        </div>
        <div
          className="w-full video_div"
          style={{ height: "calc(100vh - 155px)" }}
        >
          <div
            className={`border-[1px] border-[#EBEBEB] border-solid mt-2 shadow-md flex flex-col videoRec_div`}
            style={{ height: "calc(100vh - 150px)" }}
          >
            <div className="video2">
              {!recordedVideo ? (
                <video
                  // style={{ transform: "scaleX(-1)" }}

                  ref={liveVideoFeed}
                  autoPlay
                  className="live-player"
                ></video>
              ) : (
                <div className="recorded-player">
                  <video
                    // style={{ transform: "scaleX(-1)" }}

                    className="recorded"
                    src={recordedVideo}
                    controls
                  ></video>
                  {/* <a download href={recordedVideo}>
                    Download Recording
                  </a> */}
                </div>
              )}
            </div>
            <div className="pl-8">
              <h1 className=" text-[16px] font-[400] leading-[22px] text-white py-2  xxxxl:text-[28px] xxxxl:leading-[38px]">
                Replying to...
              </h1>
              <h1 className=" text-[20px] font-[500] leading-[28px] text-white py-1 xxxxl:text-[32px] xxxxl:leading-[38px]">
                Ryan Jones
              </h1>
              <p className=" sm:text-[16px] font-[400] leading-[22px] text-white text-[14px] xxxxl:text-[26px] xxxxl:leading-[28px]">
                [email protected]
              </p>
            </div>
            <div
              className="flex flex-col justify-end items-center gap-3 "
              style={{ height: "calc(100vh - 150px)" }}
            >
              <div
                className="flex justify-center items-end "
                style={{ zIndex: 111 }}
              >
                {/* {!isRecordingStop && (
                  <div className="flex items-center gap-4 mb-4 cursor-pointer">
                    <Link>
                      <img
                        src={Logos.VideoPreviewPlay}
                        alt=""
                        className=" xxxxl:w-[150px] mb-4"
                        onClick={stopRecording}
                      />
                    </Link>
                  </div>
                )} */}

                {!isRecordingStop && (
                  <div className="flex flex-col justify-center items-center gap-4">
                    <div className="flex justify-center items-center">
                      <Link>
                        <img
                          src={getPlayPauseIcon()}
                          alt=""
                          className=" xxxxl:w-[150px] mb-5"
                          onClick={handleClick}
                        // onClick={stopRecording}
                        />
                      </Link>
                      <div className="flex items-center gap-4 mb-5 cursor-pointer">
                        <Link to={"#"}>
                          <img
                            src={Logos.TickIcon}
                            alt=""
                            className=" xxxxl:w-[150px] mb-2 ml-2"
                            onClick={stopRecording}
                          />
                        </Link>
                      </div>
                    </div>
                  </div>
                )}

                {isRecordingStop && (
                  <div
                    className="flex justify-center items-end "
                    style={{ marginBottom: "50px" }}
                  >
                    <div className="flex items-center gap-5 cursor-pointer ">
                      <img
                        src={Logos.ApproveYes}
                        alt=""
                        className=""
                        style={{ width: "calc(2.5rem + 1vw)" }}
                        onClick={() => uploadFile()}
                      />
                      {/* </Link> */}
                      <Link to="/reply-video-preview">
                        <img
                          src={Logos.ApproveNo}
                          alt=""
                          className=""
                          style={{ width: "calc(2.5rem + 1vw)" }}
                        />
                      </Link>
                    </div>
                  </div>
                )}
                {/* my work Ends from here  */}
              </div>
            </div>
          </div>
        </div>
      </div>}
      {/* <h2 className="rec">Video Recorder</h2>
      <main>
        <div className="video-controls">
          {recordingStatus === "recording" ? (
            <button onClick={stopRecording} type="button">
              stooop
            </button>
          ) : null}
        </div>
        {isRecording && <p>Recording...</p>}
      </main> */}


    </>
  );
};

export default VideoRecorder;

Here is the stopRecording Part of code:

const stopRecording = () => {
    setRecordingStatus("inactive");
    mediaRecorder.current.stop();

    const stream = mediaRecorder.current.stream;

    stream.getTracks().forEach((track) => track.stop());

    mediaRecorder.current.onstop = async () => {
      const videoBlob = new Blob(videoChunks, { type: mimeType });
      const videoUrl = URL.createObjectURL(videoBlob);

      setRecordedVideo(videoUrl);
      
      setVideoChunks([]);
      setIsRecording(false);

      // Call the external stopRecordingCallback if it's provided
      if (typeof stopRecordingCallback === "function") {
        stopRecordingCallback();
      }

      const formData = new FormData();
      formData.append("file", videoBlob, "video.mp4");
      formData.append("type", "conversation");
      // const videoResponse = await postVideo(formData);
      fileData.current = formData;
      if (fileData.current) {
        setLoading(true)
        mutate(fileData.current, {
          onSuccess: async (data) => {
            await setFileData(data.data);
            setLoading(false)
          },
          onError: (error) => {
            showError();
            setLoading(false)
          },
        });
      }
      setSendChat(videoResponse);
      // sendMessage(videoResponse);

    };

    setIsRecordingStop(true);
  };

I have tried every answer provided on StackOverflow but no progress.

0

There are 0 best solutions below