ExoPlayer는 특별한 구성 없이 대부분의 적응형 라이브 스트림을 즉시 재생합니다. 자세한 내용은 지원되는 형식 페이지를 참고하세요.
적응형 라이브 스트림은 현재 실시간으로 이동하기 위해 정기적으로 업데이트되는 사용 가능한 미디어 기간을 제공합니다. 즉, 재생 위치는 항상 이 기간 내에 있으며 대부분의 경우 스트림이 생성되는 현재 실시간에 가깝습니다. 현재 실시간과 재생 위치의 차이를 실시간 오프셋이라고 합니다.
실시간 재생 감지 및 모니터링
라이브 기간이 업데이트될 때마다 등록된 Player.Listener 인스턴스는 onTimelineChanged 이벤트를 수신합니다. 아래에 나열되고 다음 그림에 표시된 것처럼 다양한 Player 및 Timeline.Window 메서드를 쿼리하여 현재 실시간 재생에 관한 세부정보를 가져올 수 있습니다.

Player.isCurrentWindowLive는 현재 재생 중인 미디어 항목이 라이브 스트림인지 여부를 나타냅니다. 이 값은 라이브 스트림이 종료된 경우에도 true입니다.Player.isCurrentWindowDynamic는 현재 재생 중인 미디어 항목이 아직 업데이트 중인지 여부를 나타냅니다. 이는 일반적으로 아직 종료되지 않은 라이브 스트림에 해당합니다. 이 플래그는 경우에 따라 라이브가 아닌 스트림에도 적용됩니다.Player.getCurrentLiveOffset는 현재 실시간과 재생 위치 간의 오프셋을 반환합니다 (사용 가능한 경우).Player.getDuration는 현재 실시간 창의 길이를 반환합니다.Player.getCurrentPosition는 실시간 창의 시작을 기준으로 재생 위치를 반환합니다.Player.getCurrentMediaItem는 현재 미디어 항목을 반환합니다. 여기서MediaItem.liveConfiguration에는 타겟 실시간 오프셋 및 실시간 오프셋 조정 매개변수에 대해 앱에서 제공하는 재정의가 포함됩니다.Player.getCurrentTimeline는Timeline의 현재 미디어 구조를 반환합니다. 현재Timeline.Window는Player.getCurrentMediaItemIndex및Timeline.getWindow를 사용하여Timeline에서 가져올 수 있습니다.Window내에서 다음을 수행합니다.Window.liveConfiguration에는 타겟 라이브 오프셋 및 라이브 오프셋 조정 매개변수가 포함됩니다. 이 값은 미디어의 정보와MediaItem.liveConfiguration에 설정된 앱 제공 재정의를 기반으로 합니다.Window.windowStartTimeMs는 유닉스 시간 이후 실시간 기간이 시작되는 시간입니다.Window.getCurrentUnixTimeMs은 현재 실시간의 유닉스 시간 이후의 시간입니다. 이 값은 서버와 클라이언트 간의 알려진 클럭 차이로 수정될 수 있습니다.Window.getDefaultPositionMs는 플레이어가 기본적으로 재생을 시작하는 실시간 창의 위치입니다.
라이브 스트림에서 탐색하기
Player.seekTo를 사용하여 실시간 기간 내의 어느 위치로든 탐색할 수 있습니다. 전달된 탐색 위치는 실시간 창의 시작을 기준으로 합니다. 예를 들어 seekTo(0)은 실시간 기간의 시작 부분으로 이동합니다. 플레이어는 탐색 후 탐색된 위치와 동일한 실시간 오프셋을 유지하려고 시도합니다.
실시간 기간에는 재생이 시작되는 기본 위치도 있습니다. 이 위치는 일반적으로 실시간 에지에 가까운 위치입니다. Player.seekToDefaultPosition를 호출하여 기본 위치로 탐색할 수 있습니다.
라이브 재생 UI
ExoPlayer의 기본 UI 구성요소는 실시간 기간의 길이와 그 안의 현재 재생 위치를 표시합니다. 즉, 라이브 기간이 업데이트될 때마다 위치가 뒤로 점프하는 것처럼 보입니다. 유닉스 시간 또는 현재 실시간 오프셋을 표시하는 등 다른 동작이 필요한 경우 PlayerControlView를 포크하고 필요에 맞게 수정할 수 있습니다.
실시간 재생 매개변수 구성
ExoPlayer는 일부 매개변수를 사용하여 라이브 에지에서 재생 위치의 오프셋과 이 오프셋을 조정하는 데 사용할 수 있는 재생 속도 범위를 제어합니다.
ExoPlayer는 우선순위가 높은 순서대로 세 위치에서 이러한 매개변수의 값을 가져옵니다 (첫 번째로 발견된 값이 사용됨).
MediaItem.Builder.setLiveConfiguration에 전달된MediaItem값당DefaultMediaSourceFactory에 설정된 전체 기본값입니다.- 미디어에서 직접 읽은 값입니다.
Kotlin
// Global settings. val player = ExoPlayer.Builder(context) .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build() // Per MediaItem settings. val mediaItem = MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build() ) .build() player.setMediaItem(mediaItem)
자바
// Global settings. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000)) .build(); // Per MediaItem settings. MediaItem mediaItem = new MediaItem.Builder() .setUri(mediaUri) .setLiveConfiguration( new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()) .build(); player.setMediaItem(mediaItem);
사용 가능한 구성 값은 다음과 같습니다.
targetOffsetMs: 타겟 실시간 오프셋입니다. 플레이어는 가능한 경우 재생 중에 이 실시간 오프셋에 가까워지려고 시도합니다.minOffsetMs: 허용되는 최소 실시간 오프셋입니다. 현재 네트워크 상태에 맞게 오프셋을 조정하는 경우에도 플레이어는 재생 중에 이 오프셋보다 낮게 설정하려고 시도하지 않습니다.maxOffsetMs: 허용되는 최대 실시간 오프셋입니다. 현재 네트워크 상태에 맞게 오프셋을 조정하는 경우에도 플레이어는 재생 중에 이 오프셋을 초과하려고 시도하지 않습니다.minPlaybackSpeed: 플레이어가 타겟 실시간 오프셋에 도달하려고 할 때 대체할 수 있는 최소 재생 속도입니다.maxPlaybackSpeed: 플레이어가 목표 실시간 오프셋에 도달하려고 할 때 따라잡기 위해 사용할 수 있는 최대 재생 속도입니다.
재생 속도 조정
지연 시간이 짧은 라이브 스트림을 재생할 때 ExoPlayer는 재생 속도를 약간 변경하여 라이브 오프셋을 조정합니다. 플레이어는 미디어 또는 앱에서 제공하는 타겟 실시간 오프셋과 일치시키려고 시도하지만 변화하는 네트워크 조건에 대응하려고도 시도합니다. 예를 들어 재생 중에 리버퍼링이 발생하면 플레이어는 재생 속도를 약간 늦춰 라이브 에지에서 더 멀리 이동합니다. 이후 네트워크가 다시 라이브 에지에 더 가깝게 재생을 지원할 수 있을 만큼 안정되면 플레이어는 재생 속도를 높여 타겟 라이브 오프셋으로 다시 이동합니다.
자동 재생 속도 조정이 필요하지 않은 경우 minPlaybackSpeed 및 maxPlaybackSpeed 속성을 1.0f로 설정하여 사용 중지할 수 있습니다.
마찬가지로, 이를 1.0f 이외의 값으로 명시적으로 설정하여 지연 시간이 짧지 않은 라이브 스트림에 사용 설정할 수 있습니다. 이러한 속성을 설정하는 방법에 대한 자세한 내용은 구성 섹션을 참조하세요.
재생 속도 조정 알고리즘 맞춤설정
속도 조정이 사용 설정된 경우 LivePlaybackSpeedControl은 조정 내용을 정의합니다. 맞춤 LivePlaybackSpeedControl를 구현하거나 기본 구현인 DefaultLivePlaybackSpeedControl를 맞춤설정할 수 있습니다. 두 경우 모두 플레이어를 빌드할 때 인스턴스를 설정할 수 있습니다.
Kotlin
val player = ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build() ) .build()
자바
ExoPlayer player = new ExoPlayer.Builder(context) .setLivePlaybackSpeedControl( new DefaultLivePlaybackSpeedControl.Builder() .setFallbackMaxPlaybackSpeed(1.04f) .build()) .build();
DefaultLivePlaybackSpeedControl의 관련 맞춤설정 매개변수는 다음과 같습니다.
fallbackMinPlaybackSpeed및fallbackMaxPlaybackSpeed: 미디어와 앱에서 제공하는MediaItem가 모두 한도를 정의하지 않는 경우 조정에 사용할 수 있는 최소 및 최대 재생 속도입니다.proportionalControlFactor: 속도 조정이 얼마나 원활한지 제어합니다. 값이 높으면 조정이 더 갑작스럽고 반응성이 높지만 들릴 가능성도 높습니다. 값이 작을수록 속도 간 전환이 더 부드러워지지만 속도가 느려집니다.targetLiveOffsetIncrementOnRebufferMs: 이 값은 리버퍼가 발생할 때마다 타겟 실시간 오프셋에 추가되어 더 신중하게 진행됩니다. 값을 0으로 설정하면 이 기능을 사용 중지할 수 있습니다.minPossibleLiveOffsetSmoothingFactor: 현재 버퍼링된 미디어를 기반으로 가능한 최소 라이브 오프셋을 추적하는 데 사용되는 지수 평활 계수입니다. 1에 매우 가까운 값은 추정이 더 신중하고 개선된 네트워크 상태에 맞게 조정하는 데 더 오래 걸릴 수 있음을 의미하는 반면, 값이 작을수록 추정이 더 빠르게 조정되지만 리버퍼링이 발생할 위험이 더 높습니다.
BehindLiveWindowException 및 ERROR_CODE_BEHIND_LIVE_WINDOW
플레이어가 충분히 오랫동안 일시중지되거나 버퍼링되는 경우와 같이 재생 위치가 실시간 창보다 뒤처질 수 있습니다. 이 경우 재생이 실패하고 오류 코드 ERROR_CODE_BEHIND_LIVE_WINDOW이 있는 예외가 Player.Listener.onPlayerError를 사용하여 보고됩니다. 기본 위치에서 재생을 재개하여 이러한 오류를 처리할 수 있습니다. 데모 앱의 PlayerActivity는 이 접근 방식을 보여줍니다.
Kotlin
override fun onPlayerError(error: PlaybackException) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition() player.prepare() } else { // Handle other errors } }
자바
@Override public void onPlayerError(PlaybackException error) { if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { // Re-initialize player at the live edge. player.seekToDefaultPosition(); player.prepare(); } else { // Handle other errors } }