맞춤설정

ExoPlayer 라이브러리의 핵심에는 Player 인터페이스가 있습니다. Player 양방향 미디어 플레이어와 같은 기존의 상위 수준 미디어 플레이어 기능을 버퍼링 미디어, 재생, 일시중지, 탐색이 있습니다. 기본 구현 ExoPlayer는 다음과 같습니다. 가정이 거의 없는 방식으로 설계되어 제한사항이 거의 적용되지 않음 재생 중인 미디어 유형, 저장 방법 및 위치, 미디어 있습니다. 미디어 로드와 렌더링을 직접 구현하는 대신 ExoPlayer 구현은 이 작업을 삽입된 구성요소에 위임합니다. 플레이어가 생성되거나 새 미디어 소스가 플레이어에 전달될 때. 모든 ExoPlayer 구현의 공통 구성요소는 다음과 같습니다.

  • MediaSource 재생할 미디어를 정의하고 미디어를 로드하며 여기서 로드된 미디어를 읽을 수 있습니다. MediaSource 인스턴스가 생성됨 플레이어 내의 MediaSource.Factory에 의한 MediaItem에서 호출되었습니다. 또한 미디어 소스 기반 재생목록 API를 사용하여 플레이어에 직접 전달될 수 있습니다.
  • MediaItemMediaSource로 변환하는 MediaSource.Factory 인스턴스 이 플레이어가 생성될 때 MediaSource.Factory가 삽입됩니다.
  • 미디어의 개별 구성요소를 렌더링하는 Renderer 인스턴스 이는 삽입될 수 있습니다.
  • MediaSource에서 제공할 트랙을 선택하는 TrackSelector 사용 가능한 각 Renderer에서 소비합니다. TrackSelector가 삽입됨 플레이어가 생성됩니다.
  • MediaSource가 더 많은 미디어를 버퍼링하는 시점을 제어하는 LoadControl 버퍼링되는 미디어의 양과 같습니다. 플레이어가 다음 상태일 때 LoadControl가 삽입됩니다. 생성됨.
  • 라이브 중 재생 속도를 제어하는 LivePlaybackSpeedControl 플레이어가 설정된 실시간 오프셋에 가깝게 유지할 수 있도록 합니다. 가 플레이어가 생성될 때 LivePlaybackSpeedControl가 삽입됩니다.

플레이어의 조각을 구현하는 구성요소를 삽입한다는 개념 기능이 라이브러리 전체에 있습니다. 기본 구현은 일부 구성 요소는 추가로 삽입된 구성 요소에 작업을 위임합니다. 이렇게 하면 많은 사용자가 하위 구성 요소가 포함되어 있는 구현으로 개별적으로 대체되어야 합니다. 구성할 수 있습니다

플레이어 맞춤설정

구성요소를 삽입하여 플레이어를 맞춤설정하는 일반적인 예는 다음과 같습니다. 참조하세요.

네트워크 스택 구성

ExoPlayer에서 사용하는 네트워크 스택 맞춤설정에 관한 페이지가 있습니다.

네트워크에서 로드된 데이터 캐싱

다음 가이드를 참고하세요. 즉석 캐싱 미디어 다운로드를 사용할 수 있습니다

서버 상호작용 맞춤설정

일부 앱은 HTTP 요청 및 응답을 가로채려고 할 수 있습니다. 권장 사항 커스텀 요청 헤더를 삽입하고, 서버의 응답 헤더를 읽고, '요청' URI 등이 해당됩니다. 예를 들어, 앱이 미디어 세그먼트를 요청할 때 헤더로 사용할 수 있는 토큰입니다.

다음 예는 다음을 통해 이러한 동작을 구현하는 방법을 보여줍니다. DefaultMediaSourceFactory에 맞춤 DataSource.Factory 삽입:

Kotlin

