투케이2K

222. (TWOK/WORK) [업무 이슈] AWS Kvs HLS getHLSStreamingSessionURL 호출 시 타이밍 이슈 발생으로 API 에러 발생 및 재시도 문의 본문

투케이2K 업무정리

222. (TWOK/WORK) [업무 이슈] AWS Kvs HLS getHLSStreamingSessionURL 호출 시 타이밍 이슈 발생으로 API 에러 발생 및 재시도 문의

투케이2K 2026. 6. 7. 16:25
728x90
반응형

[제 목]

주제 : 투케이2K 업무 정리

타이틀 : 투케이 / 2k / 업무 정리

제목 : [업무 이슈] AWS Kvs HLS getHLSStreamingSessionURL 호출 시 타이밍 이슈 발생으로 API 에러 발생 및 재시도 문의

 

[내 용]

 

------------------------------------------------------------------------------
[개발 및 테스트 환경]
------------------------------------------------------------------------------

- 제 목 : [개선 요청] AWS Kvs HLS getHLSStreamingSessionURL 호출 시 타이밍 이슈 발생으로 API 에러 발생 및 재시도 문의


- 테스트 환경 : AWS / Kvs / HLS / Viewer


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

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

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


- 사전) 👉 HLS 개념 설명 : 

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

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

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

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


- 사전) 👉 PlaybackMode 설명 : 

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

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





------------------------------------------------------------------------------
[이슈 사항]
------------------------------------------------------------------------------

1. 🟥 AWS Kinesis Video Streams (KVS) HLS 스트리밍 환경에서 타이밍 이슈로 인해 getHLSStreamingSessionURL() 호출이 일시적으로 실패하는 경우가 보완 로직 구현 필요 이슈


2. 🟥 AWS KVS getHLSStreamingSessionURL() 호출 시 실패할 수 있는 원인 정리

  >> Fragment 인덱싱 지연 : Producer 가 KVS 에 영상을 업로드한 직후에는 실제 영상 데이터는 이미 업로드되고 있어도 Fragment 인덱싱 완료 전 상태라면 실패할 수 있습니다.

  >> Stream 생성 직후 : Stream 생성 직후 바로 PutMedia 를 하는 경우 GetDataEndpoint , GetHLSStreamingSessionURL 이 내부적으로 아직 준비되지 않은 상태일 수 있습니다.

  >> Live Edge 생성 전 : PlaybackMode.LIVE 사용 시 최소 몇 개 Fragment 가 쌓여야 HLS Playlist 가 생성됩니다.

  >> AWS 내부 Eventually Consistent 특성 : KVS 도 완전한 Strong Consistency 기반 서비스는 아닙니다. 상황이 간헐적으로 발생할 수 있습니다.


3. 🟥 기존) 자바스크립트 AWS KVS getHLSStreamingSessionURL() 호출 후 에러 발생 로직 처리 코드

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

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

  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);

        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");								
    }
    
  })

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





------------------------------------------------------------------------------
[원인 파악 및 증상 재현]
------------------------------------------------------------------------------


1. 🟥 디바이스 기기 Producer 가 KVS 에 영상을 업로드 수행 실시 (PutMedia)


2. 🟥 앱 및 웹 뷰어에서 즉시 getHLSStreamingSessionURL 호출을 통해서 HLS 영상 시청 요청 수행


3. 🟥 getHLSStreamingSessionURL API 에서 Error 에러 코드가 반환 되는 것 확인

  >> AWS 콘솔 대시보드에서 확인 시에는 영상이 정상적으로 출력 되는 것 확인

  >> 앱 및 뷰어에서 즉시 getHLSStreamingSessionURL 호출 시 타이밍 문제로 인해 에러 코드가 반환 되는 것 확인

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






------------------------------------------------------------------------------
[조치 내용]
------------------------------------------------------------------------------

1. 🟦 앱 및 웹 뷰어에서 getHLSStreamingSessionURL API 호출 후 에러가 발생한 경우 일정 횟수 재시도 요청 로직 추가 보완


2. 🟦 자바스크립트 소스 코드 getHLSStreamingSessionURL API 보완 된 소스 코드 첨부 : 

kinesisVideoArchivedMedia.getHLSStreamingSessionURL( params , function(err, response){
  if (err){
    console.error("[getLiveHLSUrl] : [getHLSStreamingSessionURL] : ❌ 예외 상황 발생 : ", err.message);

    // [1번 더 재시도 수행]
    if (retryCnt < 6){

      retryCnt ++; // 카운트 증가
    
      console.error("[getLiveHLSUrl] : [Error] : 타이머 대기 및 재시도 수행 : ", retryCnt);                          

      // ✅ 5초 (5000ms) 대기 후 함수 실행
      setTimeout(() => {
        getLiveHLSUrl(region, endpoint, accessKeyId, secretAccessKey, streamName, hlsStreamType);
      }, 5000);

    }
    else {
      
      // -----------------------------------------
      // [에러 알림]
      // -----------------------------------------
      var errMsg = err.message;

      if (errMsg.indexOf("No fragments found in the stream for the streaming request") >= 0){
        errMsg += "\n\n" + "현재 재생 되고 있는 스트리밍이 없습니다. 스트리밍 재생 여부를 다시 확인해주세요." + "\n";
      }

      console.error("[getLiveHLSUrl] : [Error] : ", errMsg);

      return;

    }

  }

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

  const hlsUrl = response.HLSStreamingSessionURL;

  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);

      hls.on(Hls.Events.ERROR, function(event, data){
        console.error("");
        console.error("=========================================");
        console.error("[getLiveHLSUrl] : [getHLSStreamingSessionURL] : ❌ Hls.Events.ERROR");
        console.error("-----------------------------------------");
        console.error("[ERROR] : ", JSON.stringify(data));
        console.error("-----------------------------------------");
        console.error("[data.type] : ", data.type);
        console.error("-----------------------------------------");
        console.error("[data.details] : ", data.details);
        console.error("-----------------------------------------");
        console.error("[data.fatal] : ", data.fatal);
        console.error("=========================================");
        console.error("");

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

      });

    }
    else {
      console.error("[getLiveHLSUrl] : [Error] : ❌ Hls.isSupported False");
    }

  }
  else {
    console.error("[getLiveHLSUrl] : [Error] : ❌ HLSStreamingSessionURL Is Null");
  }

})
            
------------------------------------------------------------------------------





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

▶️ [Web/JavaScript] [기능 보완] 자바스크립트 AWS Kvs HLS 뷰어 Viewer 비디오 스트림 영상 재생 수행 유틸 - 재시도 적용

https://kkh0977.tistory.com/8900

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


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

https://kkh0977.tistory.com/7956

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


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

https://kkh0977.tistory.com/8276

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


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

https://kkh0977.tistory.com/8098

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


▶️ [JavaScript] The FragmentSelector is required for LIVE_REPLAY PlaybackMode

https://kkh0977.tistory.com/8256

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


▶️ [JavaScript] No fragments found in the stream for the streaming request

https://kkh0977.tistory.com/8257

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

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