Compatibilidad con time-shifting

Usa las APIs de pausa en directo en tu servicio de entrada de TV para permitir que los usuarios pausen, retrocedan y adelantan los programas en vivo en tus canales de servicio. Si tu app admite la pausa en directo, los usuarios obtienen flexibilidad en cuanto a cómo miran tu contenido:

  • Los usuarios pueden pausar programas mientras controlan una interrupción de corto plazo, de modo que nunca se pierdan de momentos clave.
  • Los usuarios pueden adelantar el contenido que ya vieron o que no les interesa.
  • Pueden retroceder o volver a mirar sus momentos favoritos del contenido del programa.

Figura 1: Controles de reproducción de Android TV para pausa en directo

La pausa en directo usa segmentos cortos, temporales y grabados de los datos del programa para implementar la capacidad de reproducir programas en vivo. Los usuarios no pueden reproducir estas grabaciones con pausa en directo fuera de la sesión de reproducción actual. Esto significa que no pueden usar la pausa en directo para pausar un programa para mirar al día siguiente o pausarlo para verlo más tarde mientras cambian a un canal diferente.

Usa las APIs de grabación de TV si quieres permitir que los usuarios graben contenido de programas para mirarlos fuera de la sesión de reproducción actual.

Cómo agregar compatibilidad con la pausa en directo

Para agregar compatibilidad con la pausa en directo a tu servicio de entrada de TV, debes implementar las APIs de esta función en tu clase TvInputService.Session, controlar la grabación y reproducción de grabaciones con pausa en directo en tu app, y notificar al sistema que tu servicio de entrada proporciona compatibilidad con esta función.

Los métodos TvInputService.Session que implementas son los siguientes:

Para obtener más información sobre cómo informar al sistema que tu servicio de entrada admite pausa en directo, consulta la sección Cómo notificar al sistema sobre el estado de la pausa en directo.

Si usas la Biblioteca complementaria del TIF para implementar tu clase TvInputService.Session, obtienes automáticamente una implementación de pausa en directo que usa ExoPlayer. Puedes usar esta implementación o anular los métodos de la API de pausa en directo en BaseTvInputService.Session y proporcionar tu propia implementación. Para obtener más información sobre el uso de la Biblioteca complementaria del TIF, consulta Cómo crear un servicio de entrada de TV con la Biblioteca complementaria del TIF.

Cómo grabar contenido cuando comienza una sesión

Un usuario puede pausar, retroceder y adelantar el contenido de un programa si accede a los controles de reproducción del canal, ya sea presionando Seleccionar mientras mira contenido y, luego, navegando hasta los controles de reproducción o usando controles de reproducción dedicados en un dispositivo remoto.

Dado que el usuario puede usar la pausa en directo en cualquier momento mientras mira el contenido de un programa, tu servicio de entrada de TV debe comenzar a grabar el contenido con pausa en directo apenas el usuario sintoniza un canal en tu implementación de onTune(). También debes informar al sistema que eres capaz de grabar mediante una llamada a notifyTimeShiftStatusChanged(int), como se describe en la sección Cómo notificar al sistema sobre el estado de la pausa en directo.

Cómo administrar el almacenamiento de contenido grabado

Tu servicio de TV es responsable de almacenar las grabaciones con pausa en directo en el almacenamiento privado de la app y reproducir contenido cuando el sistema llama a tus métodos de pausa en directo, como onTimeShiftResume(). Si tu contenido ya está almacenado en la nube y tu app puede administrar grabaciones con pausa en directo en ella, puedes usar el almacenamiento en la nube en lugar de en la app.

Si tu contenido usa contenido protegido, tu servicio de entrada de TV es responsable de la encriptación adecuada del contenido grabado y la desencriptación durante la reproducción.

