투케이2K

147. (TWOK/LOGIC) [android] 안드로이드 휴대폰 실시간 카메라 스트림 영상을 마스터 역할로 Aws Kvs HLS 라이브 스트리밍 업로드 로직 정리 본문

투케이2K 로직정리

147. (TWOK/LOGIC) [android] 안드로이드 휴대폰 실시간 카메라 스트림 영상을 마스터 역할로 Aws Kvs HLS 라이브 스트리밍 업로드 로직 정리

투케이2K 2025. 9. 5. 19:23
728x90
반응형

[로직 정리]

정리 로직 : Mobile

상태 : [android] 안드로이드 휴대폰 실시간 카메라 스트림 영상을 마스터 역할로 Aws Kvs HLS 라이브 스트리밍 업로드 로직 정리

 

[설 명]

// --------------------------------------------------------------------------------------
[사전) 설정 및 정보 확인 사항]
// --------------------------------------------------------------------------------------

1. 사전) 인프라 환경 구축 및 파일 준비 필요 사항

  >> Aws Kinesis Video Streams (Kvs) 인프라 구축 필요

    - IAM 계정 생성 (KVS 권한 할당) 및 AccessKey , SecretKey 생성 준비

  >> Aws 사이트에서 KVS HLS 비디오 스트림 채널 생성 필요 (테스트 고유 디바이스 스트림 명칭)

  >> Aws Kvs HLS 에 업로드 하려는 동영상 파일 (mp4) 준비 필요

  >> 재생 되고 있는 실시간 스트리밍 정보를 보기 위한 Viewer 뷰어 프로그램 준비 필요


2. 사전) 비디오 스트림 학습 : 

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

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


3. 사전) KVS 개념 학습 : 

  >> KVS 는 ML (기계 학습), 재생 및 기타 처리를 위해 커넥티드 디바이스에서 AWS로 비디오를 쉽고 안전하게 스트리밍할 수 있는 기술입니다


4. 사전) HLS 개념 학습 : 

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

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

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

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


5. 사전) PutMedia 개념 학습 : 

  >> Kinesis 비디오 스트림 전송 API 입니다. (미디어 데이터 전송)

  >> PutMedia 전송 시 파라미터에는 streamName 또는 streamARN 중 하나를 지정해야합니다


6. 사전) Signature V4 서명 학습 : 

  >> AWS API 요청에 인증 정보를 추가하기 위한 AWS 서명 프로토콜입니다

  >> HTTP Authorization 헤더에서 또는 URL의 쿼리 문자열로 표현될 수 있습니다


7. 사전) MKV 비디오 파일 학습 : 

  >> 멀티미디어 컨테이너 형식으로 여러 개의 오디오, 비디오, 자막 트랙을 하나의 파일에 포함할 수 있는 컨테이너 형식입니다

  >> MKV 편집이 가능한 프로그램 : 

    - DaVinci Resolve : 무료 + 고급 영상 편집 가능

    - VLC Media Player : 간단한 컷 편집 가능

    - FFmpeg : MKV 변환 & 편집 (커맨드 라인)

    - Avidemux : 간단한 트리밍 & 편집


8. 사전) FFMpecg (미디어 포맷 변환 도구) 학습 : 

  >> FFmpeg 이란 디지털 음성 스트림과 영상 스트림에 대해서 다양한 종류의 형태로 기록하고 변환하는 컴퓨터 프로그램입니다 (미디어 포맷 변환 도구)

  >> FFmpeg을 기반으로 하는 동영상 플레이어 : 

    - iOS : AV player, nPlayer

    - 안드로이드 : Dice Player, MX 플레이어, 안드로이드용 곰플레이어, 안드로이드용 KMPlayer

    - Microsoft Windows : 팟플레이어, 곰플레이어, KMPlayer, MPC-HC, 콘플레이어

    - macOS : 무비스트

    - 크로스 플랫폼 : VLC, MPlayer


9. 사전) 안드로이드 Aws Kvs HLS 에 동영상 업로드를 위한 build.gradle 의존성 부여

    implementation 'com.amazonaws:aws-android-sdk-kms:2.57.0'
    implementation 'com.amazonaws:aws-android-sdk-s3:2.57.0'
    implementation 'com.amazonaws:aws-android-sdk-iot:2.57.0'
    implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.57.0'
    implementation 'com.amazonaws:aws-android-sdk-kinesisvideo:2.57.0'


