Live API Sample: Create a Live Job

Product(s)
Live
Role(s)
API Developer
Topic(s)
Live Streaming
API(s)
Live API

In this sample, you will learn how to create a simple Live job.

Introduction

This sample creates a simple Live job with three output renditions: 1080p, 720p, and 480p.

Because the Live API is not CORS-enabled and must be accessed from a server-side app, the API request is sent through a simple proxy written in PHP. You can reproduce this in any server-side language - all it does is collect the request parameters sent by the JavaScript, sends the request to the API, and returns the response to the JavaScript. All the code can be found in the code section below.

App inputs

Live API Key:

Select region:

App outputs

Log

Request body

Playback URLs

stream_url

playback_url

playback_url_dvr

Full response

Code for this sample

HTML

<section class="bcls-section">
  <h2 id="inputs">App inputs</h2>
  <p>Live API Key: <input id="live_key" type="text"></p>
  <p>Select region: <select name="regionSelect" id="regionSelect"></select></p>
  <p><button id="sendButton" class="bcls-button">Create the Job</button></p>
</section>
<section class="bcls-section">
  <h2 id="outputs">App outputs</h2>
  <h3>Log</h3>
  <p>Request body</p>
  <textarea name="reqBody" id="reqBody" class="bcls-code" rows="8" cols="80"></textarea>
  <h3>Playback URLs</h3>
  <p><code>stream_url</code></p>
  <textarea name="stream_url" id="stream_url" cols="100" rows="2" class="bcls-code"></textarea>
  <p><code>playback_url</code></p>
  <textarea name="playback_url" id="playback_url" cols="100" rows="2" class="bcls-code"></textarea>
  <p><code>playback_url_dvr</code></p>
  <textarea name="playback_url_dvr" id="playback_url_dvr" cols="100" rows="2" class="bcls-code"></textarea>

  <h3>Full response</h3>
<pre class="line-numbers"><code id="apiResponse" class="language-json"></code></pre>
</section>

JavaScript

var BCLS = ( function (window, document) {
  var live_key       = document.getElementById('live_key'),
    regionSelect     = document.getElementById('regionSelect'),
    stream_url       = document.getElementById('stream_url'),
    playback_url     = document.getElementById('playback_url'),
    playback_url_dvr = document.getElementById('playback_url_dvr'),
    apiResponse      = document.getElementById('apiResponse'),
    sendButton       = document.getElementById('sendButton'),
    reqBody          = document.getElementById('reqBody'),
    proxyURL         = 'https://solutions.brightcove.com/bcls/bcls-proxy/live-proxy.php',
    regions          = ['us-west-1', 'us-west-2', 'us-east-1', 'us-east-2', 'eu-west-1', 'eu-west-2', 'ap-southeast-2', 'ap-northeast-1', 'ap-southeast-1', 'eu-central-1', 'sa-east-1', 'ap-south-1'],
    apiKey           = '6aaXAZSSzRatgbVo7P12v7g13ovsuemr3y0CLGkR',
    body             = JSON.parse('{"live_stream":true,"region":"us-west-2","reconnect_time":20,"live_sliding_window_duration":30,"outputs":[{"label":"hls1080p","live_stream":true,"width":1920,"height":1080,"video_codec":"h264","h264_profile":"main","video_bitrate":2400,"segment_seconds":6,"keyframe_interval":60},{"label":"hls720p","live_stream":true,"width":1280,"height":720,"video_codec":"h264","h264_profile":"main","video_bitrate":1843,"segment_seconds":6,"keyframe_interval":60},{"label":"hls480p","live_stream":true,"width":640,"height":360,"video_codec":"h264","h264_profile":"main","video_bitrate":819,"segment_seconds":6,"keyframe_interval":60}]}'),
    requestURL       = 'https://api.bcovlive.io/v1/jobs',
    fragment         = document.createDocumentFragment(),
    option,
    i,
    iMax;

  // build select options
  iMax = regions.length;
  for (i = 0; i < iMax; i++) {
    option = document.createElement('option');
    option.setAttribute('value', regions[i]);
    option.textContent = regions[i];
    if (regions[i] === 'us-west-2') {
      option.setAttribute('selected', 'selected');
    }
    fragment.appendChild(option);
  }
  regionSelect.appendChild(fragment);

  // event handlers

  sendButton.addEventListener('click', function() {
    if (isDefined(live_key.value)) {
      createRequest();
    } else {
      alert('You must provide a Live API Key');
    }
  });

  /**
   * get selected value for single select element
   * @param {htmlElement} e the select element
   * @return {Object} object containing the `value`, text, and selected `index`
   */
  function getSelectedValue(e) {
      var selected = e.options[e.selectedIndex],
          val = selected.value,
          txt = selected.textContent,
          idx = e.selectedIndex;
      return {
          value: val,
          text: txt,
          index: idx
      };
  }

  /**
   * 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) {
          return false;
      }
      return true;
  }

  /*
   * tests to see if a string is json
   * @param {String} str string to test
   * @return {Boolean}
   */
  function isJson(str) {
      try {
          JSON.parse(str);
      } catch (e) {
          return false;
      }
      return true;
  }

  /**
   * prepares the api request and handles the response
   */
    function createRequest() {
      var options = {},
        responseDecoded,
        playlist;
      body.region = getSelectedValue(regionSelect).value;
      options.url = requestURL;
      reqBody.textContent = JSON.stringify(body);
      options.requestBody = JSON.stringify(body);
      options.requestType = 'POST';
      options.apiKey = live_key.value;
      makeRequest(options, function(response) {
        if (isJson(response)) {
          responseDecoded = JSON.parse(response);
          apiResponse.textContent = JSON.stringify(responseDecoded, null, '  ');
          stream_url.textContent = responseDecoded.stream_url;
          playback_url.textContent = responseDecoded.playback_url;
          playback_url_dvr.textContent = responseDecoded.playback_url_dvr;
        } else {
          apiResponse.textContent = response;
        }
      });
    }

  /**
   * send API request to the proxy
   * @param  {Object} options options for the request
   * @param  {String} requestID the type of request = id of the button
   * @param  {Function} [callback] callback function
   */
  function makeRequest(options, callback) {
    var httpRequest = new XMLHttpRequest(),
      responseRaw,
      parsedData,
      requestParams,
      dataString,
      renditions,
      field,
      i = 0,
      iMax,
      // response handler
      getResponse = function() {
        try {
          if (httpRequest.readyState === 4) {
            if (httpRequest.status >= 200 && httpRequest.status < 300) {
              // check for completion
              responseRaw = httpRequest.responseText;
              callback(responseRaw);
            }
          }
        } catch (e) {
          alert('Caught Exception: ' + e);
        }
      };
    // set up request data
    requestParams = 'url=' + encodeURIComponent(options.url) + '&requestType=' + options.requestType + '&apiKey=' + options.apiKey + '&requestBody=' + options.requestBody;

    // set response handler
    httpRequest.onreadystatechange = getResponse;
    // open the request
    httpRequest.open('POST', proxyURL);
    // set headers
    httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    // open and send request
    httpRequest.send(requestParams);
  }

})(window, document);