Dado que el contenido de video grabado puede requerir una gran cantidad de almacenamiento, debes administrar cuidadosamente el contenido grabado durante la sesión de reproducción. Si el tiempo de la sesión de reproducción supera la cantidad de tiempo que puedes grabar y almacenar para la pausa en directo, ajusta la grabación con pausa en directo para mantener el búfer actual, pero asegúrate de que se capture el tiempo actual. Por ejemplo, si el usuario reprodujo contenido durante 31 minutos y el tamaño máximo de grabación con pausa en directo es de 30 minutos, ajusta la grabación y la hora de inicio para que incluyan contenido desde el minuto 1 hasta el minuto 31.

Si tu servicio de entrada de TV no admite la pausa en directo debido a la falta de almacenamiento, debes informárselo al sistema. Para obtener más detalles sobre cómo notificar al sistema sobre las restricciones de compatibilidad con la pausa en directo, consulta la sección Cómo notificar al sistema sobre el estado de la pausa en directo.

Cuando el usuario cambie a un canal diferente o finalice la sesión de reproducción, borra los datos grabados de la pausa en directo.

Cómo notificar al sistema sobre el estado de la pausa en directo

Si tu servicio de entrada de TV admite la pausa en directo, llama a notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_AVAILABLE) en tu implementación de onTune() cuando un usuario sintonice un canal.

Para informar al sistema sobre algún cambio en las capacidades de pausa en directo de tu servicio de entrada, usa notifyTimeShiftStatusChanged(int). Por ejemplo, si tu servicio de entrada de TV no admite la pausa en directo debido a restricciones de espacio de almacenamiento u otros motivos, llama a notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_UNAVAILABLE).

Si tu servicio de entrada de TV no admite la pausa en directo, llama a notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_UNSUPPORTED) cuando se cree una sesión de reproducción. El sistema trata cualquier servicio de entrada que nunca llame a notifyTimeShiftStatusChanged() como un servicio de entrada que no admite la pausa en directo. Esto abarca los servicios de entrada que usan el nivel de API 22 y versiones anteriores.

Cómo realizar el seguimiento de los tiempos de la reproducción

La posición de inicio de una grabación con pausa en directo es la posición de tiempo absoluto más temprana, en milisegundos desde la época, a la que el usuario puede saltar. Este suele ser el tiempo en el que se inicia la reproducción de video después de llamar a onTune(). Sin embargo, cuando el usuario mira una cantidad de contenido que excede lo que la app puede grabar, debes comenzar a grabar un nuevo segmento para la pausa en directo y actualizar la hora de inicio según corresponda.

La posición actual de una grabación con pausa en directo es la posición de reproducción actual, en milisegundos desde la época. Esta posición cambia continuamente durante la reproducción. Por lo general, puedes usar el motor de reproducción para determinar este valor, tal como se muestra en el siguiente ejemplo:

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;
}

Asegúrate de que la hora de inicio que proporciones cuando el sistema llame a tu onTimeShiftGetStartPosition() nunca sea mayor que la posición de tiempo actual que proporcionas en onTimeShiftGetCurrentPosition(). El sistema usa estas llamadas para actualizar la duración de la pausa en directo en la IU de controles de reproducción.

Cómo agregar compatibilidad con los parámetros de reproducción

Para cambiar la velocidad de reproducción durante la pausa en directo, el sistema usa parámetros de reproducción. Por ejemplo, si el usuario decide retroceder la reproducción actual, los nuevos parámetros de reproducción se pasan a tu app con una velocidad de reproducción negativa. La pausa en directo también admite varios niveles diferentes, 2 o 3 veces, de velocidad de reproducción para retroceder o adelantar.

El sistema llama a tu método onTimeShiftSetPlaybackParams(PlaybackParams) con un objeto PlaybackParams que contiene parámetros para la sesión actual. Usa esta información para configurar tu motor de reproducción de contenido multimedia correctamente.

Si tu motor de reproducción no admite un parámetro, emula el comportamiento esperado lo mejor que puedas. Por ejemplo, si tu motor de reproducción no admite la velocidad 2x, usa operaciones de búsqueda repetidas en el motor de reproducción para lograr una velocidad de reproducción doble aproximadamente.

Después de configurar los parámetros, no debes cambiar la configuración, a menos que el usuario emita un comando de reproducción que requiera un parámetro diferente o cambie a un canal nuevo.