JavaFx에 의한 비디오 재생을 사용한 멀티스레딩 예제

JavaFx에 의한 비디오 재생을 사용한 멀티스레딩 예제

2022-10-19 last update

9 minutes reading java multithreading javafx
Java 다중 스레드에 대한 연구를 시작할 때 어떻게 사용해야 하는지 예를 보았습니다.

when downloading a large file (e.g., an image, an audio clip or a video clip) over the Internet, the user may not want to wait until the entire clip downloads before starting the playback.



요즘은 그냥 유튜브가 그랬던 것처럼 평범한 일이야



그래서 나는 그것에 대해 이해하기 위해 Video Play 앱을 구현하기 시작합니다

1. HTTP 요청 헤더 범위



비디오 파일의 일부를 다운로드하려면 서버에서 지원해야 합니다Range HTTP header.

이 예에서는 Range 헤더 요청을 지원하는 AWS S3 서버에 미디어 파일을 저장합니다.

샘플 파일: Sting+-+Shape+of+My+Heart+(Leon).mp4

다음은 javafx.concurrent.Task를 확장하는 샘플 다운로드 작업입니다.

입력 URL 및 범위는 String으로 정의하고 byte[]를 출력합니다.

package com.vominh.example.thread.fx.task;

import javafx.concurrent.Task;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class Download extends Task {

    private String url;
    private String range;

    public Download(String url, String range) {
        this.url = url;
        this.range = range;
    }

    @Override
    public byte[] call() throws Exception {
        URL publicUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) publicUrl.openConnection();
        conn.setRequestProperty("Range", "bytes=" + range);
        conn.connect();
        byte[] data;
        try (InputStream inputStream = conn.getInputStream()) {
            data = inputStream.readAllBytes();
        }

        return data;
    }
}


2.다운로드와 플레이를 동시에 하는 방법



2.1. 콘텐츠 길이를 가져오고 바이트 단위로 청크 크기를 계산합니다.



이 간단한 스니펫 코드는 java.net.HttpURLConnection을 사용하여 다운로드하지 않고도 파일 정보를 얻을 수 있도록 합니다.

URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getContentType();
conn.getContentLengthLong()


콘텐츠 길이에 따라 청크 크기 = contentLength/10으로 계산합니다. 첫 번째 다운로드 바이트[]의 범위: 0-{청크 크기}

예: 크기가 20MB인 mp4 파일(20.000.000바이트)
청크 크기 = 20.000.000/10 = 2.000.000바이트
첫 번째 범위 헤더: "바이트=0-2000000"
다음 범위 헤더: "바이트=2000001-4000000"
다음 범위 헤더: "바이트=4000001-6000000"

2.2. 첫 번째 다운로드 바이트[]에서 파일 생성



파일의 첫 번째 부분이 다운로드되면 운영 체제의 임시 디렉토리에 파일을 생성합니다.

또 하나의 고급 기능은 비디오 파일에서 미리보기 이미지를 가져오는 것입니다.
이를 수행하는 org.bytedeco 지원 라이브러리가 있습니다.

2.3. 다음 다운로드는 언제 발생합니까?



javafx.scene.media.MediaPlay는 미디어 파일 재생 시 1초마다 이벤트 리스너를 지원합니다.

MediaPlayer player = new MediaPlayer(media);
player.currentTimeProperty().addListener(observable -> {
    // Event fire every 1/4 second
    int currentSecond = (int) player.getCurrentTime().toSeconds();
});


이를 바탕으로 재생량 = 다운로드의 x%일 때 다운로드 작업을 제출합니다.
x는 일시 중지 없이 비디오를 재생하려면 총 다운로드의 70% 미만이어야 합니다.
이 단계는 파일 크기, 인터넷 속도에 따라 매우 복잡합니다. 그리고 대용량 파일에 최적화하기 어렵습니다.

새 부품이 다운로드되면 첫 번째 단계에서 생성된 임시 파일에 byte[]를 추가하기만 하면 됩니다.



3.스레드 정보



나는 몇 개의 스레드가 생성되었고 그것이 무엇인지 확인하기 위해 응용 프로그램에 로그인을 했고 결과는 다음과 같습니다.


메인 스레드 -> 프로그램이 시작될 때 자동으로 생성되며, 자바 코드는 이 스레드에 의해 실행됩니다.
JavaFX 응용 프로그램 스레드 -> GUI 작업을 수행하는 스레드
pool-2-thread-1 -> 데이터 다운로드를 위해 열린 스레드

4. 앱의 남은 문제


  • 다운로드한 데이터의 끝을 다시 진행하면 재생을 재개할 수 없습니다(네트워크 오류 또는 다운로드 지점이 최적화되지 않음).
  • 종자가 지원되지 않음
  • MediaPlay가 미디어 유형을 완전히 지원하지 않습니다. 예를 들어 .mkv 파일을 재생할 수 없습니다. 여기에서 지원되는 미디어 유형을 참조하세요.
    출처는 myGithub repo에서 볼 수 있습니다.