# 13.0 -5 Recorder

이원규·2022년 7월 13일
0

Itube

목록 보기
39/46

-> 사람들이 버튼을 누르면 비디오 녹음이 시작됨. 5초로 제한을 둘거고, 5초가 지나면 녹화된 비디오를 다운받을 수 있게됨.

1. Setup - client/js/recoder.js생성 - 프론트엔드에서 vanillaJS로 만들 것임.

1.1 client/js/recoder.js생성

1.2 webpack에 추가

  • webpack
// entry에 추가
recorder : "./src/client/js/recorder.js",

1.3 upload.pug에 script추가 & 녹화 버튼 추가

// script선언해주기
block scripts 
    script(src="/assets/js/recorder.js")

//버튼 추가
block content
    div 
    	video#preview.hidden 
        button#startBtn.hidden Start Recording
        button#initBtn if u record video, Click here 

1.4 client/js/recoder.js작성

  • recoder.js
const startBtn = document.getElementById("startBtn");
const video = document.getElementById("preview")

const handleStart = async() => {
    const stream = await navigator.mediaDevices.getUserMedia({
        audio: true,
        video: {width:500, height:500},
    });
    video.srcObject = stream; // video에 stream넣어주기 -> stream이 object라서 video.src가 아니라 video.Object임.
    video.play();
};


startBtn.addEventListener("click", handleStart);
  1. MediaDevices.getUserMedia()
    MediaDevices 인터페이스의 getUserMedia() 메서드는 사용자에게 미디어 입력 장치 사용 권한을 요청하며, 사용자가 수락하면 요청한 미디어 종류의 트랙을 포함한 MediaStream (en-US)을 반환합니다. 스트림은 카메라, 비디오 녹화 장치, 스크린 공유 장치 등 하드웨어와 가장 비디오 소스가 생성하는 비디오 트랙과, 마이크, A/D 변환기 등 물리적과 가상 오디오 장치가 생성하는 오디오 스트림, 그리고 그 외의 다른 종류의 스트림을 포함할 수 있습니다.
    보통, MediaDevices 싱글톤 객체는 다음과 같이 navigator.mediaDevices를 사용해 접근합니다.
    navigator.mediaDevices.getUserMedia(constraints);

기본 사용법:

  1. constraints
    요청할 미디어 유형과 각각에 대한 요구사항을 지정하는 MediaStreamConstraints 객체. constraints 매개변수는 두 개의 구성 요소, video와 audio를 가지는 객체로, 요청할 미디어 유형에 대해 설명합니다. 둘 중 적어도 하나는 지정해야 합니다.
    { audio: true, video: true }

  2. regenerator-runtime
    Regenerator로 컴파일된 생성기 및 비동기 함수를 위한 독립 실행형 런타임입니다. -> async, await을 사용하기 위해 설치 및 import해줘야함.
    npm i regenerator-runtime

-> main.js에 import regeneratorRuntime from "regenerator-runtime"; 해주고 base.pug에 script(src="/assets/js/main.js") 추가

  1. HTMLMediaElement srcObject

HTMLMediaElement 인터페이스의 srcObject 속성은 HTMLMediaElement와 연결된 미디어의 소스 역할을 하는 객체를 설정하거나 반환합니다.
그 객체는 MediaStream, MediaSource, Blob 또는 파일(Blob에서 상속됨)일 수 있습니다.

사용 예시
이 예에서 카메라의 MediaStream은 새로 생성된 요소에 할당됩니다.

const mediaStream = await navigator.mediaDevices.getUserMedia({video: true});
const video = document.createElement('video');
video.srcObject = mediaStream;

2. Recording File & download

2.1 사용할 API들

  1. MediaRecorder
    MediaStream Recording API의 MediaRecorder 인터페이스는 미디어를 쉽게 녹화할 수 있는 기능을 제공합니다. MediaRecorder() 생성자를 사용하여 생성됩니다.

