soporte Contactar con asistencia técnica | estado del sistema Estado del Sistema
Contenido de la página

    Obtener estado de solicitudes

    Cuando se utiliza el Dynamic Ingest API para agregar videos a tu Video Cloud En la cuenta, lo que más desea saber es cuándo se procesó el video y si se crearon o no las representaciones con éxito. Este documento explica cómo puedes hacer eso usando Dynamic Ingest API notificaciones También proporcionamos una aplicación de panel de muestra que automatiza el proceso. Tenga en cuenta que este documento solo se aplica al sistema de ingesta heredado; para la entrega dinámica, consulte Obtener el estado de solicitudes dinámicas de ingesta

    Obteniendo los datos

    Las notificaciones de Ingreso dinámico le brindan toda la información que necesita saber cuando su video está listo; solo necesita saber qué buscar ... y definir qué significa "listo" para sus sistemas. Este diagrama resume el flujo de trabajo:

    Flujo de trabajo de estado de ingreso
    Flujo de trabajo de estado de ingreso

    Notificaciones de ingesta dinámica

    El servicio de notificación de Ingreso dinámico le envía notificaciones para varios tipos de eventos. Los tres que son más útiles para determinar cuándo el video está "listo" son los que indican que se han creado las representaciones particulares, las que indican que se ha creado un manifiesto y el que indica que se ha completado todo el procesamiento. Aquí hay ejemplos de cada uno:

    Rendición de notificación creada

        {
            "entity": "5002412132001",
            "profileRefId": "ts7",
            "accountId": "57838016001",
            "entityType": "ASSET",
            "videoId": "5002361893001",
            "status": "SUCCESS",
            "version": "1",
            "action": "CREATE",
            "jobId": "bb316631-c58b-4bd4-a686-13c5f7a3a779"
        }
    Notification for Rendition Created

    Tenga en cuenta en este ejemplo:

    • La videoId valor le permite saber para qué video es la versión (en caso de que tenga varios trabajos de ingesta en ejecución)
    • La profileRefId valor es la identificación de referencia para la representación especificada en el perfil de ingesta
    • si el status valor es "SUCCESS", la versión fue creada con éxito
    • Para un tipo segmentado como HLS o MPEG-DASH, la existencia de la representación no la hace reproducible; también necesita el manifiesto apropiado (consulte el siguiente ejemplo). Las representaciones MP4 se pueden reproducir tan pronto como se crean.

    Notificación creada de 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 de Manifesto Creado

    Tenga en cuenta en este ejemplo:

    • La videoId valor le permite saber para qué video es la versión (en caso de que tenga varios trabajos de ingesta en ejecución)
    • La profileRefId valor es un código especial que le dice que el activo creado era un manifiesto de 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 usar en la Media API heredada, el otro para CMS API), por lo que verá dos notificaciones de este tipo.
    • Si la línea status el valor es "SUCCESS", el manifiesto se creó con éxito
    • Para un tipo segmentado como HLS o MPEG-DASH, no existe un orden definido para la creación de las representaciones y el manifiesto; estas representaciones no se pueden reproducir hasta que ambas se hayan creado (o el video haya sido procesado por completo, consulte el siguiente ejemplo).

    Procesando la 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 de procesamiento completo

    Tenga en cuenta en este ejemplo:

    • La videoId valor le permite saber para qué video es la versión (en caso de que tenga varios trabajos de ingesta en ejecución)
    • La profileRefId is no incluido en esta notificación
    • Si la línea status el valor es "SUCCESS", el video fue procesado con éxito

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

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

    Tablero de muestra

    Esta sección explica cómo se pueden juntar las notificaciones para crear un panel de control simple para el Dynamic Ingest API. El manejador de notificaciones analiza las notificaciones de la Dynamic Ingest API para identificar el procesamiento de notificaciones completas. Luego agrega las notificaciones de video en una matriz de objetos para cada video 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 al CMS API para obtener los metadatos del video. Puedes ver el tablero aquí.

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

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

    Ingesta de arquitectura Dashboad
    Ingesta de arquitectura Dashboad

    Las partes de la aplicación

    El controlador para notificaciones está integrado en PHP: busca procesar las notificaciones completas y agrega el ID de video a una matriz en un archivo JavaScript separado:

        <?php
        // var to log errors, if any
        $problem = "No errors";
        // var to store current video index
        $videoIndex = -1;
        
        // get input data
        try {
            $json    = file_get_contents('php://input');
            $decoded = json_decode($json, true);
        } catch (Exception $e) {
            $problem = $e->getMessage();
            echo $problem;
        }
        
        // get the data file contents and parse them
        try {
            $notificationData = file_get_contents('di.json');
            $notificationDataDecoded = json_decode($notificationData, true);
        } catch (Exception $e) {
            $problem = $e->getMessage();
            echo $problem;
        }
        
        
            if (isset($decoded["entityType"])) {
                $entityType = $decoded["entityType"];
                // if the entity type is ASSET or TITLE, add it to notification data array
                if ($entityType == "ASSET" || $entityType == "TITLE") {
                    array_push($notificationDataDecoded, $decoded);
                }
                // now we'll replace the contents of di.json with what we have
                file_put_contents('di.json', json_encode($notificationDataDecoded));
        
            }
        
        echo "Dynamic Ingest callback app is running";
        var_dump($notificationData);
        
        ?>
        

    Archivo JSON:

    El archivo JSON es inicialmente una matriz vacía ([]): el manejador de notificaciones agrega los datos.

    Resumen

    El panel de control incluye HTML y JavaScript para recuperar los datos de notificación y los datos de video adicionales de la CMS API y escribe los resultados en una tabla:

        <!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>
        

    apoderado

        <?php
        /**
         * brightcove-learning-proxy.php - proxy for Brightcove RESTful APIs
         * gets an access token, makes the request, and returns the response
         * Accessing:
         *     URL: https://solutions.brightcove.com/bcls/bcls-proxy/bcsl-proxy.php
         *         (note you should *always* access the proxy via HTTPS)
         *     Method: POST
         *
         * @post {string} url - the URL for the API request
         * @post {string} [requestType=GET] - HTTP method for the request
         * @post {string} [requestBody=null] - JSON data to be sent with write requests
         *
         * @returns {string} $response - JSON response received from the API
         */
        
        // CORS enablement
        header("Access-Control-Allow-Origin: *");
        
        // set up request for access token
        $data = array();
        //
        // change the values below to use this proxy with a different account
        //
        $client_id     = "YOUR_CLIENT_ID_HERE";
        $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($request);
        curl_setopt_array($ch, array(
                CURLOPT_POST           => TRUE,
                CURLOPT_RETURNTRANSFER => TRUE,
                CURLOPT_SSL_VERIFYPEER => FALSE,
                CURLOPT_USERPWD        => $auth_string,
                CURLOPT_HTTPHEADER     => array(
                    'Content-type: application/x-www-form-urlencoded',
                ),
                CURLOPT_POSTFIELDS => $data
            ));
        $response = curl_exec($ch);
        curl_close($ch);
        
        // Check for errors
        if ($response === FALSE) {
            die(curl_error($ch));
        }
        
        // Decode the response
        $responseData = json_decode($response, TRUE);
        $access_token = $responseData["access_token"];
        
        // set up the API call
        // get data
        if ($_POST["requestBody"]) {
            $data = json_decode($_POST["requestBody"]);
        } else {
            $data = array();
        }
        // get request type or default to GET
        if ($_POST["requestType"]) {
            $method = $_POST["requestType"];
        } else {
            $method = "GET";
        }
        
        // get the URL and authorization info from the form data
        $request = $_POST["url"];
        
        //send the http request
        $ch = curl_init($request);
        curl_setopt_array($ch, array(
                CURLOPT_CUSTOMREQUEST  => $method,
                CURLOPT_RETURNTRANSFER => TRUE,
                CURLOPT_SSL_VERIFYPEER => FALSE,
                CURLOPT_HTTPHEADER     => array(
                    'Content-type: application/json',
                    "Authorization: Bearer {$access_token}",
                ),
                CURLOPT_POSTFIELDS => json_encode($data)
            ));
        $response = curl_exec($ch);
        curl_close($ch);
        
        // Check for errors
        if ($response === FALSE) {
            echo "Error: "+$response;
            die(curl_error($ch));
        }
        
        // Decode the response
        // $responseData = json_decode($response, TRUE);
        // return the response to the AJAX caller
        echo $response;
        ?>
        

    Borrar el registro

    Esta simple aplicación de PHP simplemente restaura el archivo JavaScript a su estado original, borrando los viejos identificadores de video:

        <?php
            $logFileLocation = "di.json";
            $freshContent = array ();
            $encodedContent = json_encode($freshContent);
            file_put_contents($logFileLocation, $encodedContent);
        
        echo 'Log file cleared - <a href="di-log.html">go back to the dashboard</a>';
        ?>
        

    Página actualizada por última vez el 12 jun 2020