val dataSourceFactory =
  DataSource.Factory {
    val dataSource = httpDataSourceFactory.createDataSource()
    // Set a custom authentication request header.
    dataSource.setRequestProperty("Header", "Value")
    dataSource
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
    )
    .build()

자바

DataSource.Factory dataSourceFactory =
    () -> {
      HttpDataSource dataSource = httpDataSourceFactory.createDataSource();
      // Set a custom authentication request header.
      dataSource.setRequestProperty("Header", "Value");
      return dataSource;
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory))
        .build();

위의 코드 스니펫에서 삽입된 HttpDataSource에는 헤더가 포함되어 있습니다. 모든 HTTP 요청에서 "Header: Value"입니다. 이 동작은 모든 iOS에서 수정됩니다. HTTP 소스와의 상호 작용을 통해 작동합니다

더 세부적인 접근 방식을 위해 다음을 사용하여 적시 동작을 삽입할 수 있습니다. ResolvingDataSource 다음 코드 스니펫은 : HTTP 소스와 상호작용하기 직전에 요청 헤더를 확인합니다.

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time request headers.
    dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri))
  }

자바

    DataSource.Factory dataSourceFactory =
        new ResolvingDataSource.Factory(
            httpDataSourceFactory,
            // Provide just-in-time request headers.
            dataSpec -> dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri)));

ResolvingDataSource를 사용하여 URI를 적시(JIT) 수정해야 합니다.

Kotlin

val dataSourceFactory: DataSource.Factory =
  ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec ->
    // Provide just-in-time URI resolution logic.
    dataSpec.withUri(resolveUri(dataSpec.uri))
  }

자바

DataSource.Factory dataSourceFactory =
    new ResolvingDataSource.Factory(
        httpDataSourceFactory,
        // Provide just-in-time URI resolution logic.
        dataSpec -> dataSpec.withUri(resolveUri(dataSpec.uri)));

오류 처리 맞춤설정

맞춤 LoadErrorHandlingPolicy를 구현하면 앱에서 ExoPlayer가 로드 오류에 반응하는 방식으로 작동합니다. 예를 들어 앱이 빠르게 실패하고 싶을 수 있습니다. 여러 번 다시 시도하는 대신 각 재시도 사이에 플레이어의 대기 시간을 제어합니다. 다음 스니펫 맞춤 백오프 로직을 구현하는 방법을 보여줍니다.

Kotlin

val loadErrorHandlingPolicy: LoadErrorHandlingPolicy =
  object : DefaultLoadErrorHandlingPolicy() {
    override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long {
      // Implement custom back-off logic here.
      return 0
    }
  }
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)
    )
    .build()

자바

LoadErrorHandlingPolicy loadErrorHandlingPolicy =
    new DefaultLoadErrorHandlingPolicy() {
      @Override
      public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) {
        // Implement custom back-off logic here.
        return 0;
      }
    };

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context)
                .setLoadErrorHandlingPolicy(loadErrorHandlingPolicy))
        .build();

LoadErrorInfo 인수에는 실패한 로드에 대한 자세한 정보가 포함되어 있습니다. 오류 유형이나 실패한 요청을 기반으로 로직을 맞춤설정할 수 있습니다.

추출기 플래그 맞춤설정

추출기 플래그를 사용하여 개별 형식이 추출되는 방식을 맞춤설정할 수 있음 진보적인 미디어입니다. 다음 DefaultExtractorsFactory에서 설정할 수 있습니다. DefaultMediaSourceFactory에 제공됩니다. 다음 예는 MP3 스트림에 대한 색인 기반 탐색을 가능하게 합니다.

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING)
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context, extractorsFactory))
    .build()

자바

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING);

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

고정 비트 전송률 탐색 사용 설정

MP3, ADTS 및 AMR 스트림의 경우 일정한 비트 전송률 가정을 FLAG_ENABLE_CONSTANT_BITRATE_SEEKING 플래그와 함께 사용합니다. 이러한 플래그는 DefaultExtractorsFactory.setXyzExtractorFlags 메서드를 사용해야 합니다. 받는사람 비트 전송률을 지원하는 모든 추출기에 대해 일정한 비트 전송률을 찾도록 설정하려면 DefaultExtractorsFactory.setConstantBitrateSeekingEnabled