Proxy (PHP)

<?php
/**
 * bcls-proxy.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
 *
 * @post {string} url - the URL for the API request
 * @post {string} [requestType=GET] - HTTP method for the request
 * @post {string} [requestBody] - JSON data to be sent with write requests
 * @post {string} apiKey - Live API key
 *
 * @returns {string} $response - JSON response received from the API
 */


// 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");


// set up the API call
// get data
if ($_POST["requestBody"]) {
    $data = json_decode($_POST["requestBody"]);
}
// get api key
$apikey = $_POST["apiKey"];
// get request type or default to GET
if ($_POST["requestType"]) {
    $method = $_POST["requestType"];
} else {
    $method = "GET";
}
// security checks
$needle = '.io';
$endapi = strpos($_POST["url"], $needle) + 3;

$nextChar = substr($_POST['url'], $endapi, 1);

if (strpos($_POST["url"], 'api.bcovlive.io') == false) {
    exit('{"ERROR":"Only requests to Brightcove Live APIs are accepted by this proxy"}');
} else if ($nextChar !== '/' && $nextChar !== '?') {
    exit('{"ERROR": "There was a problem with your API request - please check the URL"}');
}
// get the URL and authorization info from the form data
$request = $_POST["url"];
//send the http request
if ($_POST["requestBody"]) {
  $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',
      "X-API-KEY: {$apikey}",
    ),
    CURLOPT_POSTFIELDS => json_encode($data)
  ));
  $response = curl_exec($ch);
  curl_close($ch);
} else {
  $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',
      "X-API-KEY: {$apikey}",
    )
  ));
  $response = curl_exec($ch);
  curl_close($ch);
}

// Check for errors
if ($response === FALSE) {
    $logEntry = "\nError:\n".
    "\n".date("Y-m-d H:i:s")." UTC \n"
    .$response;
    $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(curl_error($ch));
}

// Decode the response
// $responseData = json_decode($response, TRUE);
// return the response to the AJAX caller
$responseDecoded = json_decode($response);
// if (!isset($responseDecoded)) {
// 	$response = '{null}';
// }
echo $response;
?>