본문 바로가기
개발(Development)/Media(오디오&비디오 개발)

자바스트립트 Media Stream Recording API: MediaRecorder

by 카레유 2021. 12. 6.

Media Stream Recording API란 소리나 영상 등의 미디어 스트림을 녹음, 녹화하는 API이다.

이 글은 Media Stream Recording API에 대한 개념과 예제 코드를 정리한다.


# Media Stream Recording API란?

- Media Stream을 Recording 하는 API로 MediaRecorder객체 하나로 구성되어 있다.

- 즉, MediaStream객체를 통해 입력 받는 소리, 영상, 화면 등을 MediaRecorder객체로 녹음 및 녹화하는 API이다.

 

* 주의사항

- MediaRecorder 객체는 브라우저별 지원 여부 확인 필요(2021년 기준, Safari는 지원 안 되는 것으로 확인된다.)


# MediaRecorder로 녹음 및 녹화할 수 있는 것들

- MediaRecorder는 MediaStream객체로 입력받는 스트림(소리, 영상, 화면)을 녹음/녹화할 수 있다.

- MediaStream객체로 입력받을 수 있는 스트림은 아래와 같다.

  ㄴ 마이크 입력 소리

  ㄴ 카메라 입력 영상

  ㄴ <audio>태그에서 재생 중인 소리

  ㄴ <video>태그에서 재생 중인 영상

  ㄴ <canvas>태그에서 그려지는 그림

  ㄴ 브라우저 window 영역에서 그려지는 그림


# MediaStream을 취득하는 방법

1. 마이크

-  navigator.mediaDevice.getUserMedia()  : "마이크"로 입력받는 소리 스트림 취득

- 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia

 

2. 카메라

-  navigator.mediaDevice.getUserMedia()  : "카메라"로 입력받는 영상 스트림 취득

- 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia

 

3. <audio>태그

-  HTMLMediaElement.captureStream()  : <audio>엘리먼트에서 재생 중인 오디오 스트림 취득

- 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/captureStream

 

4. <video>태그

-  HTMLMediaElement.captureStream()  : <video>엘리먼트에서 재생 중인 비디오 스트림 취득

- 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/captureStream

 

5. <canvas>태그 

-  HTMLCanvasElement.captureStream()  : <canvas>엘리먼트 영역을 특정 시간 동안 녹화

- 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream

 

6. window 영역

-  MediaDevices.getDisplayMedia()  : 브라우저 화면의 지정된 영역을 특정 시간 동안 녹화

- 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia

 

* navigator.mediaDevice.getUserMedia는 실제 배포 환경에서는 https에서만 작동한다.

* captureStream() 메서드는 브라우저별 지원 여부 확인 필요

 

 

▼MediaStream 자체에 대한 자세한 내용은 아래 글을 참고하자.▼

자바스크립트 Media Capture and Streams API: MediaStream, MediaStreamTrack


# MediaRecorder로 미디어 데이터를 저장하는 방법

입력되는 소리나 영상은 한번에 쭉 들어오는게 아니기 때문에,

들어올 때마다 배열에 담아두고 마지막에 합쳐서 사용하는게 포인트다.

 

여기서는 간단하게 정리만 하고, 아래의 예제코드에서 실제 사용 방법을 다루어 보겠다.

 

1. MediaStream 객체 취득

- 마이크, 카메라, <audio>태그, <video>태그, <canvas>태그 등에서 MediaStream을 취득한다.

 

2. MediaRecorder 객체 생성

