타임 시프팅 지원

TV 입력 서비스에서 타임 시프팅 API를 사용하면 사용자가 서비스 채널에서 라이브 프로그램을 일시중지, 되감기, 빨리 감기할 수 있습니다. 앱에서 타임 시프팅을 지원하면 사용자는 콘텐츠를 유연하게 시청할 수 있습니다.

  • 사용자가 중요한 순간을 놓치지 않도록 프로그램을 일시중지하는 동시에 단기적인 중단을 처리할 수 있습니다.
  • 사용자는 이미 본 콘텐츠나 관심이 없는 콘텐츠를 빨리 감을 수 있습니다.
  • 사용자가 좋아하는 부분을 다시 보기 위해 프로그램 콘텐츠를 되감을 수 있습니다.

그림 1. 타임 시프팅에 사용되는 Android TV 재생 컨트롤

타임 시프팅은 임시로 녹화된 짧은 프로그램 데이터 세그먼트를 사용하여 라이브 프로그램을 재생하는 기능을 구현합니다. 사용자는 현재 재생 세션 외부에서 이러한 타임 시프팅 녹화를 재생할 수 없습니다. 즉, 타임 시프팅을 사용하여 다음 날 시청하기 위해 프로그램을 일시중지하거나 다른 채널로 전환하는 동안 나중에 시청하기 위해 프로그램을 일시중지할 수 없습니다.

사용자가 현재 재생 세션 외부에서 볼 수 있도록 프로그램 콘텐츠를 녹화할 수 있도록 하려면 TV 녹화 API를 사용하세요.

타임 시프팅 지원 추가

TV 입력 서비스에 타임 시프팅 지원을 추가하려면 TvInputService.Session 클래스에서 타임 시프팅 API를 구현하고, 앱에서 타임 시프팅 녹화의 녹화 및 재생을 처리하고, 입력 서비스가 타임 시프팅을 지원한다고 시스템에 알려야 합니다.

구현하는 TvInputService.Session 메서드는 다음과 같습니다.

입력 서비스가 타임 시프팅을 지원한다고 시스템에 알리는 방법에 관한 자세한 내용은 시스템에 타임 시프팅 상태 알림 섹션을 참고하세요.

TIF 컴패니언 라이브러리를 사용하여 TvInputService.Session 클래스를 구현하고 있다면 ExoPlayer를 사용하는 타임 시프팅을 자동으로 구현하게 됩니다. 이 구현을 사용하거나 BaseTvInputService.Session에서 타임 시프팅 API 메서드를 재정의하여 자체 구현을 제공할 수 있습니다. TIF 컴패니언 라이브러리 사용에 관한 자세한 내용은 TIF 컴패니언 라이브러리를 사용하여 TV 입력 서비스 만들기를 참고하세요.

세션 시작 시 콘텐츠 녹화

사용자는 콘텐츠를 시청하는 동안 선택을 누른 다음 재생 컨트롤로 이동하거나 원격 기기의 전용 재생 컨트롤을 사용하여 채널의 재생 컨트롤에 액세스하여 프로그램 콘텐츠를 일시중지, 되감기, 빨리 감기할 수 있습니다.

사용자는 프로그램 콘텐츠를 시청하는 동안 언제든지 타임 시프팅을 사용할 수 있으므로 TV 입력 서비스는 사용자가 onTune() 구현의 채널에 맞추는 즉시 타임 시프팅 콘텐츠 녹화를 시작해야 합니다. 또한 시스템에 타임 시프팅 상태 알림 섹션에 설명된 대로 notifyTimeShiftStatusChanged(int)를 호출하여 녹화할 수 있음을 시스템에 알려야 합니다.

녹화된 콘텐츠 저장소 관리

TV 입력 서비스는 앱의 비공개 앱 저장소에 타임 시프팅 녹화를 저장하고 시스템이 타임 시프팅 메서드(예: onTimeShiftResume())를 호출할 때 콘텐츠를 재생합니다. 콘텐츠가 이미 클라우드에 저장되어 있고 앱이 클라우드에서 타임 시프팅 녹화를 관리할 수 있다면 앱 저장소 대신 클라우드 스토리지를 사용할 수 있습니다.

콘텐츠가 보호된 콘텐츠를 사용하는 경우 TV 입력 서비스는 녹화된 콘텐츠를 적절하게 암호화하고 재생 중에 복호화해야 합니다.

녹화된 동영상 콘텐츠는 많은 저장용량이 필요할 수 있으므로 세션 재생 중에 녹화된 콘텐츠를 신중하게 관리해야 합니다. 재생 세션 시간이 타임 시프팅을 위해 녹화하고 저장할 수 있는 시간을 초과하면 타임 시프팅 녹화를 조정하여 현재 버퍼를 유지하되 현재 시간이 캡처되도록 해야 합니다. 예를 들어 사용자가 31분 동안 콘텐츠를 재생했고 최대 타임 시프팅 녹화 크기가 30분인 경우 1분에서 31분 사이의 콘텐츠가 포함되도록 녹화와 시작 시간을 조정합니다.