MediaRecorder()
기록할 MediaStream이 지정된 새 MediaRecorder 개체를 만듭니다.

  1. stream
    기록될 MediaStream입니다. 이 소스 미디어는 navigator.mediaDevices.getUserMedia()를 사용하여 생성된 스트림이나 audio, video 또는 canvas 요소에서 가져올 수 있습니다.

  2. MediaRecorder.start()
    미디어 녹화를 시작합니다. 이 메서드는 선택적으로 밀리초 단위의 값을 가진 타임슬라이스 인수를 전달할 수 있습니다.

  3. MediaRecorder.stop()
    저장된 데이터의 최종 Blob을 포함하는 dataavailable 이벤트가 발생하는 시점에서 기록을 중지합니다.

  4. MediaRecorder ondataavailable
    => MediaRecorder.stop()이 실행될 때 발생하는 이벤트이다. recording된 데이터에 접근할 수 있도록 해준다.

  1. URL.createObjectURL() : 브라우저 메모리에서만 가능한 URL을 만들어준다. 이 URL은 웹 상에 실제로 존재하지 않고, 브라우저의 메모리를 가리키기만 하는 URL임. => 그냥 파일을 가리키고 있는 URL. 즉 파일은 브라우저의 메모리 상에 있다는 것임.
    요약: 브라우저 메모리 상에 저장을 해두고, 우리가 그 파일에 접근할 수 있는 URL을 준거. 즉, 이 URL은 브라우저가 파일을 보여주는 형식.

URL.createObjectURL() 정적 메서드는 주어진 객체를 가리키는 URL을 DOMString으로 반환합니다. 해당 URL은 자신을 생성한 창의 document가 사라지면 함께 무효화됩니다.

=> 결과: 우리는 ondataavailable의 event.data를 이용할 것임.- > 여기에 파일이 들어가 있음.

  1. MediaStream.getTracks()

인터페이스의 getTracks()메서드는 에 관계없이 이 스트림의 모든 개체 MediaStream를 나타내는 시퀀스를 반환합니다.

2.2 client/scss/screens/upload.scss 만들기

.hidden {
    display: none;
}

2.3 recorder.js

-> 가짜 버튼 이용: a 안에 download가 있으면 href(url)로 이동하는게 아니라 href를 다운
a - download

const startBtn = document.getElementById("startBtn");
const initBtn = document.getElementById("initBtn");
const video = document.getElementById("preview");


let stream;
let recorder;
let videoFile;

const handleDownload = () => {
    const a = document.createElement("a");
    a.href = videoFile;
    a.download = "MyRecording.webm"; // href(url)을 다운로드 함. => 다운할 때 파일명을 넣어주면 됨.
    document.body.appendChild(a);
    a.click();
    const tracks = stream.getTracks();
    tracks.forEach((track) => {
        track.stop();
    });
    stream = null;
    video.src = null;
    startBtn.innerText = "Start Recording";
    startBtn.removeEventListener("click",handleDownload);
    startBtn.addEventListener("click", handleStart);
    startBtn.classList.add("hidden");
    video.classList.add("hidden");
    initBtn.classList.remove("hidden");
};

const handleStop = () => {
    startBtn.innerText = "Dowload Recording";
    startBtn.removeEventListener("click",handleStop);
    startBtn.addEventListener("click", handleDownload);
    recorder.stop();
};

const handleStart = () => {
    startBtn.innerText = "Stop Recording";
    startBtn.removeEventListener("click", handleStart);
    startBtn.addEventListener("click", handleStop);
    recorder = new window.MediaRecorder(stream);//stream을 record가능한 형태로 만들어줌.
    recorder.ondataavailable = (event) => {// recorder data에 접근함. / event를 감지함. event가 발생하면 다음의 것들이 실행됨. 이건 stop()일 떄 발생하므로 stop()되면 event발생 -> ondataavailable발생
        videoFile = URL.createObjectURL(event.data); // 브라우저 메모리 상에 저장을 해두고, 우리가 그 파일에 접근할 수 있는 URL을 준거.
        video.srcObject = null;
        video.src = videoFile;
        video.loop = true;
        video.play();
    };
    recorder.start();
};

const init = async() => {
    startBtn.classList.remove("hidden");
    video.classList.remove("hidden");
    initBtn.classList.add("hidden");
    stream = await navigator.mediaDevices.getUserMedia({
        audio: false,
        video: true,
    });
    video.srcObject = stream; // video에 stream넣어주기 -> stream이 object라서 video.src가 아니라 video.Object임.
    video.play();
};

initBtn.addEventListener("click", init);
startBtn.addEventListener("click", handleStart);
profile
github: https://github.com/WKlee0607

0개의 댓글