Paper Contacter le support | état du système L'état du système
Contenu de la page

    Obtenir le statut des demandes d'acquisition dynamiques

    Lorsque vous utilisez le Dynamic Ingest API ajouter des vidéos à votre Video Cloud compte, ce que vous voulez le plus savoir, c'est quand la vidéo a été traitée et si les rendus ont été créés avec succès.

    Introduction

    Ce document explique comment vous pouvez suivre l’état des tâches en effectuant des demandes d’état auprès du CMS API ou en utilisant Dynamic Ingest API notifications. Nous fournissons également un exemple d'application de tableau de bord qui automatise le processus

    Notez que l'état des travaux d'acquisition n'est disponible que pour les travaux soumis avec les derniers jours 7.

    Statut de demande

    Vous obtenez le statut des travaux d'acquisition dynamiques (acquisition, remplacement ou retranscode) à l'aide de ces CMS API critères - notez que ces terminaux fonctionnent pour Emplois Dynamic Delivery uniquement:

    Obtenir le statut pour tous les emplois

        https://cms.api.brightcove.com/v1/accounts/{account_id}/videos/{video_id}/ingest_jobs

    La réponse ressemblera à ceci:

         [
          {
            "id": "ac49b1db-e6e1-477f-a2c1-70b9cd3107cb",
            "state": "finished",
            "account_id": "57838016001",
            "video_id": "5636411346001",
            "error_code": null,
            "error_message": null,
            "updated_at": "2017-11-07T13:56:51.505Z",
            "started_at": "2017-11-07T13:56:12.510Z",
            "priority": "normal",
            "submitted_at": "2017-11-07T13:56:12.435Z"
          },
          {
            "id": "10605652-8b6f-4f22-b190-01bd1938677b",
            "state": "processing",
            "account_id": "57838016001",
            "video_id": "5636411346001",
            "error_code": null,
            "error_message": null,
            "updated_at": null,
            "started_at": null,
            "priority": "low",
            "submitted_at": "2017-11-07T14:06:35.000Z"
          }
        ]

    Obtenir le statut d'une tâche spécifique

        https://cms.api.brightcove.com/v1/accounts/{account_id}/videos/{video_id}/ingest_jobs/{job_id}

    La réponse ressemblera à ceci:

        {
            "id": "ac49b1db-e6e1-477f-a2c1-70b9cd3107cb",
            "state": "finished",
            "account_id": "57838016001",
            "video_id": "5636411346001",
            "error_code": null,
            "error_message": null,
            "updated_at": "2017-11-07T13:56:51.505Z",
            "started_at": "2017-11-07T13:56:12.510Z",
            "priority": "normal",
            "submitted_at": "2017-11-07T13:56:12.435Z"
          }

    Les valeurs possibles pour state sont:

    • processing: traitement, la vidéo n'est pas encore lisible
    • publishing: au moins un rendu lisible a été créé et la vidéo est en cours de préparation pour la lecture.
    • published: au moins un rendu est disponible pour la lecture
    • finished: tout le traitement est terminé
    • failed: le traitement a échoué; Si vous ne parvenez pas à comprendre ce qui ne va pas, contactez le support.

    Obtenir des notifications

    Si la méthode d’état de la demande décrite ci-dessus fonctionne, si vous attendez un état particulier (published or finished), il est préférable de laisser Brightcove vous avertir lorsque ces événements se produisent plutôt que de continuer à demander le statut jusqu'à ce que vous obteniez la réponse que vous recherchez. Nous allons maintenant voir comment vous pouvez créer une application pour gérer les notifications.

    Les notifications Dynamic Ingest vous donnent toutes les informations dont vous avez besoin pour savoir quand votre vidéo est prête. Il vous suffit de savoir ce qu'il faut rechercher ... et de définir ce que signifie «prêt» pour vos systèmes. Ce diagramme résume le flux de travail:

    Ingest Statut du flux de travail
    Ingest Statut du flux de travail

    Notifications d'acquisition dynamique

    Le service de notification Dynamic Ingest vous envoie des notifications pour plusieurs types d'événements. Les deux qui sont les plus utiles pour déterminer quand la vidéo est "prête" sont ceux qui indiquent que des rendus particuliers ont été créés et celui qui indique que tout le traitement est terminé. Voici des exemples de chacun:

    Rendu dynamique créé notification

        {
          "entity": "default/video3800",
          "entityType": "DYNAMIC_RENDITION",
          "version": "1",
          "action": "CREATE",
          "jobId": "d3ef8751-2b88-4141-95d5-83f0393aca07",
          "videoId": "5660367449001",
          "dynamicRenditionId": "default\/video3800",
          "bitrate": 3804,
          "width": 1920,
          "height": 1080,
          "accountId": "57838016001",
          "status": "SUCCESS"
        }
        
        
    Notification pour Rendition créée

    Notez dans cet exemple:

    • Le système videoId valeur vous permet de savoir à quelle vidéo le rendu est destiné (au cas où plusieurs travaux d'acquisition sont en cours d'exécution)
    • Le système entity value est le type de rendu dynamique créé
    • si le status la valeur est "SUCCESS", le rendu a été créé avec succès

    Traitement de la notification complète

        {
          "entity": "5660367449001",
          "entityType": "TITLE",
          "version": "1",
          "action": "CREATE",
          "jobId": "d3ef8751-2b88-4141-95d5-83f0393aca07",
          "videoId": "5660367449001",
          "accountId": "57838016001",
          "status": "SUCCESS"
        }
        
        
    Notification de traitement terminée

    Notez dans cet exemple:

    • Le système videoId et jobId les valeurs vous permettent de savoir à quelle vidéo il s'agit (au cas où plusieurs travaux d'acquisition sont en cours d'exécution)
    • Si la status la valeur est "SUCCESS", la vidéo a été traitée avec succès

    Pour recevoir des notifications, vous devez inclure un champ "rappels" dans votre navigateur. Dynamic Ingest API demandes, pointant vers une ou plusieurs adresses de rappel:

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

    Exemple de tableau de bord

    Cette section explique comment regrouper les notifications pour créer un tableau de bord simple pour le Dynamic Ingest API. Le gestionnaire de notifications analyse les notifications de la Dynamic Ingest API identifier le traitement des notifications complètes. Il ajoute ensuite les notifications vidéo à un tableau d'objets pour chaque vidéo d'un fichier JSON. Le tableau de bord lui-même est une page HTML qui importe le fichier JSON pour obtenir les données de notification. Il utilise les identifiants pour faire une demande au CMS API pour obtenir les métadonnées de la vidéo.

    Voici l'architecture de haut niveau de l'application:

    Architecture du tableau de bord Ingest
    Architecture du tableau de bord Ingest

    Les parties de l'application

    Le gestionnaire des notifications est construit en PHP - il cherche à traiter les notifications complètes et ajoute l'identifiant vidéo à un tableau dans un fichier JavaScript séparé:

        <?php
          // POST won't work for JSON data
          $problem = "No errors";
          try {
            $json    = file_get_contents('php://input');
            $decoded = json_decode($json, true);
          } catch (Exception $e) {
            $problem = $e->getMessage();
            echo $problem;
          }
        
          // full notification
          $notification = json_encode($decoded, JSON_PRETTY_PRINT);
        
          // Begin by extracting the useful parts of the notification
          // for Dynamic Delivery, look for 'videoId'
          // for the legacy ingest system, the video id is the 'entity'
        
          if (isset($decoded["videoId"])) {
            $videoId = $decoded["videoId"];
          } elseif (isset($decoded["entity"])) {
            $videoId = $decoded["entity"];
          } else {
            $videoId = null;
          }
        
          if (isset($decoded["entityType"])) {
            $entityType = $decoded["entityType"];
          } else {
            $entityType = null;
          }
        
          if (isset($decoded["status"])) {
            $status = $decoded["status"];
          } else {
            $status = null;
          }
        
          if (isset($decoded["action"])) {
            $action = $decoded["action"];
          } else {
            $action = null;
          }
        
          // if notification is for completed title, act
        
          if (($entityType == 'TITLE') && ($action == 'CREATE')) {
            if (($status == 'SUCCESS') || ($status == 'FAILED')) {
              $newLine = "\nvideoIdArray.unshift(".$videoId.");";
              // Tell PHP where it can find the log file and tell PHP to open it
              // and add the string we created earlier to it.
              $logFileLocation = "video-ids.js";
              $fileHandle      = fopen($logFileLocation, 'a') or die("-1");
              chmod($logFileLocation, 0777);
              fwrite($fileHandle, $newLine);
              fclose($fileHandle);
            }
          }
        
          // save full notification for audit trail
          $logEntry = $notification.",\n";
        
          $logFileLocation = "full-log.txt";
          $fileHandle      = fopen($logFileLocation, 'a') or die("-1");
          chmod($logFileLocation, 0777);
          fwrite($fileHandle, $logEntry);
          fclose($fileHandle);
        
        
          echo "Dynamic Ingest callback app is running";
          ?>
          
          

    Fichier JSON:

    Le fichier JSON est initialement un tableau vide ( [] ) - les données sont ajoutées par le gestionnaire de notification.

    Tableau de Bord

    Le tableau de bord comprend le code HTML et le code JavaScript permettant de récupérer les données de notification et des données vidéo supplémentaires à partir du fichier. CMS API et écrivez les résultats dans un tableau:

          <!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>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;
              /**
              * 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.renditions = 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 === 'DYNAMIC_RENDITION') {
                    // increment the renditions account
                    videoDataArray[objIndex].renditions++;
                  }
                } 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...';
                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.renditions + '</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);
                              // process the notifications
                              kMax = dataArray.length;
                              for (k = 0; k < kMax; k++) {
                              processNotification(dataArray[k]);
                            }
                            getVideoInfo();
                            break;
                          case 'video':
                            parsedData = JSON.parse(responseData);
                            videoDataArray[currentIndex].reference_id = parsedData.reference_id;
                            videoDataArray[currentIndex].name = parsedData.name;
                            currentIndex++;
                            if (currentIndex < iMax) {
                            currentVideo = videoDataArray[currentIndex];
                            setVideoRequestOptions();
                            } else {
                            writeReport();
                            }
                            break;
                        }
                      } else {
                        console.log('There was a problem with the request. Request returned '', httpRequest.status);
                        if (type === 'video') {
                          setVideoRequestOptions();
                        } else {
                          setSourcesRequestOptions();
                        }
                      }
                    }
                  }
                  catch(e) {
                  console.log('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>
        
        

    procuration

        <?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 entablement
        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;
        ?>
        
        

    Effacer le journal

    Cette simple application PHP restaure simplement le fichier JavaScript dans son état d'origine, effaçant ainsi les anciens identifiants vidéo:

        <?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>';
        ?>
        
        

    Dernière mise à jour de la page le 19 août 2020