Aspectos básicos del flujo de trabajo de contenido protegido

Flash Player 10.1 y posterior, Adobe AIR 2.0 y posterior

El siguiente flujo de trabajo de alto nivel muestra cómo una aplicación puede recuperar y reproducir contenido protegido. El flujo de trabajo asume que la aplicación está diseñada específicamente para reproducir contenido protegido con Flash Access:

  1. Obtenga los metadatos del contenido.

  2. Gestione las actualizaciones a Flash Player, si es necesario.

  3. Compruebe si hay una licencia disponible localmente. Si es así, cárguela y vaya al paso 7. Si no, vaya al paso 4.

  4. Compruebe si es necesario autenticarse. Si no lo es, vaya al paso 7.

  5. Si se requiere autenticación, obtenga las credenciales para el usuario y envíelas al servidor de licencias.

  6. Una vez completada la autenticación, descargue la licencia del servidor.

  7. Reproduzca el contenido.

Si no se produce ningún error y se autoriza correctamente al usuario a ver el contenido, el objeto NetStream distribuye un objeto DRMStatusEvent. La aplicación comienza a reproducirse después. El objeto DRMStatusEvent contiene la información de la licencia asociada, que identifica la póliza del usuario y sus permisos. Por ejemplo, contiene información relacionada con si el contenido puede verse sin conexión o cuándo caduca la licencia. La aplicación puede aprovechar estos datos para informar al usuario del estado de su póliza. Por ejemplo: la aplicación puede mostrar en una barra de estado el número de días restantes para que el usuario pueda ver el contenido.

(Sólo AIR) Si el usuario tiene permiso para acceder sin conexión, la licencia se guarda en caché y el contenido cifrado se descarga en el equipo del usuario. El contenido está accesible en la duración definida en el periodo de cesión sin conexión. La propiedad detail del evento contiene "DRM.voucherObtained". La aplicación decide dónde guardar el contenido en el equipo para tenerlo a disposición fuera de línea. También se puede realizar la carga previa de licencias mediante la clase DRMManager.

Todos los errores relacionados con DRM hacen que la aplicación distribuya un objeto DRMErrorEvent o, en AIR, un objeto DRMAuthenticationErrorEvent. Es responsabilidad de la aplicación gestionar de forma explícita todos los demás eventos de error. Estos eventos incluyen casos en que el usuario introduce credenciales válidas pero la licencia que protege el contenido cifrado limita el acceso al contenido. Por ejemplo, un usuario autenticado no puede acceder al contenido si no ha pagado por los derechos. Este caso también puede darse si dos miembros registrados del mismo editor intentan compartir contenido por el que solo uno de ellos ha pagado. La aplicación debería informar al usuario sobre el error y ofrecer una sugerencia como alternativa. Una alternativa habitual es ofrecer instrucciones para registrarse y pagar por los derechos de visionado.

Flujo de trabajo detallado de la API

