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

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

by 카레유 2021. 12. 8.

이번 글은 자바스크립트의 Media Capture and Streams API이용해

아래의 MediaStream을 취득해서 동시 재생하는 예제 코드를 정리한다.

 

1. 마이크 소리

2. 카메라 영상

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

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

5. <canvas> 화면

 

▼MediaStream, MediaStreamTrack의 원리는 아래 글 참고▼

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


1. 마이크 소리

- 마이크 MediaStream 취득 방법:  navigator.mediaDevices.getUserMedia({audio: true})

 

마이크로 입력되는 소리를 MediaStream으로 취득하고, <audio>태그로 재생하는 예제 코드이다.

주의할 점은 getUserMedia()는 서버 배포시, https에서만 작동한다는 것이다.(그냥 PC에서 실행하는건 괜찮다)

설명은 주석으로 상세하게 달았다.

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

    <!-- 오디오 엘리먼트 -->
    <audio controls></audio>
    
</body>

<script>
    // audio 엘리먼트 취득
    const $audio = document.querySelector("audio");

    // 마이크 MediaStream 취득(audio를 true로 설정)
    navigator.mediaDevices.getUserMedia({audio: true})
    .then((mediaStream)=>{
        // Promise이므로 then으로 받아서 사용(async/await를 사용해도 된다.)

        // 마이크에서 입력받은 MediaStream으로 오디오 재생
        $audio.srcObject = mediaStream;
        $audio.onloadedmetadata = (event)=>{
            $audio.play();
        }
    })
    .catch((err)=>{
        console.error(`에러 발생: ${err}`);
    });
</script>

</html>

 

- 실행 결과: 마이크 사용 권한 허용 후, 목소리를 내면 실시간으로 재생된다(하울링 주의)


2. 카메라 영상

- 카메라 MediaStream 취득 방법:  navigator.mediaDevices.getUserMedia({video: true})

 

카메라로 입력되는 영상을 MediaStream으로 취득해 Video태그로 재생한다.

video: true; audio: false;로 설정하면 무음 영상을 취득한다. 소리도 함께 취득하려면 audio: true;로 설정하면 된다.

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

    <!-- 비디오 엘리먼트 -->
    <video controls></video>
    
</body>

<script>
    // video 엘리먼트 취득
    const $video = document.querySelector("video");

    // 카메라 MediaStream 취득(video만 true로 설정)
    navigator.mediaDevices.getUserMedia({audio: false, video: true})
    .then((mediaStream)=>{
        // Promise이므로 then으로 받아서 사용(async/await를 사용해도 된다.)

        // 카메라에서 입력받은 MediaStream으로 영상 재생
        $video.srcObject = mediaStream;
        $video.onloadedmetadata = (event)=>{
            $video.play();
        }
    })
    .catch((err)=>{
        console.error(`에러 발생: ${err}`);
    });
</script>
</html>

 

- 실행결과: 카메라 사용권한 허용하면, 카메라에 입력되는 영상이 실시간으로 재생된다.


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

- <audio>태그 MediaStream 취득 방법:  HTMLMediaElement.captureStream()

 

<audio> 태그에서 재생 중인 오디오를 MediaStream으로 입력 받아 그대로 동시 재생하는 코드다.

사실상 이렇게 사용할 일은 없을 듯하다.

 

주의할 점은 CORS정책 때문에 아래의 HTML코드에서 오디오 파일을 정상적으로 로드하지 못한다는 것이다.

서버 환경에서 실행되어야 하는데, VSCode 환경이라면 Live Server를 이용해 구동해주면 된다.

▼설치 및 실행 방법은 아래 글을 참고하자▼

[JS] VS Code로 HTML, JavaScript 개발 환경 구축/실행(@맥, 윈도우)

 

아래 코드에서 사용한 caputreStream()메서드도 브라우저별 지원 여부를 확인해야 한다.(크롬은 되는데 사파리는 안 되는듯)

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>audio엘리먼트 mediaStream</title>
</head>
<body>

    <!-- 여기서 오디오 파일을 재생하고-->
    <audio id="audioFile" src="./sample_audio.mp3">파일 재생용(컨트롤X)</audio>
    
    <!-- 여기서 mediaStream으로 받아서 동시 재생한다 -->
    <audio id="audioStream" controls>MeidaStream 취득 재생용(컨트롤O)</audio>
    
    <button id="btnStart">시작</button>

</body>
<script>
    // <audio> 엘리먼트 취득
    const $audioFile = document.getElementById("audioFile");
    const $audioStream = document.getElementById("audioStream");

    // <button> 엘리먼트 취득
    const $button = document.getElementById("btnStart");

    // 버튼 클릭시, 오디오 파일을 재생하고, 스트림을 취득하여 동시 재생한다.
    $button.onclick = (event)=>{
        // 오디오 파일 재생: 오디오가 재생 중이어야 스트림이 나온다.
        $audioFile.play();
            
        // 재생 중인 mediaStream 취득
        const mediaStream = $audioFile.captureStream();

        // 다른 오디오 태그에서 mediaStream을 받아서 동시 재생 처리
        $audioStream.srcObject = mediaStream;
        $audioStream.play();
    }


