Support Kontakt Support | Systemstatus Systemstatus
Seiteninhalt

    Abrufen des Status von Dynamic Ingest-Anfragen

    Wenn Sie die Dynamic Ingest API Videos zu deinem hinzufügen Video Cloud Was Sie am meisten wissen möchten, ist, wann das Video verarbeitet wurde und ob Wiedergaben erfolgreich erstellt wurden oder nicht.

    Einführung

    In diesem Dokument wird erläutert, wie Sie den Status von Jobs verfolgen können, indem Sie entweder Statusanfragen an den Server senden CMS API oder unter Verwendung von Dynamic Ingest API Benachrichtigungen. Wir bieten auch eine Beispiel-Dashboard-App, die den Prozess automatisiert

    Beachten Sie, dass der Status von Aufnahmeaufträgen nur für Aufträge verfügbar ist, die mit den letzten 7-Tagen übermittelt wurden.

    Status anfordern

    Sie erhalten den Status von dynamischen Ingest-Jobs (Ingest, Replacement oder Retranscode) folgende CMS API Endpunkte - Beachten Sie, dass diese Endpunkte für funktionieren Nur dynamische Bereitstellungsjobs:

    Status für alle Jobs abrufen

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

    Die Antwort sieht etwa so aus:

         [
          {
            "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"
          }
        ]

    Status für bestimmte Jobs abrufen

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

    Die Antwort sieht etwa so aus:

        {
            "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"
          }

    Die möglichen Werte für state sind:

    • processing: Verarbeitung, Video ist noch nicht abspielbar
    • publishing: Es wurde mindestens eine abspielbare Wiedergabe erstellt, und das Video wird für die Wiedergabe vorbereitet
    • published: Mindestens eine Wiedergabe ist für die Wiedergabe verfügbar
    • finished: at least one audio/video rendition has been processed
    • failed: Verarbeitung gescheitert; Wenn Sie nicht herausfinden können, was schiefgegangen ist, wenden Sie sich an den Support

    Benachrichtigungen erhalten

    Wenn die oben beschriebene Anforderungsstatusmethode funktioniert, sollten Sie auf einen bestimmten Status warten (published or finished) ist es besser, sich von Brightcove benachrichtigen zu lassen, wenn diese Ereignisse eintreten, als ständig nach dem Status zu fragen, bis Sie die gewünschte Antwort erhalten. Wir werden uns nun ansehen, wie Sie eine App zum Umgang mit Benachrichtigungen erstellen können.

    Die Dynamic Ingest Benachrichtigungen geben Ihnen alle Informationen, die Sie wissen müssen, wenn Ihr Video fertig ist - Sie müssen nur wissen, wonach Sie suchen müssen ... und definieren, was "ready" für Ihre Systeme bedeutet. Dieses Diagramm fasst den Arbeitsablauf zusammen:

    Status Workflow einlesen
    Status Workflow einlesen

    Dynamische Ingest Benachrichtigungen

    Der Benachrichtigungsdienst Dynamic Ingest sendet Ihnen Benachrichtigungen für verschiedene Arten von Ereignissen. Die beiden, die am nützlichsten sind, um herauszufinden, wann das Video "bereit" ist, sind solche, die anzeigen, dass bestimmte Wiedergabeversionen erzeugt wurden, und diejenigen, die anzeigen, dass die Verarbeitung vollständig ist. Hier sind Beispiele von jedem:

    Dynamische Wiedergabe erstellt Benachrichtigung

        {
          "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"
        }
        
        
    Benachrichtigung für Wiedergabe erstellt

    Beachten Sie in diesem Beispiel:

    • Das videoId Mit value können Sie feststellen, für welches Video die Wiedergabe gedacht ist (falls mehrere Ingest-Jobs ausgeführt werden).
    • Das entity value ist der erstellte dynamische Wiedergabetyp
    • wenn die status Wert ist "ERFOLGREICH", die Wiedergabe wurde erfolgreich erstellt

    Verarbeitung der vollständigen Benachrichtigung

        {
          "entity": "5660367449001",
          "entityType": "TITLE",
          "version": "1",
          "action": "CREATE",
          "jobId": "d3ef8751-2b88-4141-95d5-83f0393aca07",
          "videoId": "5660367449001",
          "accountId": "57838016001",
          "status": "SUCCESS"
        }
        
        
    Benachrichtigung für die Verarbeitung abgeschlossen

    Beachten Sie in diesem Beispiel:

    • Das videoId und zum jobId Werte zeigen an, für welches Video das ist (falls mehrere Ingest-Jobs laufen)
    • Wenn die status Wert ist "ERFOLGREICH", das Video wurde erfolgreich verarbeitet

    Um Benachrichtigungen zu erhalten, müssen Sie ein Feld "Rückrufe" in sich einfügen Dynamic Ingest API Anfragen, die auf eine oder mehrere Callback-Adressen verweisen:

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

    Beispiel-Dashboard

    In diesem Abschnitt wird erläutert, wie Benachrichtigungen zusammengestellt werden können, um ein einfaches Dashboard für die Dynamic Ingest API. Der Handler für Benachrichtigungen analysiert Benachrichtigungen vom Dynamic Ingest API zur Identifizierung der verarbeitenden Meldungen. Anschließend werden die Videobenachrichtigungen zu einem Array von Objekten für jedes Video in einer JSON-Datei hinzugefügt. Das Dashboard selbst ist eine HTML-Seite, die die JSON-Datei importiert, um die Benachrichtigungsdaten abzurufen. Es verwendet die IDs, um eine Anfrage an die zu senden CMS API um die Video-Metadaten zu erhalten.

    Hier ist die High-Level-Architektur der App:

    Ingest Dashboard-Architektur
    Ingest Dashboard-Architektur

    Die App Teile

    Der Handler für Benachrichtigungen ist in PHP integriert - er sucht nach der Verarbeitung vollständiger Benachrichtigungen und fügt die Video-ID zu einem Array in einer separaten JavaScript-Datei hinzu:

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

    JSON-Datei:

    Die JSON-Datei ist anfänglich ein leeres Array ( [] ) - Daten werden vom Benachrichtigungshandler hinzugefügt.

    Übersicht

    Das Dashboard enthält HTML und JavaScript, um die Benachrichtigungsdaten und zusätzliche Videodaten aus dem Internet abzurufen CMS API und schreibe die Ergebnisse in eine Tabelle:

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

    Proxy

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

    Löschen Sie das Protokoll

    Diese einfache PHP-App stellt nur die Originalversion der JavaScript-Datei wieder her und löscht die alten Video-IDs:

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

    Seite zuletzt aktualisiert am 22. Oktober 2020