타임 시프팅 지원

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
    

자바

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

시스템이 onTimeShiftGetStartPosition()을 호출할 때 제공한 시작 시간은 onTimeShiftGetCurrentPosition()에서 제공한 현재 시간 위치를 절대 초과하지 않아야 합니다. 시스템은 이 호출을 사용하여 재생 컨트롤 UI에서 타임 시프팅 시간을 업데이트합니다.

재생 매개변수 지원

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

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

재생 엔진에서 매개변수를 지원하지 않는 경우 예상되는 동작을 최대한 에뮬레이션해야 합니다. 예를 들어, 재생 엔진이 2배속을 지원하지 않는다면 재생 엔진에서 반복 탐색 작업을 사용하여 거의 두 배의 재생 속도를 달성해야 합니다.

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