지원 고객 지원 문의 | 시스템 상태 시스템 상태
페이지 내용

    동적 인제스트 요청의 상태 가져오기

    당신이 사용할 때Dynamic Ingest API Video Cloud 계정에 비디오를 추가하기 위해 가장 알고 싶은 것은 비디오가 처리 된시기와 렌 디션이 성공적으로 생성되었는지 여부입니다.

    서문

    이 문서는 상태 요청을 통해 작업 상태를 추적하는 방법을 설명합니다. CMS API또는 사용하여Dynamic Ingest API알림 . 프로세스를 자동화하는 샘플 대시 보드 앱도 제공합니다.

    수집 작업의 상태는 지난 7 일 동안 제출 된 작업에만 사용할 수 있습니다.

    상태 요청

    다음을 사용하여 동적 수집 작업 (수집, 교체 또는 재 트랜스 코딩)의 상태를 가져옵니다. 이들CMS API끝점 -이러한 엔드 포인트는 Dynamic Delivery 작업 만 :

    모든 작업에 대한 상태 가져 오기

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

    응답은 다음과 같습니다.

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

    특정 작업에 대한 상태 가져 오기

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

    응답은 다음과 같습니다.

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

    가능한 값state아르:

    • processing : 처리 중, 동영상은 아직 재생할 수 없습니다.
    • publishing : 재생 가능한 변환이 하나 이상 생성되었으며 비디오를 재생할 준비 중입니다.
    • published : 재생에 사용할 수있는 변환이 하나 이상 있습니다.
    • finished : 하나 이상의 오디오 / 비디오 변환이 처리되었습니다.
    • failed : 처리에 실패했습니다. 무엇이 잘못되었는지 파악할 수없는 경우 지원팀에 문의하십시오.

    알림 받기

    위에서 설명한 요청 상태 방법이 작동하는 동안 특정 상태 ( published또는finished ) 원하는 답변을 얻을 때까지 상태를 계속 묻는 것보다 이러한 이벤트가 발생할 때 Brightcove가 사용자에게 알리도록하는 것이 좋습니다. 이제 알림 처리를 중심으로 앱을 빌드하는 방법을 살펴 보겠습니다.

    Dynamic Ingest 알림은 비디오가 준비되었을 때 알아야하는 모든 정보를 제공합니다. 무엇을 찾아야하는지 알고 시스템에 "준비"가 무엇을 의미하는지 정의하기 만하면됩니다. 이 다이어그램은 워크 플로우를 요약합니다.

    수집 상태 워크 플로
    수집 상태 워크 플로

    동적 인제스트 알림

    Dynamic Ingest 알림 서비스는 여러 종류의 이벤트에 대한 알림을 보냅니다. 비디오가 "준비된"시기를 파악하는 데 가장 유용한 두 가지는 특정 변환이 생성되었음을 나타내는 것과 모든 처리가 완료되었음을 나타내는 것입니다. 다음은 각각의 예입니다.

    동적 변환 생성 알림

        {
          "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"
        }
        
        
    변환에 대한 알림 생성

    이 예에서 참고 :

    • 그만큼videoId 값을 사용하면 변환이 어떤 비디오인지 알 수 있습니다 (여러 수집 작업이 실행중인 경우).
    • 그만큼entity value는 생성 된 동적 변환 유형입니다.
    • 만약status 값이 "SUCCESS"이면 변환이 성공적으로 생성되었습니다.

    처리 완료 알림

        {
          "entity": "5660367449001",
          "entityType": "TITLE",
          "version": "1",
          "action": "CREATE",
          "jobId": "d3ef8751-2b88-4141-95d5-83f0393aca07",
          "videoId": "5660367449001",
          "accountId": "57838016001",
          "status": "SUCCESS"
        }
        
        
    처리 완료 알림

    이 예에서 참고 :

    • 그만큼videoId jobId 값을 통해 어떤 비디오에 해당하는지 알 수 있습니다 (여러 수집 작업이 실행중인 경우).
    • 만약status 값이 "SUCCESS"이면 동영상이 성공적으로 처리되었습니다.

    알림을 받으려면 "콜백"필드를 포함해야합니다. Dynamic Ingest API하나 이상의 콜백 주소를 가리키는 요청 :

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

    샘플 대시 보드

    이 섹션에서는 Dynamic Ingest API에 대한 간단한 대시 보드를 구축하기 위해 알림을 조합하는 방법을 설명합니다. 알림 처리기는Dynamic Ingest API처리 완료 알림을 식별합니다. 그런 다음 JSON 파일의 각 비디오에 대한 개체 배열에 비디오 알림을 추가합니다. 대시 보드 자체는 알림 데이터를 가져 오기 위해 JSON 파일을 가져 오는 HTML 페이지입니다. ID를 사용하여 CMS API비디오 메타 데이터를 가져옵니다.

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

    수집 대시 보드 아키텍처
    수집 대시 보드 아키텍처

    앱 부분

    알림 핸들러는 PHP로 빌드됩니다. 완전한 알림 처리를 찾고 별도의 자바 스크립트 파일의 배열에 동영상 ID를 추가합니다.

        <?php
          //JSON 데이터에 대해 POST가 작동하지 않음
          $ 문제 = “오류 없음”;
          {
            $ JSON = 파일 _get_내용 ('PHP://입력');
            $ 디코딩 = json_decode ($ JSON, 사실);
          } catch (Exception $e) {
            $ 문제 = $ - > getMessage ();
            echo $ problem;
          }
    
          // 전체 알림
          $ 알림 = json_인코딩 ($ 디코딩, JSON_PRETTY_인쇄);
    
          // 알림의 유용한 부분을 추출하여 시작합니다.
          // Dynamic Delivery의 경우 'videoId'를 찾습니다.
          // 레거시 수집 시스템의 경우 동영상 ID는 '엔티티'입니다.
    
          if (isset ($ decoded [ "videoId"])) {
            $ videoId = $ decoded [ "videoId"];
          } elseif (isset ($ decoded [ "entity"])) {
            $ videoId = $ decoded [ "entity"];
          } else {
            $ videoId = null;
          }
    
          if (isset ($ 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 (($ entityType == 'TITLE') && ($ action == 'CREATE')) {
            if (($ status == 'SUCCESS') || ($ status == 'FAILED')) {
              $ newLine = "\\ nvideoIdArray.unshift (". $ videoId. ");";
              //PHP가 로그 파일을 찾을 수 있는 위치를 알려주고 PHP에 열도록 지시합니다.
              //이전에 만든 문자열을 추가합니다.
              $ logFileLocation = "video-ids.js";
              $ 파일 핸들 = fopen ($ 로그 파일 위치, 'a') 또는 다이 (“-1");
              chmod ($로그 파일위치, 0777);
              fwrite ($ fileHandle, $ newLine);
              fclose ($ fileHandle);
            }
          }
    
          // 감사 추적에 대한 전체 알림 저장
          $ logEntry = $ notification. ", \\ n";
    
          $ logFileLocation = "full-log.txt";
          $ 파일 핸들 = fopen ($ 로그 파일 위치, 'a') 또는 다이 (“-1");
          chmod ($로그 파일위치, 0777);
          fwrite ($ fileHandle, $ logEntry);
          fclose ($ fileHandle);
    
    
          echo "Dynamic Ingest 콜백 앱이 실행 중입니다.";
          ?>
          
          

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

    프록시

        <?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 강화
        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);
        에코 '로그 파일이 지워졌습니다 - < href="di-log.html"대시 < > 보드/a'로 > 돌아갑니다.
        ?>