10. 사전) 안드로이드 Aws Kvs HLS 동영상 업로드를 위한 OKHTTP 네트워킹 라이브러리 build.gradle 의존성 부여

    implementation("com.squareup.okhttp3:okhttp:4.9.0")
    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'


11. 사전) 안드로이드 FFmpeg 트랜스 코딩 라이브러리 build.gradle 의존성 부여

    [ffmpeg aar 파일 다운로드 사이트] : https://artifactory.appodeal.com/appodeal-public/com/arthenica/ffmpeg-kit-full-gpl/6.0-2.LTS/

    [안드로이드 프로젝트 libs 폴더 생성 방법] : https://blog.naver.com/kkh0977/222355981962?trackingCode=blog_bloghome_searchlist

    implementation files('libs/ffmpeg-kit-full-gpl-6.0-2.LTS.aar')
    implementation 'com.arthenica:smart-exception-java:0.2.1'

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






// --------------------------------------------------------------------------------------
[로직 설명]
// --------------------------------------------------------------------------------------

1. 안드로이드 Camera , MediaRecorder , SurfaceView 객체를 사용해 휴대폰 실시간 카메라 영상 출력 및 외부 저장소에 녹화 된 파일을 MP4 형태로 저장 수행

  >> 외부 저장소 다운로드 경로 확인 코드 : String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath().trim()+"/video.mp4";

  >> MediaRecorder 에 녹화 파일 저장 설정 값 지정 : 

    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); // [오디오 데이터를 얻어올 곳]
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // [비디오 데이터를 얻어올 곳]

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // [비디오 저장 파입]
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // [비디오 인코딩 타입]
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // [오디오 인코딩 타입]

    mediaRecorder.setOrientationHint(90);  // [세로 모드 고정 (0, 90, 180, 270)]

    mediaRecorder.setVideoSize(1280, 720); // 원하는 해상도
    mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024); // 5Mbps 비트레이트 (높을수록 화질↑, 용량↑)
    mediaRecorder.setVideoFrameRate(30); // FPS 설정 (30 또는 60)

    mediaRecorder.setOutputFile(filePath); // [비디오 저장 경로]
    mediaRecorder.setPreviewDisplay(holder.getSurface()); // [홀더에 표시 된 영상 화면 레코더에 지정]

    mediaRecorder.prepare(); // [Recorder 준비]
    mediaRecorder.start(); // [Recorder 시작]


2. 안드로이드 FFmpeg 라이브러리를 사용해 외부 저장소에 저장 된 MP4 파일을 MKV 파일 형식으로 트랜스 코딩 수행 (FFmpegKit.executeAsync)

  >> mp4 파일을 mkv 파일로 변환 커맨드 코드 : 

    String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath().trim();
    String mp4Path = filePath + "/video.mp4";

    String mkvPath = filePath + "/video.mkv";

    String command = String.format("-i %s -c copy %s", mp4Path, mkvPath);


