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

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

by 카레유 2021. 12. 3.

# 자바스크립트에서 미디어를 다루는 방법

자바스크립트에서 미디어를 다루는 주요 API는 4가지가 있다.

 

1. Media Capture and Streams API (=Meida Stream API)

- 마이크, 카메라 등을 이용해 들어오는 (Media Stream: 오디오, 비디오, 화면 등) 데이터를 다룬다.

 

2. MediaStream Recording API

- 미디어 스트림(Media Stream: 오디오, 비디오, 화면 등) 데이터를 녹음/녹화 한다.

 

3. Web Audio API

- 오디오 데이터를 처리/분석하는 API이다.

- 오디오 데이터로 사용될 수 있는 음원은 MediaStream(마이크 소리 등), 오디오 파일(mp3 등), 컴퓨터로 직접 만든 소리(Oscillator) 등이 있다.

 

4. Web RTC

- Web Real-Time Communication의 약자로, 브라우저 간에 데이터를 주고 받을 수 있게 해준다.

 

 

이번 글에서는 마이크, 카메라를 통해 들어오는 오디오, 비디오 스트림을 다루는

Media Capture and Streams API (=Meida Stream API)를 정리해본다.

 

▼스트림(Stream) 자체에 대한 내용은 아래 글을 참고해 보면 좋을 것 같다▼

스트리밍(Streaming)이란: 스트림(Stream), 버퍼(Buffer) 원리


# Media Capture and Streams API(=MeidaStream API)란?

Meida Stream API란 스트림 형태로 입출력되는 미디어(오디오, 비디오, 화면 등)을 다루는 API이다.

 

1. 오디오 스트림

1) 마이크로 입력되는 오디오 소리 스트림

2) <audio> 태그를 통해 재생중인 오디오 소리 스트림

 

2. 비디오 스트림

2) 카메라로 입력되는 비디오 영상 스트림

3) <video> 태그를 통해 재생 중인 비디오 영상 스트림

 

3. 화면 스트림

1) 브라우저 window 영역의 화면을 캡쳐하는 스트림

2) <canvas> 태그 영역의 화면을 캡처하는 스트림

 

위의 미디어 스트림들은 모두 MediaStream객체를 통해 입/출력된다.

먼저 MediaStream 객체에 대해 살펴보고, 각 스트림을 취득하여 다루는 방법을 정리해 보자.


# MeidaStream이란?

MediaStream이란 오디오, 비디오 같은 미디어 스트림을 다루는 객체이다.

마이크나 카메라를 통해 입력되는 소리와 영상 스트림, 그리고 브라우저의 화면은 모두 MediaStream객체를 통해 취득할 수 있다.

 

예를 들어 마이크에서 소리가 발생하면 브라우저는 MediaStream객체를 통해 소리 데이터를 입력 받는다.

개발자는 MediaStream객체를 통해 마이크로 입력되는 소리 데이터를 다룰 수 있게 된다.

 

주의할 점은 MediaStream객체는 한번 생성되면 계속 열려(?)있다는 점이다.

즉, 한번 카메라 영상을 입력받는 스트림이 열리면, 별도로 닫아주지 않는 한 계속해서 영상 데이터를 입력 받는다.

마찬가지로 한번 영상 스트림을 출력하면, 별도로 닫아주지 않는 한 계속해서 영상 데이터를 출력 한다.


# MeidaStream 생성 방법

MediaStream객체의 생성은 주로 아래의 2가지 방법이 사용된다.

주의할 점은 MediaStream 객체를 "여러 개" 생성하더라도 동일한 소스를 사용한다면 입력되는 "스트림은 동일"하다는 점이다. 

즉, 동일한 소스(마이크, 카메라, 화면 등)를 바라보는 스트림 "객체"만 여러 개 생성될 뿐이다.

 

1. MediaStream 생성자

생성자로 MediaStream 객체를 생성하는 방법이다.

 

1)  new MediaStream()  

: 비어있는 MediaStream 객체를 생성

 

2)  new MediaStream(MeidaStream객체)  

: 입력인자로 들어온 객체와 동일한 트랙을 갖는 MediaStream 객체 생성

: 두 MediaStrema객체는 동일한 스트림 source에 연결된다.

 

