Daten abrufen
Die Dynamic Ingest-Benachrichtigungen geben Ihnen alle Informationen, die Sie benötigen, um zu wissen, wann Ihr Video fertig ist - Sie müssen nur wissen, worauf Sie achten müssen... und definieren, was „bereit“ für Ihre Systeme bedeutet. Dieses Diagramm fasst den Arbeitsablauf zusammen:
Dynamische Ingest-Benachrichtigungen
Der Dynamic Ingest-Benachrichtigungsdienst sendet Ihnen Benachrichtigungen für verschiedene Arten von Ereignissen. Die drei, die am nützlichsten sind, um herauszufinden, wann das Video "fertig" ist, sind diejenigen, die angeben, dass bestimmte Wiedergaben erstellt wurden, diejenigen, die anzeigen, dass ein Manifest erstellt wurde, und diejenigen, die anzeigen, dass die gesamte Verarbeitung abgeschlossen ist. Hier sind Beispiele für jeden:
Rendition hat eine Benachrichtigung erstellt
{
"entity": "5002412132001",
"profileRefId": "ts7",
"accountId": "57838016001",
"entityType": "ASSET",
"videoId": "5002361893001",
"status": "SUCCESS",
"version": "1",
"action": "CREATE",
"jobId": "bb316631-c58b-4bd4-a686-13c5f7a3a779"
}
Hinweis in diesem Beispiel:
- Der
videoId
Wert lässt Sie wissen, für welches Video die Formatvariante gilt (falls Sie mehrere Aufgabe-Jobs ausführen) - Das
profileRefId
value ist die Referenz-ID für die im Aufnahmeprofil angegebene Wiedergabe - wenn die
status
Wert ist "SUCCESS", die Wiedergabe wurde erfolgreich erstellt - Bei einem segmentierten Typ wie HLS oder MPEG-DASH ist die Wiedergabe aufgrund der Wiedergabe nicht spielbar. Sie benötigen außerdem das entsprechende Manifest (siehe nächstes Beispiel). MP4-Renditons können abgespielt werden, sobald sie erstellt wurden.
Manifest erstellte Benachrichtigung
{
"jobId": "31f0b112-9890-4567-adb5-0f4ed1673701",
"status": "SUCCESS",
"version": "1",
"action": "CREATE",
"entityType": "ASSET",
"entity": "5002412528001",
"videoId": "5002361895001",
"profileRefId": "HlsManifest",
"accountId": "57838016001"
}
Hinweis in diesem Beispiel:
- Der
videoId
Wert lässt Sie wissen, für welches Video die Formatvariante gilt (falls Sie mehrere Aufgabe-Jobs ausführen) - Das
profileRefId
value ist ein spezieller Code, der angibt, dass das erstellte Asset ein HLS-Manifest war (die anderen möglichen Werte sindHdsManifest
,DashManifest
, undSmoothIsmManifest
) - Für HLS und HDS wird ein Manifest erstellt, sodass eine Benachrichtigung angezeigt wird. Für DASH und SmoothIsm werden zwei Manifeste erstellt (eines zur Verwendung in der Legacy-Medien-API, das andere für die CMS-API), sodass zwei Benachrichtigungen dieses Typs angezeigt werden.
- Wenn die
status
Wert ist "SUCCESS", das Manifest wurde erfolgreich erstellt - Für einen segmentierten Typ wie HLS oder MPEG-DASH gibt es keine bestimmte Reihenfolge für die Erstellung der Wiedergaben und des Manifests. Diese Wiedergaben können erst abgespielt werden, wenn beide erstellt wurden (oder das Video vollständig verarbeitet wurde - siehe nächstes Beispiel).
Komplette Benachrichtigung wird verarbeitet
{
"entityType": "TITLE",
"status": "SUCCESS",
"accountId": "57838016001",
"entity": "5002412652001",
"action": "CREATE",
"jobId": "3e98b3a0-f624-4f2d-81c1-4e43e1d04a0f",
"version": "1",
"videoId": "5002412652001"
}
Hinweis in diesem Beispiel:
- Der
videoId
Wert lässt Sie wissen, für welches Video die Formatvariante gilt (falls Sie mehrere Aufgabe-Jobs ausführen) - Das
profileRefId
ist nicht in dieser Benachrichtigung enthalten - Wenn die
status
Wert ist "ERFOLG", das Video wurde erfolgreich verarbeitet
Um Benachrichtigungen zu erhalten, müssen Sie in Ihre Dynamic Ingest API Anfragen ein Feld „Rückrufe“ einfügen, das auf eine oder mehrere Rückrufadressen verweist:
{
"master": {
"url": "https://s3.amazonaws.com/bucket/mysourcevideo.mp4"
}, "profile": "high-resolution",
"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 zu erstellen. Der Handler für Benachrichtigungen analysiert Benachrichtigungen von der, Dynamic Ingest API um vollständige Benachrichtigungen für die Verarbeitung zu identifizieren. Anschließend fügt er die Video-Benachrichtigungen für jedes Video in einer JSON-Datei in ein Array von Objekten ein. 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 CMS-API zu stellen, um die Video-Metadaten zu erhalten. Sie können das Dashboard anzeigen Hier.
Alle Dateien für diese App sowie Anweisungen zum Einrichten für Ihr Konto befinden sich in dieses Repository.
Hier ist die hochrangige Architektur der App:
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 einem Array in einer separaten JavaScript-Datei hinzu:
<?php
// var, um Fehler zu protokollieren, falls vorhanden
$ Problem = „Keine Fehler“;
// var, um den aktuellen Videoindex zu speichern
$ videoIndex = -1;
// Eingabedaten abrufen
versuche {
$json = file_get_contents ('php: //insput');
$ decodiert = json_decode ($ json, true);
} catch (Ausnahme $e) {
$ Problem = $ e- > getMessage ();
echo $ Problem;
}
// Den Inhalt der Datendatei abrufen und analysieren
versuche {
$ notificationData = file_get_contents ('di.json');
$ notificationDataDecoded = json_decode ($ notificationData, true);
} catch (Ausnahme $e) {
$ Problem = $ e- > getMessage ();
echo $ Problem;
}
if (isset ($ decodiert ["entityType"])) {
$entityType = $ decodiert ["entityType"];
// Wenn der Entitätstyp ASSET oder TITLE ist, fügen Sie ihn dem Benachrichtigungsdatenarray hinzu
if ($ entityType == "ASSET" || $ entityType == "TITLE") {
array_push ($ notificationDataDecoded, $ decoded);
}
// Jetzt ersetzen wir den Inhalt von di.json durch den Inhalt, den wir haben
file_put_contents ('di.json', json_encode ($ notificationDataDecoded));
}
echo „Dynamic Ingest-Rückruf-App läuft“;
var_dump ($ notificationData);
?>
JSON-Datei:
Die JSON-Datei ist anfangs ein leeres Array ([]
) - Daten werden vom Benachrichtigungshandler hinzugefügt.
Dashboard
Das Dashboard enthält HTML und JavaScript, um die Benachrichtigungsdaten und zusätzliche Videodaten aus dem abzurufen CMS API und die Ergebnisse in eine Tabelle zu schreiben:
<!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 für Brightcove RESTful APIs
* erhält ein Zugriffstoken, stellt die Anfrage und gibt die Antwort zurück
* Zugriff:
* URL: https://solutions.brightcove.com/bcls/bcls-proxy/bcsl-proxy.php
* (beachten Sie, dass Sie *immer* über HTTPS auf den Proxy zugreifen sollten)
* Methode: POST
*
* @post {string} url - Die URL für die API-Anfrage
* @post {string} [requestType=Get] - HTTP-Methode für die Anfrage
* @post {string} [requestBodE=NULL] - JSON-Daten, die mit Schreibanfragen gesendet werden
*
* @returns {string} $response - JSON-Antwort von der API erhalten
*/
// CORS-Aktivierung
header („Access-Control-Allow-Origin: *“)
//Richten Sie eine Anfrage für Zugriffstoken ein
$ data = Array ();
//
//ändere die Werte unten, um diesen Proxy mit einem anderen Konto zu verwenden
//
$client_id = „YOUR_CLIENT_ID_HERE“;
$client_secret = „YOUR_CLIENT_SECRET_HERE“;
$auth_string = „{$client_id}: {$client_secret}“;
$ Anfrage = "https://oauth.brightcove.com/v4/access_token?grant_type=client_credentials „;
$ ch = curl_init ($ Anfrage);
curl_setopt_array ($ ch, Array (
CURLOPT_POST = > WAHR,
CURLOPT_RETURNTRANSFER = > WAHR,
CURLOPT_SSL_VERIFYPEER = > FALSCH,
CURLOPT_USERPWD = > $ auth_string,
CURLOPT_HTTPHEADER = > Array (
'Content-Typ: Anwendung/x-www-form-urlencoded',
)
CURLOPT_POSTFIELDS > = Daten
));
$ response = curl_exec ($ ch);
curl_close ($ ch);
//Auf Fehler prüfen
wenn ($ Antwort === FALSCH) {
sterben (curl_error ($ ch));
}
//Dekodiere die Antwort
$responseData = json_decode ($ Antwort, TRUE);
$access_token = $ responseData ["access_token"];
//Richten Sie den API-Aufruf ein
//Daten abrufen
wenn ($_POST ["requestBody"]) {
$ data = json_decode ($ _POST ["requestBody"]);
} else {
$ data = Array ();
}
//Anfragetyp abrufen oder Standard zu GET
wenn ($_POST ["requestType"]) {
$ Methode = $ _POST ["requestType"];
} else {
$ Methode = „GET“;
}
//Erhalte die URL- und Autorisierungsinformationen aus den Formulardaten
$ request = $ _POST ["URL"];
//senden Sie die HTTP-Anfrage
$ ch = curl_init ($ Anfrage);
curl_setopt_array ($ ch, Array (
CURLOPT_CUSTOMREQUEST = > $ Methode,
CURLOPT_RETURNTRANSFER = > WAHR,
CURLOPT_SSL_VERIFYPEER = > FALSCH,
CURLOPT_HTTPHEADER = > Array (
'Content-Typ: Anwendung/JSON',
„Berechtigung: Träger {$ access_token}“,
)
CURLOPT_POSTFIELDS = > json_encode ($ Daten)
));
$ response = curl_exec ($ ch);
curl_close ($ ch);
//Auf Fehler prüfen
wenn ($ Antwort === FALSCH) {
echo „Fehler: „+$ Antwort;
sterben (curl_error ($ ch));
}
//Dekodiere die Antwort
//$responseData = json_decode ($ Antwort, TRUE);
//Antwort an den AJAX-Anrufer zurückgeben
echo $ Antwort;
?>
Löschen Sie das Protokoll
Diese einfache PHP-App stellt einfach die JavaScript-Datei in ihren ursprünglichen Zustand 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-Datei gelöscht - < ein href=“ di-log.html "> gehe zurück zum Dashboard < /a > ';
?>