3. 안드로이드에서 변환 된 mkv 파일을 InputStream 으로 읽어 byte[] 에 담기 수행

  >> 외부 저장소에 저장 된 mkv 파일을 File 로 읽은 후 byte[] 담는 코드 : 

    String mkvPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath().trim() + "/video.mkv";

    byte[] rawMkvByte = null;

    try (InputStream inputStream = new FileInputStream(new File(mkvPath));
          ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {

        byte[] temp = new byte[4096]; // 임시 버퍼
        int bytesRead;
        while ((bytesRead = inputStream.read(temp)) != -1) {
            buffer.write(temp, 0, bytesRead);
        }

        rawMkvByte = buffer.toByteArray();
    }


4. 안드로이드 AWSKinesisVideoClient 사용해 GetDataEndpointRequest 호출로 DataEndpoint 정보 확인

  >> GetDataEndpointRequest 정보 확인 코드 : 

    AWSKinesisVideo awsKinesisVideoClient = new AWSKinesisVideoClient(credentials);
    awsKinesisVideoClient.setRegion(Region.getRegion(REGION));

    GetDataEndpointRequest dataEndPointRequest = new GetDataEndpointRequest()
            .withStreamName(STREAM_NAME) // 스트림 이름 설정
            .withAPIName(APIName.PUT_MEDIA); // TODO API 이름 설정 (PUT_MEDIA, GET_MEDIA 등)

    GetDataEndpointResult result = awsKinesisVideoClient.getDataEndpoint(dataEndPointRequest);

    String dataEndpoint  = result.getDataEndpoint();


5. 안드로이드 AWS4Signer 사용해 http 호출에 필요한 사인 header 값 확인 수행 :

  >> AWS4Signer 사용해 사인 header 값 확인 및 okhttp 헤더에 추가 코드 : 

    // -----------------------------------------------
    Request<?> signRequest = new DefaultRequest<>("kinesisvideo");

    signRequest.setHttpMethod(HttpMethodName.POST);
    signRequest.setEndpoint(new URI(dataEndpoint)); // TODO [DataEndpoint 적용]
    signRequest.setEncodedResourcePath("/putMedia"); // TODO [Path 설정 : 해당 값 추가 중요]

    signRequest.addHeader("Host", new URI(dataEndpoint).getHost()); // TODO [호스트 지정]
    signRequest.addHeader("x-amzn-stream-name", STREAM_NAME); // TODO [스트림 명칭]
    signRequest.addHeader("x-amzn-fragment-timecode-type", "ABSOLUTE"); // TODO [타임 코드]

    signRequest.addHeader("Content-Type", "application/octet-stream"); // TODO [Body 에서 지정한 MediaType 타입]

    signRequest.setContent(new StringInputStream("")); // TODO [Empty Body 지정 필요]
    // -----------------------------------------------
    AWS4Signer signer = new AWS4Signer();

    signer.setServiceName("kinesisvideo");
    signer.setRegionName(REGION);

    signer.sign(signRequest, credentials); // TODO [Sign 인증 수행]
    // -----------------------------------------------
    Headers.Builder okHttpHeaders = new Headers.Builder();
    for (Map.Entry<String, String> entry : signRequest.getHeaders().entrySet()) {
        okHttpHeaders.add(entry.getKey(), entry.getValue());
        S_Log.w("KWON_TWOK", ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Okhttp Header Insert :: " + String.valueOf(entry.getKey()) + " :: " + String.valueOf(entry.getValue()) + " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
    }
    // -----------------------------------------------
  

6. 안드로이드 okhttp RequestBody 에 상위에서 읽은 mkv 파일 byte[] 값 지정 후 putMedia 스트리밍 재생 http 호출 수행

  >> RequestBody 에 byte[] 지정 및 okhttp3.Request 생성 코드 : 

    // -----------------------------------------------
    RequestBody requestBody = new RequestBody() {
        @Override
        public MediaType contentType() {
            return MediaType.parse("application/octet-stream");
        }

        @Override
        public void writeTo(BufferedSink sink) throws IOException {

            try (InputStream fis = new ByteArrayInputStream(rawMkvByte)) {

                byte[] buffer = new byte[4096]; // TODO [4KB 단위로 스트리밍 데이터 전송]

                int len;

                while ((len = fis.read(buffer)) != -1) {                    
                    S_Log.w("KWON_TWOK", ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> KVS HLS 스트리밍 데이터 Body Write 수행 :: " + String.valueOf(len) + " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

                    sink.write(buffer, 0, len);
                    sink.flush();
                }
            }
        }
    };
    // -----------------------------------------------
    String putMediaUrl = dataEndpoint + "/putMedia";

    okhttp3.Request request = new okhttp3.Request.Builder()
            .url(putMediaUrl) // TODO [최종 요청 URL]
            .headers(okHttpHeaders.build()) // TODO [Signature V4 인증 헤더 값 추가]
            .post(requestBody) // TODO [실시간 스트리밍 데이터 업로드 Body 추가 : writeTo]
            .build();
    // -----------------------------------------------


7. AWS 콘솔 KVS 대시보드에서 정상적으로 HLS 라이브 스트리밍 영상이 재생 되는 것 확인

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






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

[안드로이드 Aws HLS PutMedia API 호출에 필요한 GetDataEndpoint 호출 방법]

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


[안드로이드 Aws Kvs HLS 비디오 스트리밍 putMedia 호출 시 필요한 Signature V4 서명 방법]

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


[Aws KVS HLS MKV 파일 설명 - PutMedia API 스트리밍 업로드 시 전송 파일]

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


[업무 이슈] android 안드로이드 aws kvs hls 스트리밍 동영상 업로드 이슈 - mp4 파일 ffmpeg 트랜스코딩 mkv 파일 변환

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


[안드로이드 Raw 폴더에 저장 된 MKV 형식 파일 Aws Kvs HLS 비디오 스트리밍 업로드 수행]

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

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