獲取數據
當視頻準備就緒時,動態攝取通知會為您提供所有您需要知道的信息-您只需要知道要查找的內容...並定義“就緒”對系統意味著什麼。此圖總結了工作流程:
動態提取通知
動態攝取通知服務向您發送有關多種事件的通知。對於確定視頻“就緒”的時間,最有用的三個是指示已創建特定演繹形式的三個,指示已創建清單的一個,指示所有處理已完成的一個。以下是每個示例:
渲染創建通知
在此示例中註意:
- 的
videoId
值可讓您知道演繹對像是哪個視頻(如果您正在運行多個攝取作業) - 的
profileRefId
值是在攝取配置文件中指定的翻譯的參考ID - 如果
status
值為“ SUCCESS”,表示創建成功 - 對於像HLS或MPEG-DASH之類的分段類型,呈現形式的存在並不能使其可播放-您還需要適當的清單(請參見下一個示例)。MP4 renditons一經創建就可以播放。
清單創建的通知
在此示例中註意:
- 的
videoId
值可讓您知道演繹對像是哪個視頻(如果您正在運行多個攝取作業) - 的
profileRefId
value是一個特殊的代碼,告訴您創建的資產是HLS清單(其他可能的值是HdsManifest
,DashManifest
和SmoothIsmManifest
) - 對於HLS和HDS,將創建一個清單,因此您將看到一個通知。對於DASH和SmoothIsm,將創建兩個清單(一個清單用於舊版Media API,另一個清單用於CMS API),因此您將看到兩個此類型的通知。
- 如果
status
值為“ SUCCESS”,清單創建成功 - 對於像HLS或MPEG-DASH之類的分段類型,創建再現和清單沒有明確的順序-這些再現無法創建,除非兩個都創建(或者視頻已被完全處理-參見下一個示例)。
處理完成通知
在此示例中註意:
- 的
videoId
值可讓您知道演繹對像是哪個視頻(如果您正在運行多個攝取作業) - 的
profileRefId
是不包含在此通知中 - 如果
status
值為“ SUCCESS”,視頻已成功處理
要接收通知,您需要在其中包含“回調”字段Dynamic Ingest API請求,指向一個或多個回調地址:
{
"master": {
"url": "https://s3.amazonaws.com/bucket/mysourcevideo.mp4"
}, "profile": "high-resolution",
"callbacks": ["http://host1/path1”, “http://host2/path2”]
}
樣板儀表板
本節說明如何將通知組合在一起以為Dynamic Ingest API構建簡單的儀表板。通知處理程序解析來自Dynamic Ingest API識別處理完成的通知。然後,它將視頻通知添加到JSON文件中每個視頻的對像數組中。儀表板本身是一個HTML頁面,該頁面導入JSON文件以獲取通知數據。它使用ID向CMS API獲取視頻元數據。您可以查看儀表板這裡。
該應用程序的所有文件以及為您的帳戶進行設置的說明均在這個倉庫。
這是應用程序的高級架構:
應用程式零件
通知處理程序內置於PHP中-用於查找完整的通知,並將視頻ID添加到單獨JavaScript文件中的數組中:
<?php
// var以記錄錯誤(如果有)
$ 問題 =「無錯誤」;
// var存儲當前視頻索引
$ videoIndex = -1;
//獲取輸入數據
嘗試{
$ JSON = 文件的內容('PHP://輸入');
$ 解碼 = 解碼($ JSON,真);
} catch(Exception $ e){
$ 問題 = $ 電子-> 獲取消息();
迴聲$問題;
}
//獲取數據文件內容並解析
嘗試{
$ notificationData = file_get_contents('di.json');
$ notificationDataDecoded = json_decode($ notificationData,true);
} catch(Exception $ e){
$ 問題 = $ 電子-> 獲取消息();
迴聲$問題;
}
如果(isset($ decoded [“ entityType”])){
$ 實體類型 = $ 解碼 ["實體類型"];
//如果實體類型為ASSET或TITLE,則將其添加到通知數據數組
如果($ entityType ==“ ASSET” || $ entityType ==“ TITLE”){
array_push($ notificationDataDecoded,$ decoded);
}
//現在,我們將用現有的內容替換di.json的內容
file_put_contents('di.json',json_encode($ notificationDataDecoded));
}
回顯“ Dynamic Ingest回調應用程序正在運行”;
var_dump($ notificationData);
?>
JSON檔案:
JSON文件最初是一個空數組([]
)-數據由通知處理程序添加。
儀表板
信息中心包含HTML和JavaScript,可從中獲取通知數據和其他視頻數據CMS API並將結果寫到表中:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Dynamic Ingest Log</title>
<style>
body {
font-family: sans-serif;
margin: 5em;
}
.hide {
display: none;
}
.show {
display: block;
}
table {
border-collapse: collapse;
border: 1px #999999 solid;
}
th {
background-color: #666666;
color: #f5f5f5;
padding: .5em;
font-size: .7em;
}
td {
border: 1px #999999 solid;
font-size: .7em;
padding: .5em
}
.hidden {
display: none;
}
</style>
</head>
<body>
<h1>Dynamic Ingest Log</h1>
<h2>Account: Brightcove Learning (57838016001)</h2>
<p style="width:70%">
Videos are listed in order of processing completion time, newest to oldest. The reference id (generated by the <a href="./di-tester.html">Dynamic Ingest tester</a>) is a combination of the date/time that the Dynamic Ingest job was initiated and the ingest profile that was used. You can add additional videos using the <a href="./di-tester.html">Dynamic Ingest tester</a>. New videos will appear in this log after processing is complete.
</p>
<p>
<button id="clearLogBtn">Clear the log</button>
</p>
<div id="videoLogBlock">
<table>
<thead>
<tr>
<th>Video ID</th>
<th>Name</th>
<th>Reference ID</th>
<th>HLS Manifests Created</th>
<th>HLS Renditions Created</th>
<th>MP4 Renditions Created</th>
<th>Processing Complete</th>
</tr>
</thead>
<tbody id="logBody"></tbody>
</table>
<h4 id="loadingMessage">Loading data, please wait...</h4>
</div>
<script>
var BCLS = ( function (window, document) {
// to use another account, set the account_id value appropriately
// the client_id and client_secret will also need to be changed in the proxy
var my_account_id = 57838016001,
account_id = my_account_id,
logBody = document.getElementById('logBody'),
loadingMessage = document.getElementById('loadingMessage'),
clearLogBtn = document.getElementById('clearLogBtn'),
i = 0,
iMax,
// set the proxyURL to the location of the proxy app that makes Brightcove API requests
proxyURL = './brightcove-learning-proxy.php',
dataFileURL = './di.json',
videoDataArray = [],
requestOptions = {},
currentVideo,
currentIndex = 0;
/**
* Logging function - safe for IE
* @param {string} context - description of the data
* @param {*} message - the data to be logged by the console
* @return {}
*/
function bclslog(context, message) {
if (window["console"] && console["log"]) {
console.log(context, message);
}
return;
}
/**
* tests for all the ways a variable might be undefined or not have a value
* @param {*} x the variable to test
* @return {Boolean} true if variable is defined and has a value
*/
function isDefined(x) {
if ( x === '' || x === null || x === undefined || x === NaN) {
return false;
}
return true;
}
/**
* find index of an object in array of objects
* based on some property value
*
* @param {array} targetArray - array to search
* @param {string} objProperty - object property to search
* @param {string|number} value - value of the property to search for
* @return {integer} index of first instance if found, otherwise returns null
*/
function findObjectInArray(targetArray, objProperty, value) {
var i, totalItems = targetArray.length, objFound = false;
for (i = 0; i < totalItems; i++) {
if (targetArray[i][objProperty] === value) {
objFound = true;
return i;
}
}
if (objFound === false) {
return null;
}
}
/**
* factory for new video objects
* @param {String} videoId the video id
* @return {object} the new object
*/
function makeVideoDataObject(videoId) {
var obj = {};
obj.id = videoId;
obj.name = '';
obj.reference_id = '';
obj.hlsManifests = 0;
obj.hlsRenditions = 0;
obj.mp4Renditions = 0;
obj.complete = 'no';
return obj;
}
/**
* processes notification objects
* creates a new object in the videoDataArray if it doesn't exist
* and updates the videoDataArray object based on the notification
* @param {Object} notificationObj the raw notification object
*/
function processNotification(notificationObj) {
var objIndex, videoObj;
// if notification object contains a video id, find the corresponding
// object in the videoDataArray or create it if it's not there
if (isDefined(notificationObj) && isDefined(notificationObj.videoId)) {
objIndex = findObjectInArray(videoDataArray, 'id', notificationObj.videoId);
// if not found, create one
if (!isDefined(objIndex)) {
videoObj = makeVideoDataObject(notificationObj.videoId);
videoDataArray.push(videoObj);
objIndex = videoDataArray.length - 1;
}
// now update properties based on what's in the notification
if (notificationObj.entityType === 'ASSET') {
// if it's a rendition or manifest, there will be a profileRefId
if (isDefined(notificationObj.profileRefId)) {
// see if it's an HLS manifest
if (notificationObj.profileRefId === 'HlsManifest') {
// increment the hls manifest count
videoDataArray[objIndex].hlsManifests++;
} else if (notificationObj.profileRefId.charAt(0) === 't') {
// increment the hls rendition count
videoDataArray[objIndex].hlsRenditions++;
} else if (notificationObj.profileRefId.charAt(0) === 'm') {
// increment the mp4 rendition count
videoDataArray[objIndex].mp4Renditions++;
}
}
} else if (notificationObj.entityType === 'TITLE') {
// overall processing notification - checked for SUCCESS / FAILED
if (notificationObj.status === 'SUCCESS') {
// mark complete
videoDataArray[objIndex].complete = 'yes';
} else if (notificationObj.status === 'FAILED') {
// mark failed
videoDataArray[objIndex].complete = 'failed';
}
}
}
return;
}
/**
* creates the dashboard table body
*/
function writeReport() {
var j,
jMax = videoDataArray.length,
item,
t;
loadingMessage.textContent = 'This page will refresh in 1 minute...';
/* just showing HLS and MP4 renditions, because
* that's all that will be produced in this account,
* but you could modify the notification handler and
* this page to handle other formats
*/
for (j = 0; j < jMax; j++) {
item = videoDataArray[j];
if (item.id !== undefined) {
logBody.innerHTML += '<tr><td>' + item.id + '</td><td>' + item.name + '</td><td>' + item.reference_id + '</td><td>' + item.hlsManifests + '</td><td>' + item.hlsRenditions + '</td><td>' + item.mp4Renditions + '</td><td>' + item.complete + '</td></tr>';
}
}
// set timeout for refresh
t = window.setTimeout(init, 60000);
};
// function to set up the notification data request
function setJSONRequestOptions() {
submitRequest(null, dataFileURL, 'notificationData');
}
// function to set up video data request
function setVideoRequestOptions() {
requestOptions = {};
requestOptions.url = 'https://cms.api.brightcove.com/v1/accounts/' + account_id + '/videos/' + currentVideo.id;
submitRequest(requestOptions, proxyURL, 'video');
}
/**
* initiates the CMS API requests
*/
function getVideoInfo() {
iMax = videoDataArray.length;
if (currentIndex < iMax) {
currentVideo = videoDataArray[currentIndex];
setVideoRequestOptions();
} else {
loadingMessage.innerHTML = 'No videos have been ingested - you can add some using the <a href="./di-tester.html">Dynamic Ingest tester</a>';
}
}
/**
* make the CMS API requests
* @param {Object} options request options
* @param (String) url URL to send request to
* @param (String) type the request type
*/
function submitRequest(options, url, type) {
var httpRequest = new XMLHttpRequest(),
requestData,
responseData,
videoDataObject,
parsedData,
getResponse = function () {
try {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
responseData = httpRequest.responseText;
switch (type) {
case 'notificationData':
var k, kMax, dataArray;
dataArray = JSON.parse(responseData);
bclslog('dataArray', dataArray);
// process the notifications
kMax = dataArray.length;
for (k = 0; k < kMax; k++) {
processNotification(dataArray[k]);
}
getVideoInfo();
break;
case 'video':
parsedData = JSON.parse(responseData);
bclslog('parsedData', parsedData);
videoDataArray[currentIndex].reference_id = parsedData.reference_id;
videoDataArray[currentIndex].name = parsedData.name;
currentIndex++;
if (currentIndex < iMax) {
currentVideo = videoDataArray[currentIndex];
setVideoRequestOptions();
} else {
writeReport();
}
break;
}
} else {
bclslog("There was a problem with the request. Request returned " + httpRequest.status);
if (type === 'video') {
setVideoRequestOptions();
} else {
setSourcesRequestOptions();
}
}
}
}
catch(e) {
bclslog('Caught Exception: ' + e);
}
};
// notifications data is a special case
if (type === 'notificationData') {
// set response handler
httpRequest.onreadystatechange = getResponse;
// open the request
httpRequest.open("GET", url);
// set headers
httpRequest.setRequestHeader("Content-Type", "application/json");
// open and send request
httpRequest.send();
} else {
// requests via proxy
// set up request data
requestData = "url=" + encodeURIComponent(options.url) + "&requestType=GET";
// set response handler
httpRequest.onreadystatechange = getResponse;
// open the request
httpRequest.open("POST", url);
// set headers
httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// open and send request
httpRequest.send(requestData);
}
};
// event handlers
clearLogBtn.addEventListener('click', function () {
if (window.confirm('Are you sure? This action cannot be undone!')) {
// if your clear-log app resides in another location, change the URL
window.location.href = 'clear-log.php';
}
});
// get things started
function init() {
// clear table and the video data array
logBody.innerHTML = "";
videoDataArray = [];
setJSONRequestOptions();
}
// kick off the app
init();
})(window, document);
</script>
</body>
</html>
代理
<?php
/**
* brightcove-learning-proxy.php-布萊特灣休息風格 API 的代理
* 獲取訪問令牌,發出請求,並返回響應
* 存取:
* 網址:https://solutions.brightcove.com/bcls/bcls-proxy/bcsl-proxy.php
*(請注意,您應該 * 總是 * 通過 HTTPS 訪問代理)
* 方法:開機自檢
*
* @post {字符串} 網址-API 請求的 URL
* @post {字符串} [請求類型 = 獲取]-請求的 HTTP 方法
* @post {字符串} [請求體 = 空]-JSON 數據與寫入請求一起發送
*
* @returns {字符串} $ 響應-從 API 接收到的 JSON 響應
*/
// CORS啟用
header(“ Access-Control-Allow-Origin:*”);
//設置訪問令牌的請求
$ 數據 = 數組();
//
//變更下列值,將此代理伺服器用於不同的帳戶
//
$ 客戶端代碼 =「您的客戶端 _ ID」;
$ 客戶機密 =「你的客戶 _ 秘密 _ 這裡」;
$ 驗證字符串 =「{$ 客戶端}:{$ 客戶端 _ 秘密}」;
請求 = "https://oauth.brightcove.com/v4/access_token?grant_type=client_credentials「;
$ 查詢 = 初始化($ 請求);
curl_setopt_array($ ch,array(
CURLOPT_POST => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_SSL_VERIFYPEER =>否,
CURLOPT_USERPWD => $ auth_string,
CURLOPT_HTTPHEADER =>數組(
'內容類型:應用程序 /x-www 形式的 URL 代碼',
)、
CURLOPT_POSTFIELDS => $ data
);
$ 響應 = 捲曲($ 查詢);
curl_close($ ch);
//檢查錯誤
if($ response === FALSE){
die(curl_error($ ch));
}
//解碼響應
$ 響應數據 = json_解碼($ 響應,真);
$ 訪問令牌 = $ 響應數據 ["訪問令牌"];
//設定 API 呼叫
//取得資料
如果($ _POST [“ requestBody”]){
$ 數據 = 解碼($ _POST ["請求主體"]);
}其他{
$ 數據 = 數組();
}
//獲取請求類型或默認為 GET
如果($ _POST [“ requestType”]){
$ 方法 = $_POST ["請求類型"];
}其他{
$ 方法 =「獲取」;
}
//從表單數據獲取 URL 和授權信息
$ 請求 = $ _ 郵政 ["網址"];
//傳送http 請求
$ 查詢 = 初始化($ 請求);
curl_setopt_array($ ch,array(
CURLOPT_CUSTOMREQUEST => $方法,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_SSL_VERIFYPEER =>否,
CURLOPT_HTTPHEADER =>數組(
'內容類型:應用程序/json',
「授權:承載人 {$ 訪問令牌}」,
)、
CURLOPT_POSTFIELDS => json_encode($ data)
);
$ 響應 = 捲曲($ 查詢);
curl_close($ ch);
//檢查錯誤
if($ response === FALSE){
迴聲“錯誤:” + $響應;
die(curl_error($ ch));
}
//解碼響應
//$ 響應數據 = json_解碼($ 響應,真);
//將響應返回給 AJAX 調用者
echo $ response;
?>
清除記錄
這個簡單的PHP應用程序只是將JavaScript文件恢復為原始狀態,清除了舊的視頻ID:
<?php
$ 日誌文件位置 =「di.json」;
$ 新鮮內容 = 數組();
$ 編碼內容 = json_ 編碼($ 新鮮內容);
file_put_contents($ logFileLocation,$ encodedContent);
回顯“日誌文件已清除-<a href="di-log.html">返回儀表板</a>”;
?>