지원 지원 문의 | 시스템 상태 시스템 상태

요청 상태 가져 오기

귀하가 Dynamic Ingest API 동영상을 내 동영상에 추가하려면 Video Cloud 계정에서 가장 많이 알고 싶은 것은 동영상이 처리 된 시점과 렌더링이 성공적으로 생성되었는지 여부입니다. 이 문서는 다음을 사용하여이를 수행하는 방법을 설명합니다. Dynamic Ingest API 알림. 또한 프로세스를 자동화하는 샘플 대시 보드 앱을 제공합니다. 이 문서는 레거시 수집 시스템에만 적용됩니다. 동적 전달의 경우 동적 인출 요청 상태 가져 오기

데이터 가져 오기

다이내믹 인게 스트 알림은 비디오 준비가 완료되었을 때 알아야 할 모든 정보를 제공합니다. 뭘 찾아야할지 알려주고 시스템에 어떤 의미가 있는지를 정의해야합니다. 이 다이어그램은 워크 플로를 요약합니다.

인게 스트 상태 워크 플로
인게 스트 상태 워크 플로

동적 인게이션 알림

Dynamic Ingest 알림 서비스는 몇 가지 종류의 이벤트에 대한 알림을 보냅니다. 비디오가 "준비 상태"일 때 가장 유용한 세 가지는 특정 표현이 만들어 졌음을 나타내는 것, 매니페스트가 만들어 졌음을 나타내는 것, 모든 처리가 완료되었음을 나타내는 것입니다. 다음은 각각의 예입니다.

렌 디션 생성 알림

    {
        "entity": "5002412132001",
        "profileRefId": "ts7",
        "accountId": "57838016001",
        "entityType": "ASSET",
        "videoId": "5002361893001",
        "status": "SUCCESS",
        "version": "1",
        "action": "CREATE",
        "jobId": "bb316631-c58b-4bd4-a686-13c5f7a3a779"
    }
생성 된 렌 디션에 대한 알림

이 예제의 참고 사항 :

  • 그리고, videoId 값을 사용하면 렌 디션이 어떤 비디오인지 알 수 있습니다 (여러 인제 스트 작업이 실행중인 경우)
  • 그리고, profileRefId 값은 인제 스트 프로필에 지정된 rendition에 대한 참조 ID입니다.
  • 경우 status 값이 "SUCCESS"이면 렌 디션이 성공적으로 작성되었습니다.
  • HLS 나 MPEG-DASH 같은 세분화 된 유형의 경우, 해당 렌디션의 존재로 인해 재생할 수 없습니다. 적절한 매니페스트가 필요합니다 (다음 예 참조). MP4 렌더는 생성되는 즉시 재생 가능합니다.

매니페스트 생성 알림

    {
        "jobId": "31f0b112-9890-4567-adb5-0f4ed1673701",
        "status": "SUCCESS",
        "version": "1",
        "action": "CREATE",
        "entityType": "ASSET",
        "entity": "5002412528001",
        "videoId": "5002361895001",
        "profileRefId": "HlsManifest",
        "accountId": "57838016001"
    }
생성 된 매니페스트에 대한 알림

이 예제의 참고 사항 :

  • 그리고, videoId 값을 사용하면 렌 디션이 어떤 비디오인지 알 수 있습니다 (여러 인제 스트 작업이 실행중인 경우)
  • 그리고, profileRefId 값은 생성 된 자산이 HLS 매니페스트임을 알려주는 특수한 코드입니다 (다른 가능한 값은 HdsManifest, DashManifestSmoothIsmManifest)
  • HLS 및 HDS의 경우 하나의 매니페스트가 만들어 지므로 하나의 알림이 표시됩니다. DASH 및 SmoothIsm의 경우 두 개의 매니페스트가 생성됩니다 (하나는 기존 Media API에 사용되고 다른 하나는 CMS API),이 유형의 두 가지 알림이 표시됩니다.
  • 경우 status 값이 "SUCCESS"이면 매니페스트가 성공적으로 만들어졌습니다.
  • HLS 나 MPEG-DASH 같은 세분화 된 유형의 경우, 렌 디션 및 매니페스트의 생성을위한 확실한 순서는 없습니다. 이러한 변환은 두 가지가 작성되거나 비디오가 완전히 처리 될 때까지 재생할 수 없습니다 (다음 예제 참조).

처리 완료 통지

    {
        "entityType": "TITLE",
        "status": "SUCCESS",
        "accountId": "57838016001",
        "entity": "5002412652001",
        "action": "CREATE",
        "jobId": "3e98b3a0-f624-4f2d-81c1-4e43e1d04a0f",
        "version": "1",
        "videoId": "5002412652001"
    }
처리 완료 알림

이 예제의 참고 사항 :

  • 그리고, videoId 값을 사용하면 렌 디션이 어떤 비디오인지 알 수 있습니다 (여러 인제 스트 작업이 실행중인 경우)
  • 그리고, profileRefId is 지원 이 통보에 포함 된
  • 경우 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 파일의 각 비디오에 대한 객체 배열에 추가합니다. 대시 보드 자체는 JSON 파일을 가져 와서 알림 데이터를 가져 오는 HTML 페이지입니다. ID를 사용하여 CMS API 동영상 메타 데이터를 가져옵니다. 대시 보드를 볼 수 있습니다. 여기를 클릭해 주세요.

이 앱의 모든 파일은 계정 설정 지침과 함께 다음 위치에 있습니다. 이 저장소.

다음은 앱의 고수준 아키텍처입니다.

Ingest Dashboad 아키텍처
Ingest Dashboad 아키텍처

앱 부품

알림 처리기는 PHP로 작성되었습니다. 완전한 알림 처리를 찾고 비디오 ID를 별도의 JavaScript 파일에 배열에 추가합니다.

    <?php
    // var to log errors, if any
    $problem = "No errors";
    // var to store current video index
    $videoIndex = -1;
    
    // get input data
    try {
        $json    = file_get_contents('php://input');
        $decoded = json_decode($json, true);
    } catch (Exception $e) {
        $problem = $e->getMessage();
        echo $problem;
    }
    
    // get the data file contents and parse them
    try {
        $notificationData = file_get_contents('di.json');
        $notificationDataDecoded = json_decode($notificationData, true);
    } catch (Exception $e) {
        $problem = $e->getMessage();
        echo $problem;
    }
    
    
        if (isset($decoded["entityType"])) {
            $entityType = $decoded["entityType"];
            // if the entity type is ASSET or TITLE, add it to notification data array
            if ($entityType == "ASSET" || $entityType == "TITLE") {
                array_push($notificationDataDecoded, $decoded);
            }
            // now we'll replace the contents of di.json with what we have
            file_put_contents('di.json', json_encode($notificationDataDecoded));
    
        }
    
    echo "Dynamic Ingest callback app is running";
    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 - 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 enablement
    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;
    ?>
    

로그 지우기

이 간단한 PHP 응용 프로그램은 JavaScript 파일을 원래 상태로 복원하여 이전 비디오 ID를 지 웁니다.

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

12 년 2020 월 XNUMX 일에 마지막으로 업데이트 된 페이지