투케이2K

336. (javaScript) 자바스크립트 video 비디오 태그에 재생 중 인 stream 스트림 을 캔버스 화면 녹화로 저장 실시 - canvas record 본문

JavaScript

336. (javaScript) 자바스크립트 video 비디오 태그에 재생 중 인 stream 스트림 을 캔버스 화면 녹화로 저장 실시 - canvas record

투케이2K 2023. 10. 30. 18:24

[개발 환경 설정]

개발 툴 : Edit++

개발 언어 : JavaScript

 

[소스 코드]

 

    <!-- ===================================================================================================== -->
    <!-- [자바스크립트 코드 지정] -->
    <!-- ===================================================================================================== -->
    <script>


        // =======================================================================
        // [캔버스 비디오 재생 녹화 시작 중지 관련]
        // =======================================================================
        var interval; // [지속적으로 캔버스에 비디오 이미지 그림]
        var videoView; // [비디오 뷰]
        var canvas; // [캔버스]
        var recorder; // [녹화 영상 저장]
        const arrVideoData = []; // 스트림 데이터를 담아둘 배열 생성

        function startVideoPlay(){
            console.log("");
            console.log("=========================================");
            console.log("[startVideoPlay] : [start]");
            console.log("----------------------------------------");
            console.log("[설 명] : 비디오 재생 및 상태 감지");
            console.log("=========================================");
            console.log("");


            // [로직 처리 실시]
            try {

                // [비디오 재생 컴포넌트 지정]
                videoView = document.getElementById("videoView");


                // [캔버스 컴포넌트 지정]
                canvas = document.getElementById("canvas");


                // [캔버스 사이즈 지정 실시]
                var width = videoView.clientWidth;
                var height = videoView.clientHeight;
                canvas.height = height;
                canvas.width = width;


                // [캔버스 getContext 지정]
                var ctx = canvas.getContext("2d");


                // [비디오 재생 상태 감지 이벤트 리스너 등록]
                videoView.onerror = (event) => {
                    console.error("");
                    console.error("=========================================");
                    console.error("[startVideoPlay] : 원격 비디오 뷰 컴포넌트 : onerror");
                    console.error("=========================================");
                    console.error("");

                    // [인터벌 중지]
                    if (interval != null){

                        window.clearInterval(interval);
                        interval = null;

                    }

                };
                videoView.onwaiting = (event) => {
                    console.log("");
                    console.log("=========================================");
                    console.log("[startVideoPlay] : 원격 비디오 뷰 컴포넌트 : onwaiting");
                    console.log("=========================================");
                    console.log("");
                };
                videoView.onpause = (event) => {
                    console.error("");
                    console.error("=========================================");
                    console.error("[startVideoPlay] : 원격 비디오 뷰 컴포넌트 : onpause");
                    console.error("=========================================");
                    console.error("");

                    // [인터벌 중지]
                    if (interval != null){

                        window.clearInterval(interval);
                        interval = null;

                    }

                };
                videoView.onplaying = (event) => {

                    console.warn("");
                    console.warn("=========================================");
                    console.warn("[videoJsPlay] : 원격 비디오 뷰 컴포넌트 : onplaying");
                    console.warn("=========================================");
                    console.warn("");

                    // [캔버스 그리기]
                    if (ctx != null){

                        interval = window.setInterval(function() {

                          ctx.drawImage(videoView, 0, 0, canvas.width, canvas.height);

                        }, 10);

                    }
                };


                // [비디오 재생에 필요한 SRC 지정]
                videoView.setAttribute("src","https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"); // 동영상 주소


                // [비디오 재생 수행]
                videoView.play();


            }
            catch (error){

                // [에러 발생 내용 확인]
                console.error("");
                console.error("=========================================");
                console.error("[startVideoPlay] : [Exception]");
                console.error("--------------------------------------");
                console.error("[all error] : " + error);
                console.error("--------------------------------------");
                console.error("[error stack] : " + error.stack);
                console.error("=========================================");
                console.error("");


                // [에러 팝업창 표시]
                alert("[startVideoPlay] :: [Exception] :: " + error);

            }

        };



        function canvasRecordStart(){
            console.log("");
            console.log("=========================================");
            console.log("[canvasRecordStart] : [start]");
            console.log("----------------------------------------");
            console.log("[설 명] : 캔버스 비디오 녹화 시작");
            console.log("=========================================");
            console.log("");


            // [로직 처리 실시]
            try {


                // [실시간 영상 재생 여부 체크]
                if (interval == null){

                    // [에러 팝업창 표시]
                    alert("[canvasRecordStart] :: [Error] :: 비디오 재생 여부를 확인해 주세요");
                    return
                }


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


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


                // MediaRecorder.dataavailable 이벤트 처리
                mediaRecorder.ondataavailable = (event)=>{
                    console.log("[canvasRecordStart] : [add] : stream data");

                    // 스트림 데이터(Blob)가 들어올 때마다 배열에 담아둔다
                    arrVideoData.push(event.data);
                }


                // MediaRecorder.stop 이벤트 처리
                mediaRecorder.onstop = (event)=>{
                    console.log("");
                    console.log("=========================================");
                    console.log("[canvasRecordStart] : [onstop]");
                    console.log("----------------------------------------");
                    console.log("[설 명] : 캔버스 비디오 녹화 종료 >> 비디오 파일 저장 실시");
                    console.log("=========================================");
                    console.log("");

                    // 들어온 스트림 데이터들(Blob)을 통합한 Blob객체를 생성

                    const blob = new Blob(arrVideoData);


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


                    // 다운로드 구현
                    const anchor = document.createElement("a"); // 앵커 태그 생성
                    document.body.appendChild(anchor); // body 에 추가
                    anchor.style.display = "none";
                    anchor.href = blobURL; // 다운로드 경로 설정
                    anchor.download = "twok.webm"; // 파일명 설정
                    anchor.click(); // 앵커 클릭 >> 다운로드


                    // 배열 초기화
                    arrVideoData.splice(0);


                    // [팝업창 표시]
                    alert('캔버스 녹화가 종료 되었습니다.');


                }


                // MediaRecorder 녹화 시작
                mediaRecorder.start(1000);


                // [팝업창 표시]
                alert('캔버스 녹화가 시작 되었습니다.');

            }
            catch (error){

                // [에러 발생 내용 확인]
                console.error("");
                console.error("=========================================");
                console.error("[canvasRecordStart] : [Exception]");
                console.error("--------------------------------------");
                console.error("[all error] : " + error);
                console.error("--------------------------------------");
                console.error("[error stack] : " + error.stack);
                console.error("=========================================");
                console.error("");


                // [에러 팝업창 표시]
                alert("[canvasRecordStart] :: [Exception] :: " + error);

            }

        };



        function canvasRecordStop(){
            console.log("");
            console.log("=========================================");
            console.log("[canvasRecordStop] : [start]");
            console.log("----------------------------------------");
            console.log("[설 명] : 캔버스 비디오 녹화 종료");
            console.log("=========================================");
            console.log("");


            // [로직 처리 실시]
            try {

                // [실시간 영상 재생 여부 체크]
                if (interval == null){

                    // [에러 팝업창 표시]
                    alert("[canvasRecordStop] :: [Error] :: 비디오 재생 여부를 확인해 주세요");
                    return
                }


                // [미디어 레코드 널 체크]
                if (mediaRecorder == null){

                    // [에러 팝업창 표시]
                    alert("[canvasRecordStop] :: [Error] :: mediaRecorder Is Null");
                    return
                }
                else {
                    console.log("");
                    console.log("=========================================");
                    console.log("[canvasRecordStop] : [mediaRecorder]");
                    console.log("----------------------------------------");
                    console.log("[설 명] : 캔버스 비디오 녹화 종료 수행");
                    console.log("=========================================");
                    console.log("");

                    // [인터벌 중지]
                    if (interval != null){

                        window.clearInterval(interval);
                        interval = null;

                    }

                    // [비디오 재생 정지]
                    if (videoView != null){

                        videoView.pause();
                    }


                    // [녹화 중지 처리]
                    mediaRecorder.stop();
                }


            }
            catch (error){

                // [에러 발생 내용 확인]
                console.error("");
                console.error("=========================================");
                console.error("[canvasRecordStop] : [Exception]");
                console.error("--------------------------------------");
                console.error("[all error] : " + error);
                console.error("--------------------------------------");
                console.error("[error stack] : " + error.stack);
                console.error("=========================================");
                console.error("");


                // [에러 팝업창 표시]
                alert("[canvasRecordStop] :: [Exception] :: " + error);

            }

        };


    </script>