Este flujo de trabajo ofrece una vista más detallada del flujo de trabajo de contenido protegido. Este flujo de trabajo describe las API específicas utilizadas para reproducir contenido protegido con Flash Access.

  1. Con ayuda de un objeto URLLoader, cargue los bytes del archivo de metadatos del contenido protegido. Defina este objeto como una variable, por ejemplo, metadata_bytes.

    Todo el contenido controlador por Flash Access tiene metadatos de Flash Access. Cuando se empaqueta el contenido, estos metadatos se pueden guardar como un archivo de metadatos independiente (.metadata) junto con el contenido. Para obtener más información, consulte la documentación de Flash Access.

  2. Cree una instancia de DRMContentData. Coloque este código en un bloque try-catch:

    new DRMContentData(metadata_bytes)

    donde metadata_bytes es el objeto URLLoader obtenido en el paso 1.

  3. (Sólo Flash Player) El motor de ejecución busca el módulo Flash Access. Si no lo encuentra, se emite un error IllegalOperationError con código de error 3344.

    Para gestionar este error, descargue el módulo Flash Access con la API SystemUpdater. Una vez descargado el módulo, el objeto SystemUpdater distribuye un evento COMPLETE. Incluya un detector de eventos para este evento que vuelve al paso 2 cuando se distribuye. El siguiente código demuestra estos pasos:

    flash.system.SystemUpdater.addEventListener(Event.COMPLETE, updateCompleteHandler); 
    flash.system.SystemUpdater.update(flash.system.SystemUpdaterType.DRM)
    private function updateCompleteHandler (event:Event):void { 
        /*redo step 2*/ 
        drmContentData = new DRMContentData(metadata_bytes); 
    } 

    Si se debe actualizar el propio reproductor, se distribuye un evento status. Para obtener más información sobre la gestión de este evento, consulte Detección de un evento update.

    Nota: en aplicaciones de AIR, el archivo de instalación de AIR gestiona la actualización del módulo Flash Access y las posibles actualizaciones necesarias del motor de ejecución.
  4. Cree detectores para detectar los eventos DRMStatusEvent y DRMErrorEvent del objeto DRMManager:

    DRMManager.addEventListener(DRMStatusEvent.DRM_STATUS, onDRMStatus); 
    DRMManager.addEventListener(DRMErrorEvent.DRM_ERROR, onDRMError);

    En el detector de DRMStatusEvent, confirme que la licencia es válida (no null). En el detector de DRMErrorEvent, gestione eventos DRMErrorEvent. Consulte Uso de la clase DRMStatusEvent y Uso de la clase DRMErrorEvent.

  5. Cargue la licencia necesaria para poder reproducir el contenido.

    Primero, intente cargar la licencia guardada localmente para reproducir el contenido:

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.LOCAL_ONLY)

    Una vez completada la carga, el objeto DRMManager distribuye un evento DRMStatusEvent.DRM_Status.

  6. Si el objeto DRMVoucher no es null, la licencia es válida. Vaya directamente al paso 13.

  7. Si el objeto DRMVoucher es null, compruebe el método de autenticación requerido por la póliza para este contenido. Utilice la propiedad DRMContentData.authenticationMethod.

  8. Si el método de autenticación es ANONYMOUS, vaya al paso 13.

  9. Si el método de autenticación es USERNAME_AND_PASSWORD, su aplicación debe contar con un mecanismo para que el usuario pueda introducir sus credenciales. Envíe estas credenciales al servidor de licencias para autenticar al usuario:

    DRMManager.authenticate(metadata.serverURL, metadata.domain, username, password)

    DRMManager distribuye un evento DRMAuthenticationErrorEvent si falla la autenticación y un evento DRMAuthenticationCompleteEvent si la autenticación se produce correctamente. Cree detectores para estos eventos.

  10. Si la autenticación falla, la aplicación debe volver al paso 9. Asegúrese de que la aplicación cuenta con un mecanismo para gestionar y limitar el número de fallos de autenticación repetidos. Por ejemplo, tras tres intentos, muestre un mensaje al usuario indicando que la autenticación ha fallado y que no es posible visualizar el contenido.

  11. Si la autenticación se produce correctamente, descargue la licencia del servidor de licencias:

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.FORCE_REFRESH)

    Una vez completada la carga, el objeto DRMManager distribuye un evento DRMStatusEvent.DRM_STATUS. Detecte este evento y, cuando se distribuya, podrá reproducir el contenido.

  12. (opcional) Si la autenticación se realiza correctamente, puede capturar el símbolo de autenticación (un conjunto de bytes que se almacena en memoria). Obtenga este símbolo con la propiedad DRMAuthenticationCompleteEvent.token. Puede almacenar y usar el símbolo de autenticación para que el usuario no tenga que introducir sus credenciales cada vez que quiera ver este contenido. El servidor de licencias determina el periodo de validez del símbolo de autenticación.

    Para usar el símbolo almacenado y evitar tener que pedir al usuario que introduzca sus credenciales, establezca el símbolo con el método DRMManager.setAuthenticationToken(). Seguidamente, descargue la licencia del servidor de licencias y reproduzca el contenido como en el paso 8.

  13. Reproduzca el vídeo creando un objeto NetStream y llamando a su método play() después:

    stream = new NetStream(connection); 
    stream.addEventListener(DRMStatusEvent.DRM _STATUS, drmStatusHandler); 
    stream.addEventListener(DRMErrorEvent.DRM_ERROR, drmErrorHandler); 
    stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
    stream.client = new CustomClient(); 
    video.attachNetStream(stream); 
    stream.play(videoURL); 