Kotlin

val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)

자바

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);

그런 다음 ExtractorsFactoryDefaultMediaSourceFactory를 통해 다음과 같이 삽입할 수 있습니다. 위 추출기 플래그 맞춤설정에 설명된 내용을 참조하세요.

비동기 버퍼 큐 사용 설정

비동기 버퍼 큐는 ExoPlayer의 렌더링을 개선한 것임 비동기 모드에서 MediaCodec 인스턴스를 작동하는 파이프라인과 같습니다 추가 스레드를 사용하여 데이터의 디코딩 및 렌더링을 예약합니다. 사용 설정 중 드롭된 프레임과 오디오 언더런을 줄일 수 있습니다.

Android 12를 실행하는 기기에서는 비동기 버퍼 큐가 기본적으로 사용 설정됨 (API 수준 31) 이상과 호환되며 Android 6.0 (API 수준 23)부터 수동으로 사용 설정할 수 있습니다. 드롭된 것으로 확인된 특정 기기에 기능을 사용 설정해 보세요. 프레임 또는 오디오 언더런(특히 DRM으로 보호되거나 높은 프레임 속도를 재생할 때) 있습니다.

가장 간단한 경우에는 DefaultRenderersFactory를 있습니다.

Kotlin

val renderersFactory = 
  DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing()
val exoPlayer = ExoPlayer.Builder(context, renderersFactory).build()

자바

DefaultRenderersFactory renderersFactory =
    new DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing();
ExoPlayer exoPlayer = new ExoPlayer.Builder(context, renderersFactory).build();

렌더기를 직접 인스턴스화하는 경우 MediaCodecVideoRendererAsynchronousMediaCodecAdapter.FactoryMediaCodecAudioRenderer 생성자

ForwardingPlayer로 메서드 호출 가로채기

Player 인스턴스의 동작을 다음과 같이 래핑하여 맞춤설정할 수 있습니다. ForwardingPlayer의 서브클래스이고 다음 작업을 수행하기 위해 메서드를 재정의합니다. 다음과 같습니다.

  • 위임 Player에 매개변수를 전달하기 전에 매개변수에 액세스합니다.
  • 위임 Player를 반환하기 전에 반환 값에 액세스합니다.
  • 메서드를 완전히 다시 구현합니다.

ForwardingPlayer 메서드를 재정의할 때는 구현은 일관성이 유지되고 Player을 준수합니다. 특히 API 액세스를 위해 의도된 메서드를 다룰 때 관련이 있는 것으로 간주됩니다. 예를 들면 다음과 같습니다.

  • 모든 '재생'을 재정의하고 싶다면 재정의하면 ForwardingPlayer.playForwardingPlayer.setPlayWhenReady입니다. 왜냐하면 호출자는 호출할 때 이러한 메서드의 동작이 동일할 것으로 예상합니다. playWhenReady = true입니다.
  • 탐색 증분을 변경하려면 둘 다 재정의해야 합니다. ForwardingPlayer.seekForward - 맞춤설정된 증분하여 보고하려면 ForwardingPlayer.getSeekForwardIncrement입니다. 올바른 맞춤 증분을 발신자에게 반환합니다.
  • 플레이어가 광고하는 Player.Commands를 관리하려는 경우 Player.getAvailableCommands()Player.isCommandAvailable()에서 듣고 다음 음악도 들어보세요. 알림을 받을 Player.Listener.onAvailableCommandsChanged() 콜백 변경사항을 적용할 수 있습니다.

MediaSource 맞춤설정