3)  new MediaStream([MeidaStreamTrack객체, ...])  

: 여러 개의 트랙을 조합한 MediaStream 객체 생성

 

 

그러나 생성자로 MediaStream객체를 생성할 일은 많치 않다.

MediaStream객체를 사용하는 이유는 마이크, 카메라, 화면에서 발생하는 스트림을 입력받기 위해서이다.

따라서 입력소스(마이크, 카메라, 화면 등)에서 바로 MediaStream을 받아서 사용하는 경우가 대부분이다.

 

 

2. 입력 소스에서 MediaStream 취득

입력 소스로 부터 MediaStream객체를 받아서 사용하는 방법이다.

 

1) 마이크, 카메라

 navigator.mediaDevices.getUserMedia() 

마이크, 카메라로 입력되는 오디오, 비디오 MediaStream 객체 생성

* MediaDevices 객체는 전역 객체 navigator.mediaDevices 로 참조할 수 있다.

* navigator.mediaDevices.getUserMedia 실제 배포 환경에서는 https에서만 작동한다.(localhost는 정상 작동)

 

2) <audio>, <video> 태그

-  HTMLMediaElement.captureStream() 

- <audio>, <video> 엘리먼트가 재생하는 오디오, 비디오의 MediaStream 객체 생성

* captureStream() 메서드는 브라우저별 지원여부를 확인 후 사용해야 한다.

 

3) <canvas> 태그

-  HTMLCanvasElement.captureStream() 

- <canvas> 영역에서 발생하는 화면 MediaStream 객체 생성

* canvas에서 그려지는 그림을 영상으로 캡쳐한다고 보면 된다.

 

4) 브라우저 화면

navigator.mediaDevices.getDisplayMedia() 

- 브라우저 winodw 일부 영역에 대한 화면 MediaStream 객체 생성

* 브라우저 화면에서 발생하는 내용을 영상으로 캡처한다고 보면 된다.

 

이 중에서 마이크, 카메라로부터 MediaStream을 취득하는 

navigator.mediaDevice.getUserMedia을 사용하는 방법을 알아보자(나머지는 다른 글에서 다루어볼 예정)


# MediaDevices.getUserMedia() 사용 방법

 navigator.mediaDevices.getUserMedia(MediaStreamConstraints

- 메서드가 호출되는 순간 사용자에게 마이크, 카메라 사용 권한(permission)을 요청 한다.

- 권한이 승인되면 마이크, 카메라에서 소리, 영상 스트림을 취득하여 Promise<MediaStream>을 반환한다.

- 입력인자(MediaTrackConstraints)로는 사용할 미디어 타입을 설정한다.

  ㄴ audio(마이크) : true | false

  ㄴ video(비디오) : true | false

 

예를 들어 마이크만 사용하는 MediaStream은 아래와 같이 생성한다.

navigator.mediaDevices.getUserMedia({
    audio: true,
    video: false
});

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

 

MediaTrackConstraints는 이 외에도 다양한 audio, video 관련 옵션을 줄 수 있다.

아래 코드는 해상도를 1280X720으로 조정한 셀카 카메라의 영상 MediaStream을 생성한다.

navigator.mediaDevices.getUserMedia({ 
    audio: true, 
    video: {
        width: 1280,
        height: 720,
        facingMode: "user" // 셀카 카메라 사용. 바깥쪽 카메라는 "environment"
    } 
});

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

 

 

아래 예제 코드는 노트북 카메라로 촬영되는 영상을 입력 받아 그대로 실시간으로 재생한다.

[샘플 코드 전문]

<!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>
     <!-- vidoe 태그 생성 -->
     <video controls></video>
 </body>
 
 <script>

    // video 태그 취득
    const $video = document.querySelector('video');
    
    // MediaStream 생성(마이크+카메라)
    navigator.mediaDevices.getUserMedia({
        audio: true, 
        video: true
    })
    .then(function(mediaStream) {
        // Promise이므로 then으로 받아서 처리
        
        // 입력받은 MediaStream을 그대로 video태그에 적용
        $video.srcObject = mediaStream;
        
        // 재생 처리
        $video.onloadedmetadata = function(e) {
            $video.play();
        };
    })
    .catch(function(err) { console.log(err.name + ": " + err.message); });
    
 </script>
 </html>

 

[실행 결과]

- 마이크, 카메라 사용 권한을 요청한다.

 

- 카메라로 촬영되는 영상이 실시간으로 재생된다

 

▼<audio>, <video>, <canvas> 태그의 MediaStream을 사용하는 예제 코드는 아래 글을 참고▼

[자바스크립트] MediaStream 예제 코드: 마이크, 카메라, audio, video, canvas

 


# MediaStreamTrack이란?

MediaStream을 구성하는 각 미디어 요소를 말한다.

MeidaStream은 여러 개의 MeidaStreamTrack객체로 구성된다.

예를 들어 자막이 있는 비디오 MediaStream은 3개의 MediaStreamTrack(영상 트랙, 소리 트랙, 자막 트랙)으로 구성된다.

 

MediaStream을 구성하는 각 MediaStreamTrack은 아래의 메서드들로 추출할 수 있다.

 

1)  MediaStream.getTracks() 