- 생성자:  new MediaRecorder(stream[, options]

- stream에는 취득한 MediaStream객체를 넣어주고, option에는 mime type 등을 넣어준다.

* MediaRecorder 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder

 

3. 녹화/녹음 시작

- 녹화/녹음 시작:  MediaRecorder.start()  메서드 호출

- 녹음/녹화가 시작된 이후, 이용 가능한 미디어 데이터가 들어올 때마다 dataavailabe 이벤트가 발생한다.

- 개발자는 ondataavailable 이벤트 핸들러에서 미디어 데이터 조각들을 배열에 담아 둔다.

 

4. 녹화/녹음 종료

- 녹화/녹음 종료:  MediaRecorder.stop()  메서드 호출

- 녹화/녹음이 종료되면 stop 이벤트가 발생한다.

- 개발자는 onstop 이벤트 핸들러에서 배열에 담아둔 미디어 데이터 조각들을 하나로 합쳐서 활용한다.

 

5. MediaRecorder.ondataavailable 이벤트 핸들러 정의

- 들어오는 미디어 데이터들은 이벤트 핸들러의 event.data에 Blob객체 형태로 입력된다.

- 개발자는 Blob객체를 취득할 때마다 배열에 담아 둔다.(나중에 합치기 위해)

* ondataavailable 레퍼런스: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/ondataavailable

 

6.  MediaRecorder.onstop 이벤트 핸들러 정의

- 녹화/녹음이 종료되면 배열에 담아 두었던 Blob들을 하나로 합친 통합 Blob객체를 만들어 활용한다.


# 예제 코드

1) 마이크로 입력되는 소리를 녹음하고,

2) 녹음이 종료되면 <audio>태그를 통해 재생하는 코드다.

* 테스트 환경: 크롬 브라우저 localhost

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>마이크 녹음</title>
</head>
<body>

    <button>시작/종료</button>
    <br><br>
    <audio controls>녹음된 소리를 재생할 audio 엘리먼트</audio>

</body>

<script>

    // audio, button 태그 취득
    const $audioEl = document.querySelector("audio");
    const $btn = document.querySelector("button");

    // 녹음 상태 체크용 변수
    let isRecording = false;

    // MediaRecorder 변수 생성
    let mediaRecorder = null;

    // 녹음 데이터(Blob) 조각 저장 배열
    const audioArray = [];


    // 녹음 시작/종료 버튼 클릭 이벤트 처리
    $btn.onclick = async function (event) {
        
        // 녹음 중이 아닌 경우에만 녹음 시작 처리
        if(!isRecording){

            // 마이크 mediaStream 생성: Promise를 반환하므로 async/await 사용
            const mediaStream = await navigator.mediaDevices.getUserMedia({audio: true});

            // MediaRecorder 생성: 마이크 MediaStream을 인자로 입력
            mediaRecorder = new MediaRecorder(mediaStream);

            // 이벤트핸들러: 녹음 데이터 취득 처리
            mediaRecorder.ondataavailable = (event)=>{
                audioArray.push(event.data); // 오디오 데이터가 취득될 때마다 배열에 담아둔다.
            }

            // 이벤트핸들러: 녹음 종료 처리 & 재생하기
            mediaRecorder.onstop = (event)=>{
                
                // 녹음이 종료되면, 배열에 담긴 오디오 데이터(Blob)들을 합친다: 코덱도 설정해준다.
                const blob = new Blob(audioArray, {"type": "audio/ogg codecs=opus"});
                audioArray.splice(0); // 기존 오디오 데이터들은 모두 비워 초기화한다.
                
                // Blob 데이터에 접근할 수 있는 객체URL을 생성한다.
                const blobURL = window.URL.createObjectURL(blob);

                // audio엘리먼트로 재생한다.
                $audioEl.src = blobURL;
                $audioEl.play();

            }

            // 녹음 시작
            mediaRecorder.start();
            isRecording = true;

        }else{
            // 녹음 종료
            mediaRecorder.stop();
            isRecording = false;
        }
    }


</script>

</html>

 

- 실행 결과: 

1) 마이크 사용 권한 허용 후,

2) 시작/종료 버튼을 눌러 목소리를 녹음하고,

3) 시작/종료 버튼을 다시 눌러 녹음을 종료하고,

4) audio태그의 재생(삼각형)버튼을 누르면 녹음된 목소리가 재생된다.

(처음엔 자동 재생된다)

 

 

위의 코드를 이해하기 위해서는 Blob, 객체URL 등에 대한 지식이 필요하다.

 

▼이에 대해서는 아래 글을 참고하자.▼

자바스크립트 File API 파헤치기: Blob, File, FileReader, FileList, BlobURL


# 레퍼런스

MediaRecording API는 레퍼런스가 쉽고 상세하게 잘 정리되어 있는 편이니 참고하자.

 

- MediaRecording API: https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API

- MediaRecording API 사용법: https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API/Using_the_MediaStream_Recording_API

- MediaRecorder 객체: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder

 

 

 

댓글