<body>

<!-- ===================================================================================================== -->
<!-- [body 생성] -->
<!-- ===================================================================================================== -->


<!-- ----------------------------------------------------------------------------------------------------- -->
<!-- 웹 화면 녹화 -->
<!-- ----------------------------------------------------------------------------------------------------- -->
<div class="divTagContentWidthLargeClass" style="height: 1px; background-color: #000000; top: 57%;"></div>

<!-- [비디오 컨테이너] -->
<div class="divTagContentWidthLargeClass" style="height: 5%; background-color: #ffffff; top: 59%; border: none;">
    <p class="pTagContentMiddleClass" style="color:#000;"> 비디오 뷰 </p>
</div>
<div class="divTagContentWidthLargeClass" style="height: 25%; background-color: none; top: 59%;">
    <video id="videoView" crossOrigin="anonymous" controls autoplay preload="auto" muted="muted" style="width: 100%; height: 100%; margin: 0 auto; padding: 0; position: relative; top: 0%; left: 0%;"></video>
</div>

<!-- [캔버스 컨테이너] -->
<div class="divTagContentWidthLargeClass" style="height: 5%; background-color: #ffffff; top: 60%; border: none;">
    <p class="pTagContentMiddleClass" style="color:#000;"> 캔버스 영역 </p>
</div>
<div class="divTagContentWidthLargeClass" style="height: 25%; background-color: none; top: 60%;">
    <canvas id="canvas" width="100%" height="100%"></canvas>
</div>

<!-- [비디오 재생 버튼] -->
<div class="divTagContentWidthLargeClass" style="height: 8%; background-color: #000000; top: 61%;"
     onclick="startVideoPlay();">
    <p class="pTagContentMiddleClass"> [startVideoPlay] 비디오 재생 실시 </p>
</div>


<!-- [캔버스 녹화 시작] -->
<div class="divTagContentWidthLargeClass" style="height: 8%; background-color: #000000; top: 62%;"
     onclick="canvasRecordStart();">
    <p class="pTagContentMiddleClass"> [canvasRecordStart] 캔버스 녹화 시작</p>
</div>


<!-- [캔버스 녹화 종료] -->
<div class="divTagContentWidthLargeClass" style="height: 8%; background-color: #000000; top: 63%;"
     onclick="canvasRecordStop();">
    <p class="pTagContentMiddleClass"> [canvasRecordStop] 캔버스 녹화 종료</p>
</div>


</body>

 

반응형
Comments