: MediaStream을 구성하는 모든 MediaStreamStrack 들을 배열로 반환한다.

 

2)  MediaStream.getAudioTrack() 

: MediaStream을 구성하는 오디오 MediaStream을 반환한다.

 

3)  MediaStream.getVideoTrack() 

: MediaStream을 구성하는 비디오 MediaStream을 반환한다.

 

 

추출된 MediaStreamTrack 들은

new MediaStream([MediaStreamTrack, ... ]) 생성자를 이용해 조합할 수 있다.

 

const newMeidaStream = new MediaStream([오디오MediaStreamTrack, 비디오MediaStreamTrack, ...]);

 

예를 들면, 

카메라로 들어온 MediaStream은  비디오MediaStreamTrack과 오디오 비디오MediaStreamTrack으로 구성된다.

여기서 비디오MediaStreamTrack만 추출하여 새로운 MediaStream 생성하면, 무음 영상 MediaStream 만들 있다.

<!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>
     <!-- vidoe 태그 생성 -->
     <video controls></video>
 </body>
 
 <script>

    // video 태그 취득
    const $video = document.querySelector('video');
    
    // MediaStream 생성(마이크+카메라)
    navigator.mediaDevices.getUserMedia({
        audio: true, 
        video: true
    })
    .then(function(mediaStream) {
        // Promise이므로 then으로 받아서 처리
        
        // MediaStream 에서 비디오, 오디오 MediaStreamTrack 각각 추출
        const videoTracks = mediaStream.getVideoTracks()
        const audioTracks = mediaStream.getAudioTracks()
        
        // 비디오 MediaStreamTrack으로만 구성된 새로운 MediaStream 생성(무음 영상)
        const mediaStreamAudioX = new MediaStream(videoTracks);
        
        // 입력받은 MediaStream을 그대로 video태그에 적용
        $video.srcObject = mediaStream;
        
        // 재생 처리
        $video.onloadedmetadata = function(e) {
            $video.play();
        };
    })
    .catch(function(err) { console.log(err.name + ": " + err.message); });
    
 </script>
 </html>

# 레퍼런스

더 자세한 내용은 아래의 MediaStream관련 레퍼런스를 참고하자.

 

- Media: https://developer.mozilla.org/en-US/docs/Web/Media

- MediaStream API: https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API

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

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

- MediaDevice: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices

- MediaDevice.getUserMedia: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia

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

- MediaDevices.getDisplayMedia() : https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia

- HTMLCanvasElement.captureStream(): https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream

- HTMLMediaElement.captureStream():  https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/captureStream


# MediaStream의 사용용도

MediaStream은 상황에 따라 다양한 방식으로 사용할 수 있다.

 

입력 받은 영상이나 소리를 실시간으로 재생할 수도 있고, MediaRecording API를 사용해 녹음/녹화를 할 수도 있다.

특히 Web Audio API를 사용하면 마이크로 입력된 오디오 데이터(주파수, 볼륨 등)를 분석하거나 새로운 소리로 변조할 수도 있다.

 

각각의 사용 방법에 대해서도 정리해볼 계획이다.

 

▼Media Stream Recording API 에 대한 글▼

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

 

 

댓글