본문 바로가기
개발언어/자바스크립트

[자바스크립트] 마이크 음성 소리 녹음 방법 : MediaRecorder

by 창용이랑 2022. 2. 9.
728x90

 

별도 라이브러리 없이,

자바스크립트만으로 마이크로 입력 받는 오디오를 녹음하는 방법을 정리한다.

 

대략 아래와 같은 순서로 진행하면 된다.

 

1. 마이크 소리 입력: MediaStream

2. 입력된 소리 녹음: MediaRecorder

3. 녹음된 소리 재생: Blob, Audio

 

마이크 음성 녹음의 원리를 알기 위해서는

MediaStream, MediaRecorder, Blob 등에 대해 알아두면 좋다.

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

 

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

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

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

 

물론 위의 내용을 완벽히 모르더라도 구현은 가능하다.

개발자는 코드로 이해하는게 더 빠를 때도 많으니까.

그럼 시작하자.

# 마이크 음성 녹음 - 예제 코드 전문

자바스크립트에서 목소리를 녹음하는 코드 전문이다.

코드에 대한 상세 설명은 아래에서 다룬다.

<!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>

    // 엘리먼트 취득
    const $audioEl = document.querySelector("audio");
    const $btn = document.querySelector("button");

    // 녹음중 상태 변수
    let isRecording = false;

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

    // 녹음 데이터 저장 배열
    const audioArray = [];

    $btn.onclick = async function (event) {
        if(!isRecording){

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

            // MediaRecorder 생성
            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 데이터에 접근할 수 있는 주소를 생성한다.
                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) "audio태그"의 플레이 버튼을 누르면 녹음된 목소리가 재생된다.

위의 코드에 대한 상세 설명은 아래에서 정리한다.

# 마이크 음성 녹음 - 상세 설명

1. 소리 취득

 navigator.mediaDevices.getUserMedia({audio: true}

- 마이크가 입력 받는 소리는 MediaStream객체로 들어온다.

- 위의 getUserMedia()메서드를 호출하면, Promise<MediaStream> 형태로 소리 데이터가 들어온다.

* 단, getUserMedia()는 https 환경에서만 작동하니 주의하자!(로컬 환경에서 실행하는건 상관 없다) 

 

* Promise를 반환하므로 then()으로 받아서 사용하거나, async/await 구문을 사용해야 한다.

 

 

2. 소리 녹음

- MediaStream을 통해 들어오는 오디오 데이터는 MediaRecorder 객체를 통해 저장할 수 있다.

 

1) MediaRecorder 객체 생성

 new MediaRecorder(MediaStream

: getUserMedia()로 취득한 MediaStream을 인자로 넣어 생성자를 호출해준다.

 

2) 이벤트 핸들러 정의

 mediaRecorder.ondataavailable 

: 이용가능한 오디오 데이터가 들어올 때마다 호출된다.

: 데이터 조각들은 이벤트 핸들러의 인자 event.data(Blob객체)로 취득할 수 있다.

: 취득한 Blob객체들은 나중에 합치기 위해 배열 등에 저장해 둔다.

 mediaRecorder.onstop 

: 녹음이 종료되면 호출된다.

: 배열에 저장해둔 오디오 데이터(Blob)들을 합친다.

 

3) 녹음 시작

 mediaRecorder.start() 

: 녹음을 시작하는 메서드다.

: 녹음이 시작되면 이용가능한 데이터(Blob)가 들어올 때마다 dataavailabel이벤트가 호출된다.

 

4) 녹음 종료

mediaRecorder.stop()

: 녹음을 종료하는 메서드다.

: 녹음이 종료되면 stop이벤트가 호출된다.

 

3. 소리 재생

 window.URL.createObjectURL(Blob

: 통합한 오디오 데이터(Blob)를 BlobURL로 생성한다.

: BlobURL은 Blob객체가 저장하고 있는 데이터를 가르키는 임시 URL이다.

* BlobURL은 ObjectURL이라고도 하며 생성된 웹페이지에서만 이용가능한 주소값이다.

 

 audio.src = blobURL 

 audio.play() 

: BlobURL은 audio나 video태그의 src로 설정하여 재생 가능하다.

※ 주의 사항

1. 이 코드에서 사용되는 MediaRecorder는 브라우저별로 지원 여부를 확인해야 한다.

  - 글 작성 시점 기준으로 Chrome에서는 작동하나, Safari는 작동하지 않았다.

2. 이 코드에서 사용되는 getUserMedia()는 서버 환경에서는 https에서만 작동한다.

  - 개인 PC에서 html파일을 실행하는 경우엔 잘 작동한다.

 

 

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

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

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

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

 

▼브라우저 상에서 카메라로 비디오(동영상) 녹화하는 방법은 아래 글 참고▼

[자바스크립트] 카메라 영상 녹화 방법 (+무음 비디오 촬영)

 

▼audio, video 엘리먼트로 재생중인 소리/영상 녹화 방법은 아래 글 참고▼

[자바스크립트] audio/video 태그에서 재생 중인 소리/영상 녹음 방법



출처: https://curryyou.tistory.com/446 [카레유]