투케이2K

165. (TWOK/UTIL) [Web/JavaScript] AWS Kvs HLS 뷰어 Viewer 비디오 스트림 영상 재생 수행 본문

투케이2K 유틸파일

165. (TWOK/UTIL) [Web/JavaScript] AWS Kvs HLS 뷰어 Viewer 비디오 스트림 영상 재생 수행

투케이2K 2025. 9. 12. 08:44
728x90

[설 명]

프로그램 : Web / JavaScript

설 명 : [Web/JavaScript] AWS Kvs HLS 뷰어 Viewer 비디오 스트림 영상 재생 수행

 

[소스 코드]

-----------------------------------------------------------------------------------------
[사전 설명 및 설정 사항]
-----------------------------------------------------------------------------------------

- 개발 환경 : Web


- 개발 기술 : JavaScript (자바스크립트) / AWS / Kvs / HLS / Viewer


- 사전) 비디오 스트림 간략 설명 정리 : 

  >> 비디오 스트림은 라이브 비디오 및 기타 시간이 인코딩된 데이터를 캡처하고, 선택적으로 저장하고, 실시간, 배치 혹은 애드혹 형식으로 데이터의 소비를 가능하게 할 수 있도록 해 주는 리소스입니다

  >> 일반적인 구성에서는 Kinesis 비디오 스트림은 데이터를 푸시해 주는 생산자가 하나만 있습니다 (실시간 스트리밍 데이터를 밀어 넣어주는 하드웨어 기기)


- 사전) HLS 개념 설명 : 

  >> HTTP 라이브 스트리밍으로 인터넷을 통해 소비자에게 미디어 콘텐츠를 제공하는 데 사용되는 스트리밍 프로토콜입니다

  >> HLS 는 Apple 장치에서 지원하는 유일한 형식입니다

  >> 미디어는 h.264 또는 h.265 인코딩된 비디오를 포함해야 하며 AAC 인코딩된 오디오는 선택 사항입니다

  >> 미디어 타입 유효한 값의 예로는 "video/h264" 및 "video/h264,audio/aac" 가 있습니다


- 사전) PlaybackMode 설명 : 

  >> 라이브, 라이브 재생 또는 아카이브된 온디맨드 데이터를 검색할지 여부입니다

-----------------------------------------------------------------------------------------





-----------------------------------------------------------------------------------------
[소스 코드]
-----------------------------------------------------------------------------------------