저장소 부족으로 인해 TV 입력 서비스가 타임 시프팅을 지원할 수 없다면 시스템에 알려야 합니다. 타임 시프팅 지원의 제한사항을 시스템에 알리는 방법에 관한 자세한 내용은 시스템에 타임 시프팅 상태 알림 섹션을 참고하세요.

사용자가 다른 채널로 전환하거나 재생 세션을 종료할 때 녹화된 타임 시프팅 데이터를 삭제합니다.

시스템에 타임 시프팅 상태 알림

TV 입력 서비스가 타임 시프팅을 지원하면 사용자가 채널에 맞출 때 onTune() 구현에서 notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_AVAILABLE)를 호출합니다.

입력 서비스의 타임 시프팅 기능이 변경되었음을 시스템에 알리려면 notifyTimeShiftStatusChanged(int)를 사용합니다. 예를 들어 TV 입력 서비스가 저장공간 제한 또는 다른 이유로 타임 시프팅을 지원할 수 없다면 notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_UNAVAILABLE)를 호출합니다.

TV 입력 서비스가 타임 시프팅을 전혀 지원할 수 없다면 재생 세션이 생성될 때 notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_UNSUPPORTED)를 호출합니다. 시스템은 notifyTimeShiftStatusChanged()를 호출하지 않는 모든 입력 서비스를 타임 시프팅을 지원할 수 없는 입력 서비스로 취급합니다. 여기에는 API 수준 22 및 이전 버전을 사용하는 입력 서비스가 포함됩니다.

재생 시간 추적

타임 시프팅 녹화의 시작 위치는 사용자가 탐색할 수 있는 가장 이른 절대 시간 위치(에포크 이후 밀리초 단위)입니다. 일반적으로 onTune()가 호출된 후 동영상 재생이 시작되는 시간입니다. 그러나 사용자가 앱에서 녹화할 수 있는 양을 초과하는 콘텐츠를 시청하면 타임 시프팅을 위해 새 세그먼트 녹화를 시작하고 그에 따라 시작 시간을 업데이트해야 합니다.

타임 시프팅 녹화의 현재 위치는 현재 재생 위치(에포크 이후 밀리초 단위)입니다. 이 위치는 재생 중에 계속 변경됩니다. 일반적으로 다음 예와 같이 재생 엔진을 사용하여 이 값을 결정할 수 있습니다.

Kotlin

override fun onTimeShiftGetCurrentPosition(): Long =
        tvPlayer?.run {
            currentProgram?.let { program ->
                currentPosition + program.startTimeUtcMillis
            }
        } ?: TvInputManager.TIME_SHIFT_INVALID_TIME

Java

@Override
public long onTimeShiftGetCurrentPosition() {
  if (getTvPlayer() != null && currentProgram != null) {
    return getTvPlayer().getCurrentPosition() +
      currentProgram.getStartTimeUtcMillis();
  }
  return TvInputManager.TIME_SHIFT_INVALID_TIME;
}

시스템에서 onTimeShiftGetStartPosition()를 호출할 때 제공한 시작 시간이 개발자가 onTimeShiftGetCurrentPosition()에 제공한 현재 시간 위치보다 크지 않도록 해야 합니다. 시스템은 이러한 호출을 사용하여 재생 컨트롤 UI에서 타임 시프팅 시간을 업데이트합니다.

재생 매개변수 지원

타임 시프팅 중 재생 속도를 변경하기 위해 시스템은 재생 매개변수를 사용합니다. 예를 들어 사용자가 현재 재생을 되감기로 하면 새 재생 매개변수가 음수 재생 속도로 앱에 전달됩니다. 또한 타임 시프팅은 되감기 또는 빨리 감기를 위해 다양한 수준의 재생 속도(2배 또는 3배)를 지원합니다.

시스템은 현재 세션의 매개변수가 포함된 PlaybackParams 객체를 사용하여 onTimeShiftSetPlaybackParams(PlaybackParams) 메서드를 호출합니다. 이 정보를 사용하여 미디어 재생 엔진을 적절하게 구성할 수 있습니다.

재생 엔진이 매개변수를 지원하지 않으면 가능한 한 예상 동작을 에뮬레이션하세요. 예를 들어 재생 엔진이 2배속을 지원하지 않으면 재생 엔진에서 반복 탐색 작업을 사용하여 약 두 배의 재생 속도를 달성합니다.

매개변수가 설정된 후에는 사용자가 다른 매개변수가 필요한 재생 명령어를 실행하거나 새 채널로 전환하지 않는 한 설정을 변경하지 마세요.