Youtube Clone Coding (11. Video Recoder)

LeeJaeHoon·2021년 11월 13일
0
post-thumbnail
  1. MediaDevices.getUserMedia()을 통해서 MediaStream을 얻을 수 있음.

    1. 보통, [MediaDevices](https://developer.mozilla.org/ko/docs/Web/API/MediaDevices) 싱글톤 객체는 다음과 같이 [navigator.mediaDevices](https://developer.mozilla.org/ko/docs/Web/API/Navigator/mediaDevices)를 사용해 접근한다.
    2. getUserMedia()의 인자로는 요청할 미디어 유형과 각각에 대한 요구사항을 지정하는 [MediaStreamConstraints (en-US)](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints) 객체가 온다.
  2. MediaStream얻기

    • 프론트에서 async/await를 쓰기위해서는 npm i regenerator-runtime헤주고 async/await을 쓰고싶은 파일에 import를 해주어야 한다.
    const init() = async () => {
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: true,
        video: true,
      });
    };
    init();
  3. 얻은 MediaStream으로 video 재생하기

    • video에 srcObject로 MediaStrean를 주면 video실행가능
      • HTMLMediaElement.srcObject는 MediaStrean, MediaSource,Blob, File을 실행할 때 사용된다.
        const video = document.getElementById("preview");
        
        const init = async () => {
          const stream = await navigator.mediaDevices.getUserMedia({
            audio: true,
            video: { width: 200, height: 100 },
          });
          video.srcObject = stream;
          video.play();
        };
        
        init()
  4. startBtn클릭시 innerText 바꿔주기

    • 처음 startBtn클릭시 innerText를 Stop Recoding으로 바꿔줘야한다.
    • Stop Recoding으로 바뀐 startBtn클릭시 innerText를 Download Recoding으로 바꿔줘야한다.
      • 처음 startBtn클릭시 addEventListener을 지워주고 새로만들어 줘야함.
        • handleDownload기능은 나중에 추가해 줄 거임!

          const handleStop = () => {
          	startBtn.innerText = "Download Recording";
            startBtn.removeEventListener("click", handleStop);
            startBtn.addEventListener("click", handleDownload);
          }
           
          const handleStart = () => {
          	startBtn.innerText = "Stop Recoding";
            startBtn.removeEventListener("click", handleStart);
            startBtn.addEventListener("click", handleStop);
          }
          
          startBtn.addEventListener("click", handleStart);
  5. startBtn클릭시 video 녹화 시작하기

    • MediaRecorder를 이용해서 video를 녹화 할 수 있다. → 파라미터로 stream이 필요하다.
      • MediaRecorder.start() 메소드를 이용하여 녹화를 시작할 수 있음.
      • MediaRecorder.stop() 메소드를 이용하여 녹화를 중지 할 수 있음.
        • MediaRecorder.stop() 이 호출되면 MediaRecorder.ondataavailable event가 발생한다.

        • MediaRecorder.ondataavailable event를 이용하여 녹화한 video를 가져올 수 있다.

          let stream;
          let recorder;
          
          const handleStop = () => {
            startBtn.innerText = "Download Recording";
            startBtn.removeEventListener("click", handleStop);
            startBtn.addEventListener("click", handleDownload);
            recorder.stop();
          };
          
          const handleStart = () => {
            startBtn.innerText = "Stop Recoding";
            startBtn.removeEventListener("click", handleStart);
            startBtn.addEventListener("click", handleStop);
            recorder = new MediaRecorder(stream);
            recorder.ondataavailable = e => {
              console.log(e);
            };
            recorder.start();
          };
          
          const init = async () => {
            stream = await navigator.mediaDevices.getUserMedia({
              audio: true,
              video: { width: 200, height: 100 },
            });
            video.srcObject = stream;
            video.play();
          };
          
          init();
          
          startBtn.addEventListener("click", handleStart);
        • ondataavailable의 이벤트가 발생했을때 콘솔에 찍힌 이벤트 내용은 다음과 같다.

          • e.data로 녹화한 video data를 얻을 수 있음.

            BlobEvent {isTrusted: true, data: Blob, timecode: 1635443942261.594, type: 'dataavailable', target: MediaRecorder,}
            isTrusted: true
            bubbles: false
            cancelBubble: false
            cancelable: false
            composed: false
            currentTarget: MediaRecorder {stream: MediaStream, mimeType: 'video/x-matroska;codecs=avc1,opus', state: 'inactive', onstart: null, onstop: null,}
            data: Blob {size: 5026, type: 'video/x-matroska;codecs=avc1,opus'}
            defaultPrevented: false
            eventPhase: 0
            path: []
            returnValue: true
            srcElement: MediaRecorder {stream: MediaStream, mimeType: 'video/x-matroska;codecs=avc1,opus', state: 'inactive', onstart: null, onstop: null,}
            target: MediaRecorder {stream: MediaStream, mimeType: 'video/x-matroska;codecs=avc1,opus', state: 'inactive', onstart: null, onstop: null,}
            timeStamp: 5154.80000000447
            timecode: 1635443942261.594
            type: "dataavailable"
            [[Prototype]]: BlobEvent
    1. 얻은 e.data로 녹화한 video 미리보기 만들기
      • URL.createObjectURL(e.data)을 이용하여 녹화한 video의 파일에 접근할 수 있는 URL을 가져 올 수 있다.
        const handleStop = () => {
          startBtn.innerText = "Download Recording";
          startBtn.removeEventListener("click", handleStop);
          startBtn.addEventListener("click", handleDownload);
          recorder.stop();
        };
        
        const handleStart = () => {
          startBtn.innerText = "Stop Recoding";
          startBtn.removeEventListener("click", handleStart);
          startBtn.addEventListener("click", handleStop);
          recorder = new MediaRecorder(stream);
          recorder.ondataavailable = e => {
            console.log(e);
            const videoFile = URL.createObjectURL(e.data);
            video.srcObject = null;
            video.src = videoFile;
            video.loop = true;
            video.play();
          };
          recorder.start();
        };
    2. video Download기능 만들기
      • a tag에 download기능이 있으므로 a tag를 만들고 href로 videoFile을 줘서 강제로 click하게 하면 download가 된다.
        • a.download = "My Recording.webm"로 해주면 다운로드 할 때 파일 이름이 My Recording.webm로 된다.

        • a.href로 videoFile을 주기위해 videoFile을 전역변수로 만들어줘야 한다.

          const startBtn = document.getElementById("startBtn");
          const video = document.getElementById("preview");
          
          let stream;
          let recorder;
          let videoFile;
          
          const handleDownload = () => {
            const a = document.createElement("a");
            a.href = videoFile;
            a.download = "My Recording.webm";
            document.body.appendChild(a);
            a.click();
          };
          
          const handleStop = () => {
            startBtn.innerText = "Download Recording";
            startBtn.removeEventListener("click", handleStop);
            startBtn.addEventListener("click", handleDownload);
            recorder.stop();
          };
          
          const handleStart = () => {
            startBtn.innerText = "Stop Recoding";
            startBtn.removeEventListener("click", handleStart);
            startBtn.addEventListener("click", handleStop);
            recorder = new MediaRecorder(stream);
            recorder.ondataavailable = e => {
              console.log(e);
              videoFile = URL.createObjectURL(e.data);
              video.srcObject = null;
              video.src = videoFile;
              video.loop = true;
              video.play();
            };
            recorder.start();
          };
          
          const init = async () => {
            stream = await navigator.mediaDevices.getUserMedia({
              audio: true,
              video: { width: 200, height: 100 },
            });
            video.srcObject = stream;
            video.play();
          };
          
          init();
          
          startBtn.addEventListener("click", handleStart);

0개의 댓글