XMLHttpRequest()
和一個代理。 然後,在本文的後面部分將更深入地討論示例代碼。 第一個示例使用 Analytics API 檢索並顯示在 Brightcove player 控制欄當前在視頻中的觀看次數 player 曾有過。 第二個示例(稍微複雜一點)使用 Analytics API 連同 Brightcove Player 目錄以從帳戶中檢索最受歡迎的視頻並將其顯示在播放列表中。 本文檔中的代碼討論將集中於從正確的REST API檢索所需的數據。高級視圖
要使用REST API,您需要準備一些內容。 簡而言之,它們是:
- 客戶代碼:客戶端代碼要求輸入特定數據,然後根據應用程序要求將其顯示。 本文檔中將詳細討論客戶端代碼,因為這是您最需要編寫的內容。
- 代理服務器:出於安全原因,REST API不會直接接受來自客戶端的數據請求,因為這會鼓勵從客戶端發送機密信息,例如客戶端憑據。 這意味著代理將充當客戶端和REST API之間的中介。 在示例中使用的代理是用PHP編寫的,並在本文檔的後面進行討論。 代理必須在您控制的服務器上設置,並且可以使用您選擇的語言編寫。 建議的代理配置使它可以編寫一次並由任何API使用。
- REST API:Brightcove提供了一套全面的API,用於自定義,擴展和與Brightcove平台集成。 見 概述: Video Cloud APIs 文檔以獲取更多信息。
下圖顯示了流程的三個核心實體之間的交互,以從Brightcove的REST API中檢索數據:

客戶端功能概述
客戶端代碼會發生很大變化,具體取決於您從哪個API請求數據。 如上所述,代理是一次寫入且不修改代碼段,並且API由Brightcove維護。 這就是為什麼文檔中的重點將放在學習如何更改客戶端代碼以從API之一中檢索所需數據的原因。
下圖重點介紹了客戶端代碼的關鍵部分,它們是:
- 使
HTTPRequest
給代理。 為了避免歧義,函數被命名為makeRequest()
。 它顯示在下圖的右側。 - 收集請求所需信息的代碼。 它顯示在圖的左上方。 這段代碼通常非常簡單明了,並使用了初學者都熟知的概念。
- 執行前面提到的調用
makeRequest()
功能。 它顯示在圖的左下方。 調用將一個函數傳遞給makeRequest()
作為參數。 然後在makeRequest()
該函數被調用。 這是一個匿名定義的例子 回電話 的功能。
您會在圖中看到兩個部分,標記為 異步活動。 儘管在圖中在兩個不同的位置表示,但這實際上是相同的異步活動,並且表示未知的時間:
- 客戶端將請求發送到代理。
- 代理從API請求數據。
- 用於構建結果集並將其返回給代理的API。
- 代理將數據返回給客戶端。
請注意,調用框中的邏輯流箭頭 makeRequest()
(左下角的方框)似乎表明代碼是在兩個不同的時間執行的,情況確實如此。 對該函數進行了調用,但直到執行回調函數 makeRequest()
已完成其工作並執行了回調函數,該回調函數將請求的數據返回到函數調用代碼。