</script>
</html>

- 실행 결과:

시작 버튼을 누르면 음악 2개가 동시에 재생되어 울림이 발생한다.

1) 첫번째 audio태그의 파일 재생

2) 두번째 audio태그의 MediaStream재생

컨트롤을 붙여둔 두번째 audio태그의 정지(||) 버튼을 누르면 1개만 재생되어 울림이 발생하지 않는다.


4. <Video>태그에서 재생 중인 영상

- <video>태그 MediaStream 취득 방법:  HTMLMediaElement.captureStream()

 

<vidoe> 태그를 통해 재생중인 영상을 MediaStream으로 취득해서 동시 재생하는 코드다.

주의사항은 위의 <audio> 태그 사용 방법과 동일하다.(CORS, 브라우저 지원 여부)

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>video 엘리먼트 mediaStream</title>
</head>
<body>

    <!-- 여기서 비디오 파일을 재생하고 -->
    <video id="videoFile" src="./sample_video.mp4">파일 재생용(컨트롤X)</video>
    
    <!-- 여기서 MediaStream을 취득해 재생한다 -->
    <video id="videoStream" controls>MeidaStream 취득 재생용(컨트롤O)</video>
    
    <!-- 이 버튼을 누르면 시작한다 -->
    <button id="btnStart">시작</button>

</body>
<script>
    // <video> 엘리먼트 취득
    const $videoFile = document.getElementById("videoFile");
    const $videoStream = document.getElementById("videoStream");

    // <button> 엘리먼트 취득
    const $button = document.getElementById("btnStart");

    // 버튼 클릭시, 비디오 파일을 재생하고, 스트림을 취득하여 동시 재생한다.
    $button.onclick = (event)=>{
        // 비디오 파일 재생: 비디오가 재생 중이어야 스트림이 나온다.
        $videoFile.play();
            
        // 재생 중인 mediaStream 취득
        const mediaStream = $videoFile.captureStream();

        // 다른 비디오 태그에서 mediaStream을 받아서 동시 재생 처리
        $videoStream.srcObject = mediaStream;
        $videoStream.play();
    }


</script>
</html>

 

- 실행결과: 시작 버튼을 누르면 왼쪽에서 재생중인 영상을 받아, 오른쪽에서 동시 재생한다.


5. <canvas> 태그 화면

- <canvas>태그 MediaStream 취득 방법:  HTMLCanvasElement.captureStream()

 

<canvas> 태그에서 재생 중인 화면을 MediaStream으로 취득해 <video>태그로 재생하는 코드다.

100ms 간격으로 사각형을 그리는 캔버스의 화면을 그대로 동영상으로 재생한다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas MediaStream</title>
</head>
<body>
    <!-- canvas 태그 생성 -->
    <canvas id="canvas" width="1000" height="300" style="border: 1px solid black;"></canvas>
    <br><br>
    
    <!-- 버튼 생성 -->
    <button id="btn_start">녹화시작</button>
    <br><br>

    <!-- 비디오 태그 생성 -->
    <video id="video" controls style="border: 1px solid black;"></video>
    
</body>
<script>
    // 버튼, 비디오 태그 취득
    const $btn_start = document.querySelector("#btn_start");
    const $video = document.querySelector("#video");
    
    // 캔버스 및 그리기 객체 취득
    const $canvas = document.querySelector("#canvas");
    const ctx = $canvas.getContext('2d');

    // 버튼 클릭 처리
    $btn_start.onclick = (event)=>{
        // 캔버스에 그림 그리기
        drawCanvas(); 

        // 캔버스 영역 화면을 스트림으로 취득
        const mediaStream = $canvas.captureStream();
        console.log(mediaStream);

        // 비디오 태그에서 재생
        $video.srcObject = mediaStream;
        $video.onloadedmetadata = (event)=>{
            $video.play();
        }
    }

    let rectX = 0;
    function drawCanvas() {
        
        setInterval(() => {
            ctx.fillRect(rectX, $canvas.height/2, 10, 10);
            rectX += 20;
        }, 100);
    }


</script>
</html>

 

- 실행 결과: 시작 버튼을 누르면 canvas에서 100ms 간격으로 그려지는 사각형을 video태그에서 동영상으로 재생한다.


이상으로 

마이크, 카메라, <audio>, <video>, <canvas>에서 MediaStream을 취득하는 방법 정리를 마친다.

 

 

 

 

 

 

 

댓글