Eventos relacionados con DRM

El motor de ejecución distribuye varios eventos cuando una aplicación intenta reproducir contenido protegido:

  • DRMAuthenticateEvent (sólo AIR), distribuido por NetStream

  • DRMAuthenticationCompleteEvent, distribuido por DRMManager

  • DRMAuthenticationErrorEvent, distribuido por DRMManager

  • DRMErrorEvent, distribuido por NetStream y por DRMManager

  • DRMStatusEvent, distribuido por NetStream y por DRMManager

  • StatusEvent

  • NetStatusEvent. Consulte Detección de un evento update

Para admitir contenido protegido con Flash Access, añada detectores de eventos para controlar los eventos DRM.

Precarga de licencias para reproducción sin conexión

Puede precargar las licencias necesarias para reproducir contenido protegido con Flash Access. Las licencias precargadas permiten a los usuarios ver el contenido tengan o no una conexión a Internet. (El propio proceso de carga previa requiere una conexión a Internet.) Puede utilizar el método preloadEmbeddedMetadata() de la clase NetStream y la clase DRMManager para precargar licencias. En AIR 2.0 y posterior, puede utilizar un objeto DRMContentData para precargar licencias directamente. Es preferible usar esta técnica, ya que permite actualizar el objeto DRMContentData independientemente del contenido. (El método preloadEmbeddedData() obtiene un objeto DRMContentData del contenido.)

Uso de DRMContentData

En los siguientes pasos se describe el flujo de trabajo para precargar la licencia de un archivo multimedia protegido mediante un objeto DRMContentData.

  1. Obtenga los metadatos binarios del contenido empaquetado. Si utiliza Flash Access Java Reference Packager, este archivo de metadatos se genera automáticamente con la extensión .metadata. Puede, por ejemplo, descargar estos metadatos mediante la clase URLLoader.

  2. Cree un objeto DRMContentData pasando los metadatos a la función constructora:

    var drmData:DRMContentData = new DRMContentData( metadata );
  3. El resto de los pasos son idénticos a los del flujo de trabajo descrito en Aspectos básicos del flujo de trabajo de contenido protegido.

Uso de preloadEmbeddedMetadata()

Los siguientes pasos describen el flujo de trabajo para realizar la carga previa de la licencia para un archivo multimedia protegido por DRM usando preloadEmbeddedMetadata():

  1. Descargue y almacene el archivo. (Los metadatos DRM sólo se pueden precargar desde archivos almacenados localmente.)

  2. Cree los objetos NetConnection y NetStream, proporcionando implementaciones para las funciones callback onDRMContentData() y onPlayStatus() del objeto cliente NetStream.

  3. Cree un objeto NetStreamPlayOptions y establezca la propiedad stream en la URL del archivo de medios local.

  4. Llame al método preloadEmbeddedMetadata() de NetStream, transmitiendo el objeto NetStreamPlayOptions e identificando el archivo de medios para analizar.

  5. Si el archivo contiene metadatos DRM, se invoca la función callback onDRMContentData(). Los metadatos se transmiten a esta función como un objeto DRMContentData.

  6. Utilice el objeto DRMContentData para obtener la licencia utilizando el método loadVoucher() de DRMManager.

    Si el valor de la propiedad authenticationMethod del objeto DRMContentData es userNameAndPassword, debe autenticar al usuario en el servidor de derechos multimedia antes de cargar la licencia. Las propiedades serverURL y domain del objeto DRMContentData se pueden transmitir al método authenticate(), junto con las credenciales del usuario.

  7. La función onPlayStatus() se invoca cuando el análisis del archivo ha finalizado. Si la función onDRMContentData() no se ha llamado, el archivo no contiene los metadatos necesarios para obtener una licencia. La ausencia de esta llamada también puede querer decir que Flash Access no protege este archivo.