위의 예에서는 모든 콘텐츠의 재생 중에 사용할 맞춤설정된 구성요소를 삽입합니다. 플레이어에 전달되는 MediaItem 객체입니다. 세밀한 맞춤설정이 필요한 경우 필요에 따라 맞춤설정된 구성요소를 개별 포드에 MediaSource 인스턴스: 플레이어에 직접 전달할 수 있습니다. 예시 아래는 ProgressiveMediaSource를 맞춤설정하여 DataSource.Factory, ExtractorsFactory, LoadErrorHandlingPolicy:

Kotlin

val mediaSource =
  ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
    .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
    .createMediaSource(MediaItem.fromUri(streamUri))

자바

ProgressiveMediaSource mediaSource =
    new ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory)
        .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy)
        .createMediaSource(MediaItem.fromUri(streamUri));

커스텀 구성요소 만들기

라이브러리는 상단에 나열된 구성요소의 기본 구현을 제공합니다. 이 페이지의 일반적인 사용 사례를 확인할 수 있습니다 ExoPlayer는 이러한 구성요소를 사용할 수 있지만 비표준 동작이 구현되고 있는 경우 커스텀 구현을 사용하도록 필요합니다. 맞춤 구현의 일부 사용 사례는 다음과 같습니다.

  • Renderer: 맞춤 Renderer를 구현하여 미디어 유형이 있습니다.
  • TrackSelector: 맞춤 TrackSelector를 구현하면 앱이 허용됩니다. 개발자가 MediaSource에 의해 노출된 트랙이 적용되는 방식을 변경 사용 가능한 각 Renderer에서 소비하도록 선택됩니다.
  • LoadControl: 맞춤 LoadControl를 구현하면 앱이 허용됩니다. 개발자가 플레이어의 버퍼링 정책을 변경할 수 있습니다.
  • Extractor – 현재 지원되지 않는 컨테이너 형식을 지원해야 하는 경우 라이브러리에서 지원하는 경우 맞춤 Extractor 클래스를 구현하는 것이 좋습니다.
  • MediaSource: 맞춤 MediaSource 클래스 구현은 다음과 같을 수 있습니다. 형식으로 렌더러에 피드할 미디어 샘플을 확보하려는 맞춤 방식으로 또는 맞춤 MediaSource 합성을 구현하려는 경우 있습니다.
  • MediaSource.Factory: 맞춤 MediaSource.Factory 구현 애플리케이션에서 MediaSource 생성 방식을 맞춤설정할 수 있습니다. MediaItem에서 가져옴
  • DataSource: ExoPlayer의 업스트림 패키지에는 이미 여러 다양한 사용 사례를 위한 DataSource 구현 권장 사항 자체 DataSource 클래스를 구현하여 다른 방식으로 데이터 로드(예: 커스텀 프로토콜, 커스텀 HTTP 스택 사용, 커스텀 영구 IP 주소를 통해 있습니다.

맞춤 구성요소를 빌드할 때 다음을 권장합니다.

  • 맞춤 구성요소에서 이벤트를 앱에 다시 보고해야 하는 경우 이때 기존 ExoPlayer 구성요소와 동일한 모델을 사용하여 EventDispatcher 클래스를 사용하거나 다음과 함께 Handler를 전달하는 예 구성요소의 생성자에 대한 리스너입니다.
  • 맞춤 구성요소는 기존 ExoPlayer와 동일한 모델을 사용하는 것이 좋습니다. 구성요소를 사용하여 재생 중에 앱이 재구성할 수 있도록 합니다. 이렇게 하려면 맞춤 구성요소는 PlayerMessage.Target를 구현하고 handleMessage 메서드의 구성 변경사항을 확인할 수 있습니다. 애플리케이션 코드는 ExoPlayer의 createMessage 메서드를 호출하여 구성 변경사항을 전달합니다. 이를 사용하여 메시지를 구성하고 PlayerMessage.send입니다. 재생 대화목록에서 전달될 메시지 전송 다른 작업과 함께 순서대로 실행되도록 합니다. 확인할 수 있습니다.