示例代碼演練
與其將代碼視為一個整體,不如將其分部分介紹和討論。 其中一些部分與上圖有關。
標準 player 碼
此代碼部分包含基本內容 Brightcove Player 頁內嵌入代碼。
- 第11-21行:標準 Brightcove Player 加上一個代碼
id
屬性已添加。
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
</head>
<body>
<video-js id="myPlayerID"
data-video-id="3851380732001"
data-account="1752604059001"
data-player="HkAzSmB0l"
data-embed="default"
data-application-id
class="video-js"
controls
width="640"
height="360"></video-js>
<script src="https://players.brightcove.net/1752604059001/HkAzSmB0l_default/index.min.js"></script>
準備撥打電話
此代碼部分初始化變量,並準備進行調用 makeRequest()
。 一般來說,對於讀取請求,您將需要提供以下信息:
- 例如,您將使用的代理的URL(當然,這需要您控制下的代理):
https://solutions.brightcove.com/bcls/bcls-proxy/doc-samples-proxy-v2.php
- 實際請求所需的URL,通常是動態構建的:
https://analytics.api.brightcove.com/v1/alltime/accounts/1752604059001/videos/4825279519001
- 例如,HTTP方法
GET
.
下面是一個示例:
- 第1行:標準代碼,等到 player 準備與之互動。
- 第2-4行:為代碼後面的所需變量創建/設置值。
- 第7-12行:等待
loadstart
事件如此mediainfo
對像已填充。 分配變量以保存所需的值 Analytics API 端點。 - 第13行:設置調用的HTTP方法。
videojs.getPlayer('myPlayerID').ready(function() {
var myPlayer = this,
accountId = myPlayer.bcinfo.accountId,
options = {};
// +++ Wait for loadstart event so can use mediainfo object +++
myPlayer.on('loadstart', function() {
var videoId = myPlayer.mediainfo.id,
baseURL = 'https://analytics.api.brightcove.com/v1/alltime/accounts/',
endPoint = accountId + '/videos/' + videoId;
options.proxyURL = "https://solutions.brightcove.com/bcls/bcls-proxy/doc-samples-proxy-v2.php";
options.url = baseURL + endPoint;
options.requestType = "GET";
致電 makeRequest()
此代碼段調用 makeRequest()
功能。 請注意,傳遞了兩個參數。 第一個是用於保存端點信息的options對象,第二個是回調函數。 請記住,這是一個異步調用,因此在REST API將數據返回給 makeRequest()
的功能。
- 第1行:致電
makeRequest()
函數,在中傳遞調用所需的值options
賓語。 在這種情況下,對象包含以下內容: - 第3-13行:回調函數定義為匿名函數(以黃色突出顯示)。 請記住,此函數是一個參數,在代碼的後面不會在此處調用。
- 第6、8、10行:
console.log()
顯示以下語句:- API調用返回的原始JSON字符串。
- 由生成的JSON對象
JSON.parse()
從字符串轉換為對象的方法。 - 通過使用簡單的方法從對像中提取的實際視圖計數
object.property
符號。
- 第12行:調用在控件欄中顯示視圖數的函數。
控制台中的以下屏幕截圖顯示了實際顯示的數據 console.log
聲明:

// +++ Make the request to the Analytics API +++
// Extract views from data returned by Analytics API
makeRequest(options, function(viewsRaw) {
var viewsCount;
// Remove console.log command for production code
console.log('viewsRaw', viewsRaw);
viewsObject = JSON.parse(viewsRaw);
console.log('viewsObject', viewsObject);
viewsCount = viewsObject.alltime_video_views;
console.log('views', viewsCount);
// Call function to place data in controlbar
placeCountInControlbar(viewsCount);
});
實際 makeRequest()
功能
本文檔的這一部分將檢查實際定義 makeRequest()
功能。 定義函數的代碼無需修改就可以編寫,而是按原樣重複使用。 您可能會發現不正確的情況,但是對於絕大多數使用而言,無需修改此代碼。
代碼的逐行討論如下:
- 第1-6行:函數定義和變量創建。 關鍵是新
XMLHttpRequest
對像已創建。 - 第8、26行:定義了事件處理函數
readyState
變化。 - 第9、23、25行:使用
try-catch
如果請求在高層失敗。 - 第10、11行:使用
if
聲明以確保請求完成(readyState
是4)並成功完成,狀態為200。 下面顯示了控制台的日誌記錄readyState
以及status
事件處理程序定義中的值: - 第18行:執行了回調函數。 它將返回的數據從API返回給回調函數,如 調用makeRequest() 以上部分。
- 第33行:為
XMLHttpRequest.onreadystatechange
事件。 - 第35行:初始化對代理的請求。
- 第38行:發送異步請求。
function makeRequest(options, callback) {
var httpRequest = new XMLHttpRequest(),
response,
requestParams,
dataString,
proxyURL = options.proxyURL,
// response handler
getResponse = function() {
try {
if (httpRequest.readyState === 4) {
if (httpRequest.status >= 200 && httpRequest.status < 300) {
response = httpRequest.responseText;
// some API requests return '{null}' for empty responses - breaks JSON.parse
if (response === '{null}') {
response = null;
}
// return the response
callback(response);
} else {
alert('There was a problem with the request. Request returned ' + httpRequest.status);
}
}
} catch (e) {
alert('Caught Exception: ' + e);
}
};
/**
* set up request data
* the proxy used here takes the following request body:
* JSON.stringify(options)
*/
// set response handler
httpRequest.onreadystatechange = getResponse;
// open the request
httpRequest.open('POST', proxyURL);
// set headers if there is a set header line, remove it
// open and send request
httpRequest.send(JSON.stringify(options));
}
顯示返回的數據
此代碼顯示如何將返回的數據放入控制欄。 該函數在回調函數的末尾被調用,如下所示 調用makeRequest() 以上部分。
- 第5、16行:定義功能。
- 第6行:為
spacer
控件欄中的元素。 - 第7行:動態創建
div
元件。 - 第9行:在新創建的視圖中放置標籤和視圖的值
div
元件。 - 第11行:使用JavaScript的
document.getElementsByClassName()
獲取控制欄的方法spacer
元件。 - 第13行:設置
spacer
以顯示右對齊的總視圖,並從頂部向下拉10pxspacer
. - 第15行:將新創建,填充和样式化的元素添加到
spacer
.
/**
* Dynamically build a div that is then
* placed in the controlbar's spacer element
*/
function placeCountInControlbar(viewsCount) {
var spacer,
newElement = document.createElement('div');
//Place data in div
newElement.innerHTML = "Total Views: " + viewsCount;
//Get the spacer in the controlbar
spacer = document.getElementsByClassName('vjs-spacer')[0];
//Right justify content in the spacer and add top margin
spacer.setAttribute('style', 'justify-content: flex-end; margin-top: 10px');
//Add the dynamically built div to the spacer in the controlbar
spacer.appendChild(newElement);
}
完整的代碼清單
完整的功能代碼位於以下GitHub存儲庫中: display-views-in-controlbar.html.
簡單調試
如您所見,使用REST API涉及許多方面。 當應用無法正常運行時,這可能會帶來挑戰。 您從哪裡開始調試?
本節提出了一些簡單的建議,它們是開始調試冒險的好地方。 以下兩節為您提供了一種查看所需最基本信息,進行呼叫傳遞的內容以及返回內容的方法。
檢查通話選項
本文檔中討論的客戶端代碼基本上都是關於提供與代理一起使用的正確選項以及相應的實際API的。 因此,知道選項正確對代碼正確運行至關重要。 一種簡單的方法是登錄到控制台 options
在它們傳遞到對象之前 makeRequest
使用它們的功能:

選項對象所包含的內容將隨您嘗試執行的操作而變化,但是某些基礎知識始終存在,其中包括:
- 帳戶ID。 這可以是單獨的屬性,也可以是API端點URL的一部分。
- 代理的URL,這取決於您存儲代理的位置。
- HTTP方法類型,例如
GET
,POST
orPATCH
. - 代理用來從API發出實際請求的API端點URL。 例如:
https://players.api.brightcove.com/v2/accounts/57838016001/players https://edge.api.brightcove.com/playback/v1/accounts/1752604059001/videos/5842800655001 https://analytics.api.brightcove.com/v1/alltime/accounts/1752604059001/videos/4093643993001
根據API請求,選項對像中可能需要其他屬性。 這是您記錄選項對像以請求所有對象時在控制台中看到的示例。 player在特定帳戶中:

這是更新時使用的更複雜的記錄選項對象 players:

查看返回的數據
返回的內容將取決於您請求的數據以及是否返回錯誤。 但是無論返回什麼,您最有可能希望查看返回的數據。 一種簡單的方法是將原始日誌記錄到控制台 response
通話後的數據 makeRequest
功能:

將返回的內容幾乎具有無限的可能性,但以下是一些示例。 第一個顯示了要求所有 player帳戶中的:

這是更新後的響應 players,使用 PATCH
HTTP方法:

這是第一個響應中數據的格式更好的視圖:
{
"id": "1OHQdsTAr",
"preview_url": "http://preview-players.brightcove.net/v2/accounts/.../master/index.html",
"preview_embed_in_page": "http://preview-players.brightcove.net/v2/accounts/.../master/in_page.embed",
"preview_embed_code": "<iframe src='//preview-players.brightcove.net/v2/accounts/.../master/index.html' ...></iframe>"
}
最後,這是發生錯誤時非常有價值的響應。 在這種情況下,使用的帳戶沒有適當的憑據:

其他疑難解答提示
如果您遇到問題,這裡還有其他一些要尋找的東西。
- 沒有反應
- 有幾件事要檢查您是否收到空響應:
- 檢查API參考,以確保請求返迴響應。 一些僅返回不包含任何內容的201或204響應(尤其但不僅限於DELETE請求)。 您將需要調整代碼以處理這種情況。
- 在瀏覽器中檢查“開發人員工具”的“網絡”部分,以確保您成功調用了代理(該服務器可能暫時不可用):
開發人員工具網絡部分
- 我看到了回應,但是當我嘗試
JSON.parse()
它,我得到一個例外。 - 這裡有一些可能性:
- 參見上一項-嘗試解析空字符串會拋出JSON異常
-
查看響應,並確保它是JSON字符串(以
{
或[
)。 在某些情況下,請求可能不會返回JSON- Analytics API 例如,如果您設置了format
參數csv
orxlxs
。 同樣,如果要發出這類請求,則需要調整代碼以處理非JSON響應。 - 在大多數情況下,API返回的錯誤也都是JSON格式,但是有一些例外,這些錯誤以純文本或HTML格式返回。
代理代碼
如前所述,可以使用您選擇的語言編寫代理。 Brightcove API文檔示例使用以PHP編寫的代理。 由於代理的實現與語言有關,因此下面的PHP代碼不會在本文檔中進行詳細分析。
代理提供的基本功能必須包括:
- 接受客戶要求。
- 申請 身份驗證令牌 來自 OAuth API.
- 將身份驗證令牌和數據請求(端點)發送到預期的API。
- 從API接收回數據。
- 將數據發送回客戶端。
<?php
/**
* proxy for Brightcove RESTful APIs
* gets an access token, makes the request, and returns the response
* Accessing:
* (note you should **always** access the proxy via HTTPS)
* Method: POST
* request body (accessed via php://input) is a JSON object with the following properties
*
* {string} url - the URL for the API request
* {string} [requestType=GET] - HTTP method for the request
* {string} [requestBody] - JSON data to be sent with write requests
* {string} [client_id] - OAuth2 client id with sufficient permissions for the request
* {string} [client_secret] - OAuth2 client secret with sufficient permissions for the request
*
* Example:
* {
* "url": "https://cms.api.brightcove.com/v1/accounts/57838016001/video",
* "requestType": "PATCH",
* "client_id": "0072bebf-0616-442c-84de-7215bb176061",
* "client_secret": "7M0vMete8vP_Dmb9oIRdUN1S5lrqTvgtVvdfsasd",
* "requestBody": "{\"description\":\"Updated video description\"}"
* }
*
* if client_id and client_secret are not included in the request, default values will be used
*
* @returns {string} $response - JSON response received from the API
*/
// security checks
// if you want to do some basic security checks, such as checking the origin of the
// the request against some white list, this would be a good place to do it
// CORS enablement and other headers
header("Access-Control-Allow-Origin: *");
header("Content-type: application/json");
header("X-Content-Type-Options: nosniff");
header("X-XSS-Protection");
// default account values
// if you work on one Brightcove account, put in the values below
// if you do not provide defaults, the client id, and client secret must
// be sent in the request body for each request
$default_client_id = 'YOUR_CLIENT_ID';
$default_client_secret = 'YOUR_CLIENT_SECRET';
// get request body
$requestData = json_decode(file_get_contents('php://input'));
// set up access token request
// check to see if client id and secret were passed with the request
// and if so, use them instead of defaults
if (isset($requestData->client_id)) {
$client_id = $requestData->client_id;
}
if (isset($requestData->client_secret)) {
$client_secret = $requestData->client_secret;
}
$auth_string = "{$client_id}:{$client_secret}";
// make the request to get an access token
$request = "https://oauth.brightcove.com/v4/access_token?grant_type=client_credentials";
$curl = curl_init($request);
curl_setopt($curl, CURLOPT_USERPWD, $auth_string);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-type: application/x-www-form-urlencoded',
));
$response = curl_exec($curl);
$curl_info = curl_getinfo($curl);
$php_log = array(
"php_error_info" => $curl_info
);
$curl_error = curl_error($curl);
curl_close($curl);
// Check for errors
// it's useful to log as much info as possible for debugging
if ($response === FALSE) {
log_error($php_log, $curl_error);
}
// Decode the response and get access token
$responseData = json_decode($response, TRUE);
$access_token = $responseData["access_token"];
// get request type or default to GET
$method = "GET";
if ($requestData->requestType) {
$method = $requestData->requestType;
}
// get the URL and authorization info from the form data
$request = $requestData->url;
// check for a request body sent with the request
if (isset($requestData->requestBody)) {
$data = $requestData->requestBody;
}
$curl = curl_init($request);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-type: application/json',
"Authorization: Bearer {$access_token}"
));
switch ($method)
{
case "POST":
curl_setopt($curl, CURLOPT_POST, TRUE);
if ($requestData->requestBody) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
break;
case "PUT":
// don't use CURLOPT_PUT; it is not reliable
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
if ($requestData->requestBody) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
break;
case "PATCH":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
if ($requestData->requestBody) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
break;
case "DELETE":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
if ($requestData->requestBody) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
break;
default:
// GET request, nothing to do;
}
$response = curl_exec($curl);
$curl_info = curl_getinfo($curl);
$php_log = array(
"php_error_info" => $curl_info
);
$curl_error = curl_error($curl);
curl_close($curl);
// Check for errors and log them if any
// note that logging will fail unless
// the file log.txt exists in the same
// directory as the proxy and is writable
if ($response === FALSE) {
log_error($php_log, $curl_error);
}
function log_error($php_log, $curl_error) {
$logEntry = "\nError:\n". "\n".date("Y-m-d H:i:s"). " UTC \n" .$curl_error. "\n".json_encode($php_log, JSON_PRETTY_PRINT);
$logFileLocation = "log.txt";
$fileHandle = fopen($logFileLocation, 'a') or die("-1");
fwrite($fileHandle, $logEntry);
fclose($fileHandle);
echo "Error: there was a problem with your API call"+
die(json_encode($php_log, JSON_PRETTY_PRINT));
}
// return the response to the AJAX caller
echo $response;
?>
儘管上面顯示了代理服務器的完整代碼,但它也位於GitHub存儲庫中: 樣本代理應用 在 PHP 文件夾中。
例如2
第二個示例比前面詳述的示例更為複雜。 此示例顯示播放列表中某個帳戶的10個最受歡迎的視頻。 該代碼的主要步驟是:
- 來自的請求 Analytics API 帳戶中觀看次數最多的10個視頻。 此步驟涉及使用回調函數的異步調用。
- 從返回 Analytics API 數據,僅提取視頻ID並將其放置在數組中。 編寫了一個輔助函數來從返回的數據中提取ID。
- 請求陣列ID列表中每個視頻的完整視頻對象。 此步驟涉及遍歷數組並使用以下命令請求視頻對象
player.catalog.getVideo()
。 當然,這涉及使用catalog
。 編寫了一個輔助函數,用於根據ID檢索視頻對象並將這些對象放入數組中。 - 將視頻對像數組放入播放列表以啟用播放列表 player.
由於您現在已經熟悉了許多有關如何調用API的概念和特定代碼,因此只有調用 makeRequest()
功能詳細。
- 第2行:致電
makeRequest()
函數傳遞成功REST API調用所需的選項作為參數,以及匿名定義的回調函數(以黃色突出顯示)。 從上面聽起來應該很熟悉。 非常重要的是makeRequest()
被稱為“函數”的函數是先前示例中使用的“完全相同”功能。 您可以在代碼中執行相同的操作。 的makeRequest()
該函數被編寫為可以與對Brightcove REST API的任何調用一起重用。 - 第3行:創建變量以保存JSON解析的返回數據。
- 第5行:解析返回的數據,以將其從字符串轉換為對象。
- 第7行:使用幫助程序功能從返回的數據中提取視頻ID。 不幸的是, Analytics API 不會返回完整的視頻對象,因此需要ID才能訪問完整的對象。
- 9-12行:致電
getVideoData
使用回調函數填充的輔助函數videoObjects
基於傳遞的ID的數組。 - 第11行:使用視頻對像數組填充播放列表。
// +++ Make the CMS API request to get matching video IDs +++
makeRequest(options, function(mostWatchedVideos) {
var JSONmostWatchedVideos;
// Convert response string into JSON
JSONmostWatchedVideos = JSON.parse(mostWatchedVideos);
// Extract the needed video IDs into an array
videoData = extractVideoData(JSONmostWatchedVideos);
// Get video objects based on array of video IDs
getVideoData(videoData, function(videoObjects) {
// Add the most watched videos list to the player as a playlist
myPlayer.playlist(videoObjects);
});
});
完整的代碼清單
完整的可運行示例位於此CodePen中: 播放列表中觀看次數最多的視頻.