El siguiente ejemplo de código para AIR muestra cómo precargar una licencia para un archivo multimedia local:

package 
{ 
import flash.display.Sprite; 
import flash.events.DRMAuthenticationCompleteEvent; 
import flash.events.DRMAuthenticationErrorEvent; 
import flash.events.DRMErrorEvent;   
import flash.ev ents.DRMStatusEvent; 
import flash.events.NetStatusEvent; 
import flash.net.NetConnection; 
import flash.net.NetStream; 
import flash.net.NetStreamPlayOptions; 
import flash.net.drm.AuthenticationMethod; 
import flash.net.drm.DRMContentData; 
import flash.net.drm.DRMManager; 
import flash.net.drm.LoadVoucherSetting;   
public class DRMPreloader extends Sprite  
{ 
     private var videoURL:String = "app-storage:/video.flv"; 
    private var userName:String = "user"; 
    private var password:String = "password";  
    private var preloadConnection:NetConnection; 
    private var preloadStream:NetStream; 
    private var drmManager:DRMManager = DRMManager.getDRMManager(); 
    private var drmContentData:DRMContentData; 
    public function DRMPreloader():void { 
        drmManager.addEventListener( 
            DRMAuthenticationCompleteEvent.AUTHENTICATION_COMPLETE, 
            onAuthenticationComplete); 
        drmManager.addEventListener(DRMAuthenticationErrorEvent.AUTHENTICATION_ERROR, 
            onAuthenticationError);             
        drmManager.addEventListener(DRMStatusEvent.DRM_STATUS, onDRMStatus); 
        drmManager.addEventListener(DRMErrorEvent.DRM_ERROR, onDRMError); 
        preloadConnection = new NetConnection(); 
        preloadConnection.addEventListener(NetStatusEvent.NET_STATUS, onConnect); 
        preloadConnection.connect(null);            
    } 
 
    private function onConnect( event:NetStatusEvent ):void 
    { 
        preloadMetadata(); 
    } 
    private function preloadMetadata():void 
    { 
        preloadStream = new NetStream( preloadConnection ); 
        preloadStream.client = this; 
        var options:NetStreamPlayOptions = new NetStreamPlayOptions(); 
        options.streamName = videoURL; 
        preloadStream.preloadEmbeddedData( options );                         
    }     
    public function onDRMContentData( drmMetadata:DRMContentData ):void 
    { 
        drmContentData = drmMetadata; 
        if ( drmMetadata.authenticationMethod == AuthenticationMethod.USERNAME_AND_PASSWORD ) 
        { 
            authenticateUser(); 
        } 
        else 
            { 
                getVoucher(); 
            } 
    } 
    private function getVoucher():void 
    { 
        drmManager.loadVoucher( drmContentData, LoadVoucherSetting.ALLOW_SERVER ); 
    } 
 
    private function authenticateUser():void 
    { 
        drmManager.authenticate( drmContentData.serverURL, drmContentData.domain, userName, password ); 
    } 
    private function onAuthenticationError( event:DRMAuthenticationErrorEvent ):void 
    { 
        trace( "Authentication error: " + event.errorID + ", " + event.subErrorID ); 
    } 
 
    private function onAuthenticationComplete( event:DRMAuthenticationCompleteEvent ):void 
    { 
        trace( "Authenticated to: " + event.serverURL + ", domain: " + event.domain ); 
        getVoucher(); 
    } 
    private function onDRMStatus( event:DRMStatusEvent ):void 
    { 
        trace( "DRM Status: " + event.detail); 
        trace("--Voucher allows offline playback = " + event.isAvailableOffline ); 
        trace("--Voucher already cached          = " + event.isLocal ); 
        trace("--Voucher required authentication = " + !event.isAnonymous ); 
    } 
    private function onDRMError( event:DRMErrorEvent ):void 
    { 
        trace( "DRM error event: " + event.errorID + ", " + event.subErrorID + ", " + event.text ); 
    } 
    public function onPlayStatus( info:Object ):void 
    { 
        preloadStream.close(); 
    } 
} 
}