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

[자바스크립트] 캔버스(canvas) 화면 캡처/녹화 방법(+파일 저장 다운로드 구현)

by 카레유 2021. 12. 12.

자바스크립트는 <canvas> 태그의 화면을 캡처/녹화하는 방법을 제공한다.

예를 들어 캔버스에서 동작 중인 애니메이션을 녹화하여 동영상 등으로 저장할 수 있다.

 

작업 순서는 아래와 같다.

 

# canvas 태그 화면 캡처/녹화 방법

1. canvas태그 화면 스트림 취득

: HTMLCanvasElement.captureStream()=>MediaStream

 

2. 취득한 스트림을 저장

: MediaRecorder, Blob

 

3. 저장한 스트림을 재생 OR 동영상 파일로 저장(다운로드)

: BlobURL(ObjectURL)

 

먼저 canvas화면을 캡처하는 예제 코드 전문을 보고, 상세 설명을 정리한다.


# canvas 캡처/녹화 방법 - 코드 전문

 

- <canvas>태그의 화면을 녹화하여 <video>태그에서 재생하고, 동영상 파일로 다운로드 받는다.

<!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>
    <!-- 캔버스 -->
    <canvas id="canvas" width="1000" height="300" style="border: 1px solid black;"></canvas>
    <br><br>
    
    <!-- 버튼 -->
    <button id="btn_start">녹화시작</button>
    <button id="btn_stop">녹화종료</button>
    <br><br>

    <!-- 비디오: 녹화한 캔버스를 재생 -->
    <video id="video_recorded" controls style="border: 1px solid black;"></video>
  
</body>
<script>
    // 엘리먼트 취득
    const $canvas = document.querySelector("#canvas");
    const $btn_start = document.querySelector("#btn_start");
    const $btn_stop = document.querySelector("#btn_stop");
    const $video_recorded = document.querySelector("#video_recorded");

    // MediaRecorder(녹화기) 변수 선언
    let mediaRecorder = null;

    // 스트림 데이터를 담아둘 배열 생성
    const arrVideoData = [];


    // "녹화시작" 버튼 이벤트 처리
    $btn_start.onclick = (event)=>{
        // 캔버스에 그림 그리기: 100ms 마다 작은 사각형을 연달아 그린다.
        drawCanvas(); 

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

        // MediaRecorder(녹화기) 객체 생성
        mediaRecorder = new MediaRecorder(mediaStream);

        // MediaRecorder.dataavailable 이벤트 처리
        mediaRecorder.ondataavailable = (event)=>{
            // 스트림 데이터(Blob)가 들어올 때마다 배열에 담아둔다.
            arrVideoData.push(event.data);
        }

        // MediaRecorder.stop 이벤트 처리
        mediaRecorder.onstop = (event)=>{
            // 들어온 스트림 데이터들(Blob)을 통합한 Blob객체를 생성
            const blob = new Blob(arrVideoData);

            // BlobURL 생성: 통합한 스트림 데이터를 가르키는 임시 주소를 생성
            const blobURL = window.URL.createObjectURL(blob);

            // 재생 구현
            $video_recorded.src = blobURL;
            $video_recorded.play();

            // 다운로드 구현
            const $anchor = document.createElement("a"); // 앵커 태그 생성
            document.body.appendChild($anchor);
            $anchor.style.display = "none";
            $anchor.href = blobURL; // 다운로드 경로 설정
            $anchor.download = "test.webm"; // 파일명 설정
            $anchor.click(); // 앵커 클릭
            
            // 배열 초기화
            arrVideoData.splice(0);
        }

        // 녹화 시작
        mediaRecorder.start(); 
    }


    // "녹화종료" 버튼 이벤트 처리
    $btn_stop.onclick = (event)=>{
        // 캔버스에 그림 그리기 중단!
        stopCanvas();

        // 녹화 중단!
        mediaRecorder.stop(); 
    }




    // drawCanvas메서드: 100ms마다 20px 간격으로 사각형을 연달아 그린다.
    let intervalID = null;
    let rectX = 0;
    let rectY = $canvas.height/2;
    function drawCanvas() {
      // canvas 그리기 객체 취득 
      const ctx = $canvas.getContext('2d');

      // 반복 실행: 100ms마다 사각형 그리기
      intervalID = setInterval(() => {
        ctx.fillStyle = "blue";
        ctx.fillRect(rectX, rectY, 10, 10);
        rectX += 20;
      }, 100);
    }

    // stopCanvas메서드: 사각형 반복 그리기 중단
    function stopCanvas(){
      clearInterval(intervalID);
    }

</script>
</html>

 

- 실행 결과

1) "녹화시작" 하면 <canvas>영역에 사각형이 연달아 그려진다.

2) "녹화종료"하면 <canvas>영역을 녹화한 영상이 <video>태그에서 재생되고,

3) test.webm 파일로 다운로드 된다.


# canvas 캡처/녹화 방법 - 코드 설명

1. canvas 스트림 취득

 HTMLCanvasElement.captureStream() 

- canvas 객체의 captureStream()메서드를 호출하면

- canvas 영역에서 발생하는 화면 스트림을 MediaStream객체로 반환한다.

* 단, captureStream()메서드는 브라우저별 지원 여부 체크가 필요하다.(작성 시점 기준, safari에서는 작동하지 않았다)

 

2. 캡처/녹화

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

 

1) MediaRecorder 객체 생성

 new MediaRecorder(MediaStream

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

* MediaRecorder 는 브라우저별 지원 여부를 체크하고 사용해야 한다.(작성 시점 기준 safari는 작동X)

 

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이라고도 하며 생성된 웹페이지에서만 이용가능한 주소값이다.

 

 video.src = blobURL 

 video.play() 

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

 

 a.href = blobURL 

 a.download = "파일명" 

: BlobURL을 a태그의 href로 설정하고, download 속성에 파일명을 입력하면,

: Blob객체가 저장하고 있는 데이터를 파일로 다운로드할 수 있다.


▼코드에서 사용된 메서드와 객체들에 대한 상세 내용은 아래 글을 참고▼

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

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

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

 

▼canvas 자체에 대한 기초는 아래 글 참고▼

HTML Canvas(캔버스) 기초: 기본 사용 방법 & 샘플 예제 코드

 

▼마이크, 카메라를 통해 소리나 영상을 녹음/녹화하는 방법은 아래 글 참고▼

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

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

 

▼audio/video 태그에서 재생중인 오디오/비디오를 녹음/녹화하는 방법은 아래 글 참고▼

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

 

 

 

댓글