<!DOCTYPE HTML>
<html lang="ko">
<head>
    <title>javaScriptTest</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">


    <!-- 반응형 구조 만들기 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">


    <!-- 내부 CSS 스타일 지정 -->
    <style>

        html, body {
            width: 100%;
            height: 100%;
            margin : 0 auto;
            padding : 0;
            border : none;
            background-color: #666;
        }


        #container_remoteView {
            width: 100%;
            height: 98%;
            margin: 0 auto;
            position: relative;
            top: 1%;
        }
        #remoteView {
            width: 100%;
            height: 100%;
            margin: 0 auto;
            background-color: #666;
        }


        .swal-custom-width { width: 280px !important; }
        .swal-footer { text-align: center; }
        .swal-modal { text-align: center; }
        .swal-text { text-align: center; }

    </style>





    <!-- [CDN 주소 설정] -->
    <script src="https://code.jquery.com/jquery-latest.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>

    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.1560.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>






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

        // --------------------------------------------------------------------------------------------------------------

        // [전역 변수 선언]
        var kinesisVideoClient = null;

        var region = 'ap-northeast-1'; // [AWS 리전]
        var accessKeyId = 'AK..7Q'; // [IAM 액세스 키]
        var secretAccessKey = 'Zz..xj'; // [IAM 시크릿 키]
        var streamName = 'DEVICE_1'; // [스트림 명칭]

        // --------------------------------------------------------------------------------------------------------------

        // [html 최초 로드 및 이벤트 상시 대기 실시]
        window.onload = async function() {

            // -----------------------------------------
            // [JSON 데이터 삽입 수행]
            // -----------------------------------------            
            var webJson = {
                region : region,
                accessKeyId : accessKeyId,
                secretAccessKey : secretAccessKey,
                streamName : streamName
            };

            setSystem(JSON.stringify(webJson)); 

        };

        // --------------------------------------------------------------------------------------------------------------

        async function setSystem(jsonData){
            console.log("[setSystem] : [Start] : ", JSON.stringify(jsonData));

            try {

                // -----------------------------------------
                // [json 데이터 파싱 수행 실시]
                // -----------------------------------------
                var jsonObject = JSON.parse(jsonData);

                var parse_region = String(jsonObject.region); // [AWS 리전]
                var parse_accessKeyId = String(jsonObject.accessKeyId); // [IAM 액세스 키]
                var parse_secretAccessKey = String(jsonObject.secretAccessKey); // [IAM 시크릿 키]
                var parse_streamName = String(jsonObject.streamName); // [비디오 스트림 명칭]


                // -----------------------------------------
                // [비디오 플레이 컴포넌트 지정 및 이벤트 지정]
                // -----------------------------------------

                const remoteView = document.getElementById("remoteView");
                remoteView.muted = true; // 웹 자바스크립트 : NotAllowedError 조치
                remoteView.autoplay = true; 
				

                //remoteView.onload = (event) => {};
                //remoteView.onchange = (event) => {};
                //*
                remoteView.onerror = (event) => {
                    console.error("[setSystem] : [remoteView] : 원격 비디오 뷰 컴포넌트 : onerror");
                };
                /*
                remoteView.onwaiting = (event) => { // [디바이스 스트리밍 송출 종료 시 로딩 프로그레스를 돌리기 위해 주석]
                    console.log("[setSystem] : [remoteView] : 원격 비디오 뷰 컴포넌트 : onwaiting");
                };
                // */
                remoteView.onpause = (event) => {
                    console.error("[setSystem] : [remoteView] : 원격 비디오 뷰 컴포넌트 : onpause");
                };
                remoteView.onplaying = (event) => {
                    console.log("[setSystem] : [remoteView] : 원격 비디오 뷰 컴포넌트 : onplaying");
                };
                // */
                // video.onplay = (event) => {};



                // -----------------------------------------
                // [KVS 클라이언트 생성]
                // -----------------------------------------
                kinesisVideoClient = new AWS.KinesisVideo({
                    region,
                    accessKeyId,
                    secretAccessKey,
                    correctClockSkew: true,
                });


                // -----------------------------------------
                // [KVS 스트림 엔드포인트 가져오기]
                // -----------------------------------------
                kinesisVideoClient.getDataEndpoint({
                  StreamName: streamName,
                  APIName: 'GET_HLS_STREAMING_SESSION_URL'
                }, function(err, response){
                  if (err){
                    console.error("[getDataEndpoint] : [ERROR] : ", JSON.stringify(err.message));
                    return;
                  }
					
                  console.log("[getDataEndpoint] : [response] : ", JSON.stringify(response));

                  const endpoint = response.DataEndpoint; // parsing endpoint

                  if (endpoint != null && endpoint != '' && endpoint != 'undefined'){

                    // -----------------------------------------
                    // [엔드포인트를 기반으로 HLS 세션 URL 가져오기]
                    // -----------------------------------------
                    const kinesisVideoArchivedMedia = new AWS.KinesisVideoArchivedMedia({
                      region: region,
                      endpoint: endpoint,
                      accessKeyId: accessKeyId,
                                secretAccessKey: secretAccessKey
                    });

                    const startTimestamp = new Date(Date.now() - 30 * 1000); // 과거 : 30초전

                    //const startTimestamp = new Date(Date.now() - 60 * 1000); // 과거 : 1분전
                    //const endTimestamp = new Date(); // 현재
                    //const endTimestamp = new Date(Date.now() + 60 * 1000); // 미래 : 1분후

                    kinesisVideoArchivedMedia.getHLSStreamingSessionURL({
                      StreamName: streamName,
                      //PlaybackMode: 'LIVE', // 가장 최신만 재생 (지연 최소, 끊김 위험 높음)

                      PlaybackMode: 'LIVE_REPLAY', // 이전 데이터 부터 재생을 하므로 끊김 최소화 : AWS 콘솔 대시보드도 동일 설정
                      HLSFragmentSelector: {
                        FragmentSelectorType: 'SERVER_TIMESTAMP', // 또는 PRODUCER_TIMESTAMP
                        TimestampRange: {
                          StartTimestamp: startTimestamp,
                          //EndTimestamp: endTimestamp // 디바이스가 올린 영상 종료까지 출력 위해 주석 : 주석하지 않으면 시작 ~ 종료 범위까지의 영상만 재생 됨
                        }
                      }
                      
                    }, function(err, response){
                      if (err){
                        console.error("[getHLSStreamingSessionURL] : [ERROR] : ", JSON.stringify(err.message));
                        return;
                      }

                      console.log("[getHLSStreamingSessionURL] : [response] : ", JSON.stringify(response));

                      const hlsUrl = response.HLSStreamingSessionURL; // parsing hls stream url

                      if (hlsUrl != null && hlsUrl != '' && hlsUrl != 'undefined'){
                        Hls.DefaultConfig.debug = true; // 디버깅 로그 출력
                        
                        if (Hls.isSupported()){ // Hls 지원 여부 확인

                          const hls = new Hls(); // Default

                          hls.loadSource(hlsUrl);
                          hls.attachMedia(remoteView);


                          // [비디오 AutoPlay 설정으로 주석 처리]
                          /*
                          hls.on(Hls.Events.MANIFEST_PARSED, function(){

                            remoteView.play();

                            console.log("[getHLSStreamingSessionURL] : Hls 스트리밍 재생 수행]");
                            
                          });
                          // */


                          hls.on(Hls.Events.ERROR, function(event, data){										
                            console.error("[getHLSStreamingSessionURL] : Hls.Events.ERROR : ", JSON.stringify(data));

                            // [에러 분기 처리 시 사용]
                            // if (data.details === 'bufferStalledError'){ }										
                            // if (data.details === 'bufferStalledError'){ }
                            
                          });

                        }
                        else {
                          console.error("[getHLSStreamingSessionURL] : [ERROR] : Hls.isSupported False");
                        }
                      }
                      else {
                        console.error("[getHLSStreamingSessionURL] : [ERROR] : HLSStreamingSessionURL Is Null");								
                      }
                      
                    })

                  }
                  else {
                    console.error("[getDataEndpoint] : [ERROR] : DataEndpoint Is Null");
                  }

               });
            }
            catch (exception) {
               console.error("[setSystem] : [Exception] : ", JSON.stringify(exception.message));
            }
        };

        // --------------------------------------------------------------------------------------------------------------


    </script>


</head>


<body>

<!-- [컨테이너 생성] -->
<div id="container_remoteView">
    <video autoplay="true" id="remoteView"></video>
</div>

</body>

</html>

-----------------------------------------------------------------------------------------





-----------------------------------------------------------------------------------------
[참고 사이트]
-----------------------------------------------------------------------------------------

[Aws Kinesis Video Streams] Aws KVS 비디오 스트림 , 신호 전송 채널 차이점 설명 정리

https://blog.naver.com/kkh0977/223854439046?trackingCode=blog_bloghome_searchlist


[Aws Kvs HSL 비디오 스트림 녹화 영상 관련 학습 정리]

https://blog.naver.com/kkh0977/223855980812?trackingCode=blog_bloghome_searchlist


[자바스크립트 AWS Kvs HLS 비디오 스트림 채널 생성 수행 - createStream]

https://blog.naver.com/kkh0977/223916957964


[자바스크립트 AWS Kvs HLS 비디오 스트림 채널 삭제 수행 - deleteStream]

https://blog.naver.com/kkh0977/223918327833

-----------------------------------------------------------------------------------------
 
728x90
반응형
Comments