soporte Contactar con Soporte | Estadoestado del sistema del sistema
Contenido de la página

    Obtener el estado de las solicitudes

    Cuando utiliza para agregar vídeos a su cuenta de Video Cloud, lo que más desea saber es cuándo se ha procesado el vídeo y si las copias se han creado correctamente o no.Dynamic Ingest API En este documento se explica cómo puede hacerlo mediante Dynamic Ingest API notificaciones. También ofrecemos una aplicación de panel de muestra que automatiza el proceso. Tenga en cuenta que este documento sólo se aplica al sistema de ingesta heredado: para Entrega dinámica, consulte Obtener el estado de las solicitudes de ingesta dinámica

    Obtención de los datos

    Las notificaciones de ingesta dinámica le proporcionan toda la información que necesita saber cuando el vídeo está listo - sólo necesita saber qué buscar... y definir qué significa «listo» para sus sistemas. Este diagrama resume el flujo de trabajo:

    Flujo de trabajo Estado de ingesta
    Flujo de trabajo Estado de ingesta

    Notificaciones de ingesta dinámica

    El servicio de notificaciones de ingesta dinámica le envía notificaciones para varios tipos de eventos. Los tres que son más útiles para averiguar cuándo el vídeo está «listo» son aquellos que indican que se han creado representaciones particulares, las que indican que se ha creado un manifiesto y el que indica que todo el procesamiento está completo. Aquí hay ejemplos de cada uno:

    Notificación creada por la copia

        {
            "entity": "5002412132001",
            "profileRefId": "ts7",
            "accountId": "57838016001",
            "entityType": "ASSET",
            "videoId": "5002361893001",
            "status": "SUCCESS",
            "version": "1",
            "action": "CREATE",
            "jobId": "bb316631-c58b-4bd4-a686-13c5f7a3a779"
        }
    Notificación de copia creada

    Tenga en cuenta en este ejemplo:

    • El valor le permite saber para qué video es la copia (en caso de que tenga varios trabajos de ingesta ejecutándose)videoId
    • El profileRefId valor es el identificador de referencia para la copia especificada en el perfil de ingest
    • si el status valor es «SUCCESS», la copia se creó correctamente
    • Para un tipo segmentado como HLS o MPEG-DASH, la existencia de la copia no la hace reproducible; también necesita el manifiesto apropiado (vea el siguiente ejemplo). Los renditons MP4 se pueden jugar tan pronto como se crean.

    Notificación creada por manifiesto

        {
            "jobId": "31f0b112-9890-4567-adb5-0f4ed1673701",
            "status": "SUCCESS",
            "version": "1",
            "action": "CREATE",
            "entityType": "ASSET",
            "entity": "5002412528001",
            "videoId": "5002361895001",
            "profileRefId": "HlsManifest",
            "accountId": "57838016001"
        }
    Notificación para manifiesto creado

    Tenga en cuenta en este ejemplo:

    • El valor le permite saber para qué video es la copia (en caso de que tenga varios trabajos de ingesta ejecutándose)videoId
    • los profileRefId value es un código especial que le dice que el activo creado era un manifiesto HLS (los otros valores posibles son HdsManifest , DashManifest y SmoothIsmManifest)
    • Para HLS y HDS, se creará un manifiesto, por lo que verá una notificación. Para DASH y Smoothism, se crean dos manifiestos (uno para su uso en la API Media heredada y el otro para la API de CMS), por lo que verá dos notificaciones de este tipo.
    • Si el status valor es «SUCCESS», el manifiesto se creó correctamente
    • Para un tipo segmentado como HLS o MPEG-DASH, no hay un orden definido para la creación de las copias y el manifiesto; estas representaciones no se pueden reproducir hasta que se crean ambas (o el vídeo ha sido completamente procesado - vea el siguiente ejemplo).

    Procesando notificación completa

        {
            "entityType": "TITLE",
            "status": "SUCCESS",
            "accountId": "57838016001",
            "entity": "5002412652001",
            "action": "CREATE",
            "jobId": "3e98b3a0-f624-4f2d-81c1-4e43e1d04a0f",
            "version": "1",
            "videoId": "5002412652001"
        }
    Notificación para el procesamiento completado

    Tenga en cuenta en este ejemplo:

    • El valor le permite saber para qué video es la copia (en caso de que tenga varios trabajos de ingesta ejecutándose)videoId
    • los profileRefId es no incluido en esta notificación
    • Si el status valor es «SUCCESS», el vídeo se procesó correctamente

    Para recibir notificaciones, debe incluir un campo de «devoluciones de llamada» en sus solicitudes, apuntando a una o más direcciones de devolución de llamada:Dynamic Ingest API

        {
            "master": {
                "url": "https://s3.amazonaws.com/bucket/mysourcevideo.mp4"
            }, "profile": "high-resolution",
            "callbacks": ["http://host1/path1”, “http://host2/path2”]
        }

    Panel de ejemplo

    En esta sección se explica cómo se pueden juntar las notificaciones para crear un panel simple para la API de ingesta dinámica. El controlador de notificaciones analiza las notificaciones del para identificar el procesamiento de notificaciones completas.Dynamic Ingest API A continuación, agrega las notificaciones de vídeo en una matriz de objetos para cada vídeo en un archivo JSON. El tablero en sí es una página HTML que importa el archivo JSON para obtener los datos de notificación. Utiliza los identificadores para realizar una solicitud a la API de CMS para obtener los metadatos de vídeo. Puede ver el panel aquí.

    Todos los archivos de esta aplicación, junto con las instrucciones para configurarla para su cuenta, están en este repositorio.

    Aquí está la arquitectura de alto nivel de la aplicación:

    Arquitectura de tablero de ingesta
    Arquitectura de tablero de ingesta

    Las partes de la aplicación

    El controlador de notificaciones está construido en PHP - busca procesar notificaciones completas y agrega el id de video a una matriz en un archivo JavaScript separado:

        <?PHP
        //var para registrar errores, si los hay
        $problem = «Sin errores»;
        //var para almacenar el índice de vídeo actual
        $VideoIndex = -1;
        
        //obtener datos de entrada
        probar {
            $json = file_get_contents ('php: //input');
            $decodificado = json_decode ($json, true);
        } captura (Excepción $e) {
            $problema = $e- > getMessage ();
            echo $problema;
        }
        
        //obtenemos el contenido del archivo de datos y los analizamos
        probar {
            $notificationData = file_get_contents ('di.json');
            $notificationDataDeCoded = json_decode ($NotificationData, true);
        } captura (Excepción $e) {
            $problema = $e- > getMessage ();
            echo $problema;
        }
        
        
            if (isset ($decodificado ["EntityType"])) {
                $entityType = $decodificado ["EntityType"];
                //si el tipo de entidad es ASSET o TITLE, agréguelo a la matriz de datos de notificación
                if ($entityType == «ASSET» || $EntityType == «TITLE») {
                    array_push ($notificationDataDeCoded, $decodificado);
                }
                //ahora reemplazaremos el contenido de di.json con lo que tenemos
                file_put_contents ('di.json', json_encode ($notificationDataDeCoded));
        
            }
        
        echo «La aplicación de devolución de llamada de ingesta dinámica se está ejecutando»;
        var_dump ($NotificationData);
        
        ?>
        

    Archivo JSON:

    El archivo JSON es inicialmente una matriz vacía ([]) : los datos son agregados por el controlador de notificaciones.

    Panel de control

    El panel incluye el HTML y JavaScript para obtener los datos de notificación y datos de vídeo adicionales de la y escribir los resultados en una tabla:CMS API

        <!DOCTYPE html>
        <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                <title>Dynamic Ingest Log</title>
                <style>
                    body {
                        font-family: sans-serif;
                        margin: 5em;
                    }
                    .hide {
                        display: none;
                    }
                    .show {
                        display: block;
                    }
                    table {
                        border-collapse: collapse;
                        border: 1px #999999 solid;
                    }
                    th {
                        background-color: #666666;
                        color: #f5f5f5;
                        padding: .5em;
                        font-size: .7em;
                    }
                    td {
                        border: 1px #999999 solid;
                        font-size: .7em;
                        padding: .5em
                    }
                    .hidden {
                        display: none;
                    }
                </style>
            </head>
            <body>
                <h1>Dynamic Ingest Log</h1>
                <h2>Account: Brightcove Learning (57838016001)</h2>
                <p style="width:70%">
                    Videos are listed in order of processing completion time, newest to oldest. The reference id (generated by the <a href="./di-tester.html">Dynamic Ingest tester</a>) is a combination of the date/time that the Dynamic Ingest job was initiated and the ingest profile that was used. You can add additional videos using the <a href="./di-tester.html">Dynamic Ingest tester</a>. New videos will appear in this log after processing is complete.
                </p>
                <p>
                    <button id="clearLogBtn">Clear the log</button>
                </p>
                <div id="videoLogBlock">
                    <table>
                        <thead>
                            <tr>
                                <th>Video ID</th>
                                <th>Name</th>
                                <th>Reference ID</th>
                                <th>HLS Manifests Created</th>
                                <th>HLS Renditions Created</th>
                                <th>MP4 Renditions Created</th>
                                <th>Processing Complete</th>
                            </tr>
                        </thead>
                        <tbody id="logBody"></tbody>
                    </table>
                    <h4 id="loadingMessage">Loading data, please wait...</h4>
                </div>
                <script>
                var BCLS = ( function (window, document) {
                    // to use another account, set the account_id value appropriately
                    // the client_id and client_secret will also need to be changed in the proxy
                    var my_account_id = 57838016001,
                        account_id = my_account_id,
                        logBody = document.getElementById('logBody'),
                        loadingMessage = document.getElementById('loadingMessage'),
                        clearLogBtn = document.getElementById('clearLogBtn'),
                        i = 0,
                        iMax,
                        // set the proxyURL to the location of the proxy app that makes Brightcove API requests
                        proxyURL = './brightcove-learning-proxy.php',
                        dataFileURL = './di.json',
                        videoDataArray = [],
                        requestOptions = {},
                        currentVideo,
                        currentIndex = 0;
        
                        /**
                         * Logging function - safe for IE
                         * @param  {string} context - description of the data
                         * @param  {*} message - the data to be logged by the console
                         * @return {}
                         */
                        function bclslog(context, message) {
                            if (window["console"] && console["log"]) {
                              console.log(context, message);
                            }
                            return;
                        }
        
                        /**
                         * tests for all the ways a variable might be undefined or not have a value
                         * @param {*} x the variable to test
                         * @return {Boolean} true if variable is defined and has a value
                         */
                        function isDefined(x) {
                            if ( x === '' || x === null || x === undefined || x === NaN) {
                                return false;
                            }
                            return true;
                        }
        
                        /**
                         * find index of an object in array of objects
                         * based on some property value
                         *
                         * @param {array} targetArray - array to search
                         * @param {string} objProperty - object property to search
                         * @param {string|number} value - value of the property to search for
                         * @return {integer} index of first instance if found, otherwise returns null
                         */
                        function findObjectInArray(targetArray, objProperty, value) {
                            var i, totalItems = targetArray.length, objFound = false;
                            for (i = 0; i < totalItems; i++) {
                                if (targetArray[i][objProperty] === value) {
                                    objFound = true;
                                    return i;
                                }
                            }
                            if (objFound === false) {
                                return null;
                            }
                        }
        
                        /**
                         * factory for new video objects
                         * @param {String} videoId the video id
                         * @return {object} the new object
                         */
                        function makeVideoDataObject(videoId) {
                            var obj = {};
                            obj.id = videoId;
                            obj.name = '';
                            obj.reference_id = '';
                            obj.hlsManifests = 0;
                            obj.hlsRenditions = 0;
                            obj.mp4Renditions = 0;
                            obj.complete = 'no';
                            return obj;
                        }
        
                        /**
                         * processes notification objects
                         * creates a new object in the videoDataArray if it doesn't exist
                         * and updates the videoDataArray object based on the notification
                         * @param {Object} notificationObj the raw notification object
                         */
                        function processNotification(notificationObj) {
                            var objIndex, videoObj;
                            // if notification object contains a video id, find the corresponding
                            // object in the videoDataArray or create it if it's not there
                            if (isDefined(notificationObj) && isDefined(notificationObj.videoId)) {
                                objIndex = findObjectInArray(videoDataArray, 'id', notificationObj.videoId);
                                // if not found, create one
                                if (!isDefined(objIndex)) {
                                    videoObj = makeVideoDataObject(notificationObj.videoId);
                                    videoDataArray.push(videoObj);
                                    objIndex = videoDataArray.length - 1;
                                }
                                // now update properties based on what's in the notification
                                if (notificationObj.entityType === 'ASSET') {
                                    // if it's a rendition or manifest, there will be a profileRefId
                                    if (isDefined(notificationObj.profileRefId)) {
                                        // see if it's an HLS manifest
                                        if (notificationObj.profileRefId === 'HlsManifest') {
                                            // increment the hls manifest count
                                            videoDataArray[objIndex].hlsManifests++;
                                        } else if (notificationObj.profileRefId.charAt(0) === 't') {
                                            // increment the hls rendition count
                                            videoDataArray[objIndex].hlsRenditions++;
                                        } else if (notificationObj.profileRefId.charAt(0) === 'm') {
                                            // increment the mp4 rendition count
                                            videoDataArray[objIndex].mp4Renditions++;
                                        }
                                    }
                                } else if (notificationObj.entityType === 'TITLE') {
                                    // overall processing notification - checked for SUCCESS / FAILED
                                    if (notificationObj.status === 'SUCCESS') {
                                        // mark complete
                                        videoDataArray[objIndex].complete = 'yes';
                                    } else if (notificationObj.status === 'FAILED') {
                                        // mark failed
                                        videoDataArray[objIndex].complete = 'failed';
                                    }
                                }
                            }
                            return;
                        }
        
                        /**
                         * creates the dashboard table body
                         */
                        function writeReport() {
                            var j,
                                jMax = videoDataArray.length,
                                item,
                                t;
                            loadingMessage.textContent = 'This page will refresh in 1 minute...';
                            /* just showing HLS and MP4 renditions, because
                             * that's all that will be produced in this account,
                             * but you could modify the notification handler and
                             * this page to handle other formats
                             */
                            for (j = 0; j < jMax; j++) {
                                item = videoDataArray[j];
                                if (item.id !== undefined) {
                                    logBody.innerHTML += '<tr><td>' + item.id + '</td><td>' + item.name + '</td><td>' + item.reference_id + '</td><td>' + item.hlsManifests + '</td><td>' + item.hlsRenditions + '</td><td>' + item.mp4Renditions + '</td><td>' + item.complete + '</td></tr>';
                                }
                            }
                            // set timeout for refresh
                            t = window.setTimeout(init, 60000);
                        };
        
                        // function to set up the notification data request
                        function setJSONRequestOptions() {
                            submitRequest(null, dataFileURL, 'notificationData');
                        }
        
                        // function to set up video data request
                        function setVideoRequestOptions() {
                            requestOptions = {};
                            requestOptions.url = 'https://cms.api.brightcove.com/v1/accounts/' + account_id + '/videos/' + currentVideo.id;
                            submitRequest(requestOptions, proxyURL, 'video');
                        }
        
                        /**
                         * initiates the CMS API requests
                         */
                        function getVideoInfo() {
                            iMax = videoDataArray.length;
                            if (currentIndex < iMax) {
                                currentVideo = videoDataArray[currentIndex];
                                setVideoRequestOptions();
                            } else {
                                loadingMessage.innerHTML = 'No videos have been ingested - you can add some using the <a href="./di-tester.html">Dynamic Ingest tester</a>';
                            }
                        }
        
                        /**
                         * make the CMS API requests
                         * @param {Object} options request options
                         * @param (String) url URL to send request to
                         * @param (String) type the request type
                         */
                        function submitRequest(options, url, type) {
                            var httpRequest = new XMLHttpRequest(),
                                requestData,
                                responseData,
                                videoDataObject,
                                parsedData,
                                getResponse = function () {
                                    try {
                                        if (httpRequest.readyState === 4) {
                                          if (httpRequest.status === 200) {
                                            responseData = httpRequest.responseText;
                                            switch (type) {
                                                case 'notificationData':
                                                var k, kMax, dataArray;
                                                dataArray = JSON.parse(responseData);
                                                bclslog('dataArray', dataArray);
                                                // process the notifications
                                                kMax = dataArray.length;
                                                for (k = 0; k < kMax; k++) {
                                                    processNotification(dataArray[k]);
                                                }
                                                getVideoInfo();
                                                break;
                                                case 'video':
                                                parsedData = JSON.parse(responseData);
                                                bclslog('parsedData', parsedData);
                                                videoDataArray[currentIndex].reference_id = parsedData.reference_id;
                                                videoDataArray[currentIndex].name = parsedData.name;
                                                currentIndex++;
                                                if (currentIndex < iMax) {
                                                    currentVideo = videoDataArray[currentIndex];
                                                    setVideoRequestOptions();
                                                } else {
                                                    writeReport();
                                                }
                                                break;
                                            }
                                          } else {
                                            bclslog("There was a problem with the request. Request returned " + httpRequest.status);
                                            if (type === 'video') {
                                                setVideoRequestOptions();
                                            } else {
                                                setSourcesRequestOptions();
                                            }
                                          }
                                        }
                                      }
                                      catch(e) {
                                        bclslog('Caught Exception: ' + e);
                                      }
                                };
                            // notifications data is a special case
                            if (type === 'notificationData') {
                                // set response handler
                                httpRequest.onreadystatechange = getResponse;
                                // open the request
                                httpRequest.open("GET", url);
                                // set headers
                                httpRequest.setRequestHeader("Content-Type", "application/json");
                                // open and send request
                                httpRequest.send();
                            } else {
                                // requests via proxy
                                // set up request data
                                requestData = "url=" + encodeURIComponent(options.url) + "&requestType=GET";
                                // set response handler
                                httpRequest.onreadystatechange = getResponse;
                                // open the request
                                httpRequest.open("POST", url);
                                // set headers
                                httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                                // open and send request
                                httpRequest.send(requestData);
                            }
                        };
        
                        // event handlers
                        clearLogBtn.addEventListener('click', function () {
                            if (window.confirm('Are you sure? This action cannot be undone!')) {
                                // if your clear-log app resides in another location, change the URL
                                window.location.href = 'clear-log.php';
                            }
                        });
        
                        // get things started
                        function init() {
                            // clear table and the video data array
                            logBody.innerHTML = "";
                            videoDataArray = [];
                            setJSONRequestOptions();
                        }
                        // kick off the app
                        init();
                    })(window, document);
                </script>
            </body>
        </html>
        

    Proxy

        <?PHP
        /**
         * brightcove-learning-proxy.php - proxy para las API RESTful de Brightcove
         * obtiene un token de acceso, hace la solicitud y devuelve la respuesta
         * Accediendo a:
         * URL: https://solutions.brightcove.com/bcls/bcls-proxy/bcsl-proxy.php
         * (tenga en cuenta que debe *siempre* acceder al proxy a través de HTTPS)
         * Método: PUBLICAR
         *
         * @post {string} url - la URL para la solicitud de API
         * @post {string} [requestType=Get] - Método HTTP para la solicitud
         * @post {string} [requestBody=NULL] - Datos JSON que se enviarán con solicitudes de escritura
         *
         * @returns {string} $response - respuesta JSON recibida de la API
         */
        
        //Habilitación CORS
        encabezado («Access-Control-Allow-Origin: *»);
        
        //configuramos la solicitud de token de acceso
        $data = array ();
        //
        //cambiar los valores a continuación para usar este proxy con una cuenta diferente
        //
        $client_id = «YOUR_CLIENT_ID_AQUÍ»;
        $client_secret = «YOUR_CLIENT_SECRET_HERE»;
        $auth_string = «{$client_id}: {$client_secret}»;
        $request = "https://oauth.brightcove.com/v4/access_token?grant_type=client_credentials «;
        $ch = curl_init ($solicitud);
        curl_setopt_array($ch, array(
                CURLOPT_POST           => TRUE,
                CURLOPT_RETURNTRANSFER => TRUE,
                CURLOPT_SSL_VERIFYPEER => FALSE,
                CURLOPT_USERPWD        => $auth_string,
                CURLOPT_HTTPHEADER     => array(
                    'Tipo de contenido: application/x-www-form-urlencoded',
                ),
                CURLOPT_POSTFIELDS => $data
            ));
        $ respuesta = curl_exec ($ch);
        curl_close($ch);
        
        //Comprobación de errores
        if ($response === FALSE) {
            die (curl_error ($ch));
        }
        
        //Decodificar la respuesta
        $responseData = json_decode ($respuesta, TRUE);
        $access_token = $responseData ["access_token"];
        
        //configuramos la llamada API
        //obtener datos
        if ($_POST ["requestBody"]) {
            $data = json_decode ($_POST ["requestBody"]);
        } else {
            $data = array ();
        }
        //obtener el tipo de solicitud o por defecto a GET
        if ($_POST ["RequestType"]) {
            $method = $_POST ["RequestType"];
        } else {
            $método = «GET»;
        }
        
        //obtener la URL y la información de autorización de los datos del formulario
        $request = $_POST ["url"];
        
        //enviar la solicitud http
        $ch = curl_init ($solicitud);
        curl_setopt_array($ch, array(
                CURLOPT_CUSTOMREQUEST  => $method,
                CURLOPT_RETURNTRANSFER => TRUE,
                CURLOPT_SSL_VERIFYPEER => FALSE,
                CURLOPT_HTTPHEADER     => array(
                    «Tipo de contenido: application/json»,
                    «Autorización: Portador {$access_token}»,
                ),
                CURLOPT_POSTFIELDS => json_encode($data)
            ));
        $ respuesta = curl_exec ($ch);
        curl_close($ch);
        
        //Comprobación de errores
        if ($response === FALSE) {
            echo «Error: «+$response;
            die (curl_error ($ch));
        }
        
        //Decodificar la respuesta
        //$responseData = json_decode ($response, TRUE);
        //devuelve la respuesta al llamador AJAX
        echo $respuesta;
        ?>
        

    Borrar el registro

    Esta sencilla aplicación PHP simplemente restaura el archivo JavaScript a su estado original, eliminando los identificadores de video antiguos:

        <?PHP
            $logFileLocation = «di.json»;
            $FreshContent = array ();
            $encodedContent = json_encode ($FreshContent);
            file_put_contents ($LogFileLocation, $EncodedContent);
        
        echo 'Archivo de registro borrado - < a href=» di-log.html "> volver al tablero < /a > ';
        ?>
        

    Última actualización de la página el 28-09-2020