Accessing the Brightcove 3 Media API in .NET

Written by Bob de Wit. Posted in .NET, Brightcove, Developer Blog

This article describes how to access the Brightcove 3 Media API using C# .NET 3.5. Usage of another .NET programming language can be extrapolated by principle. I will update this article when I have transcoded the entire Media API. About the Media API The Brightcove Media Library API, or Media API for short, is a REST-based API for accessing the content and metadata in your Brightcove account. Because it is a REST-based API, it can be accessed from a wider variety of places in your web applications, not just on the client, but in your dynamically generated web pages or server-side synchronization processes, for example. REST is a standard way of accessing data stored in a remote system over HTTP. It is a cousin of SOAP and is one of the technologies that power “web services.” Its primary ability is to abstract the workings of the remote system in the transfer of its state (or information). All your code needs to understand is the format of the data that is sent back. About the Brightcove Media API The Media API includes read methods and write methods.
  • The Read API consists of a set of methods which perform a variety of queries on our servers (which are cached for performance), and return sets of data in DTOs or Data Transfer Objects. For example, one API method is find_all_videos, which returns a list of VideoDTOs, where each VideoDTO contains the metadata for a specific video. Return data is formatted as JSON strings (JavaScript Object Notation). JSON is a lightweight way of transferring complex objects as strings, and nearly every language today can claim a large number of publicly available libraries to parse JSON strings into native objects.
  • The Write API consists of a set of methods that create, update, or delete videos and playlists. For example, one Write API method is create_video, which you can use to pass in a video file, together with its associated metadata, and create a video in your Brightcove account.
Note: To prevent unauthorized access to the metadata in your account, access to the API is protected with tokens that you pass as a parameter when making API calls. Like other web-based APIs, tokens are generated for you by Brightcove and protected by you. The first thing you need to do to get started is to request a token to begin development. Use this feedback form to request one from Brightcove Customer Support: https://help.brightcove.com/request-support.cfm

Creating and sending a REST Query

About the REST format Method calls using REST are basically HTTP GET requests(for read methods) or POST requests (for write methods) to a particular URL on Brightcove’s servers. The request includes the name of the method you’re calling, together with its input arguments, which are passed as parameters in the URL. The body of the HTTP response contains the results of the HTTP call as a JSON string. Method calls also require a token. Tokens are issued to accounts by Brightcove and give you access to your account using the API. There are separate tokens for read methods and write methods in the API. You append your token to the call as a URL parameter, token=<tokenString>, where tokenString is your URL-encoded token. Note: Media API tokens generally end with one or more dots (.). Be sure to include the dots when you use the API tokens – it’s easy to lose them when you cut and paste. For example, to retrieve all videos in your account, make an HTTP request that looks like: http://api.brightcove.com/services/library?command=find_all_videos&token=0123456789ABCDEF This is a raw method call. What comes back is unprocessed and unformatted. In the examples, you’ll see ways to take the returned data and shape it in ways that are useful for an application. (Note: This call uses a demo account. To use your own account, substitute your own token.) JSON in .NET? There is no standard .NET library for parsing JSON, so we’ll be using an open source library from NewtonSoft. You can find the Library and source here: http://www.codeplex.com/Json Start a new .NET project called BrightcoveAPI and make sure you include a reference to the Newtonsoft.JSON library. The first thing we’re going to do is create a static class that will contain the configuration items for the Media API. We’ll call this class BCAPIConfig:
using System;
using System.Collections.Generic;
using System.Text;

namespace BrightcoveAPI
{
    public static class BCAPIConfig
    {
        public static String ReadToken = "0123456789ABCDEF";
        public static String WriteToken = "your-write-token-here";
        public static String ServiceURL = "http://api.brightcove.com/services/library";
    }
}
Now we’ll create a base class to handle the generic REST API requests, so add a class to the project we’ll call BCAPIRequest.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using Newtonsoft.Json;

namespace BrightcoveAPI
{
    public class BCAPIRequest
    {
        private HttpWebRequest webRequest;

        public JsonReader Execute(Dictionary reqParams )
        {
            String reqUrl = BCAPIConfig.ServiceURL + "?";
            int i = 0;
            foreach (String key in reqParams.Keys)
            {
                if (i > 0) reqUrl += "&";
                reqUrl += String.Format("{0}={1}", key, HttpUtility.UrlEncode(reqParams[key]));
                i++;
            }
            webRequest = WebRequest.Create(reqUrl) as HttpWebRequest;
            HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse;
            TextReader textreader = new StreamReader(response.GetResponseStream());
            JsonReader reader = new JsonTextReader(textreader);
            return reader;
        }

    }
}
Nothing extraordinary here: we just create a generic class that creates the webRequest and joins all the parameters passed in a standard .NET Dictionary into a URLEncoded string to be added to the API URL defined in the BCAPIConfig static class. The result is then passed as a JSON Reader class (not unlike a .NET Stream) to the caller.

Parsing the returned JSON Data

There are many ways to parse the returned JSON data, but to make the code as reusable as possible, let’s create a Brightcove Object base class that contains all necessary conversion functions from and to JSON data formats, in particular for converting DateTime values:
using System;
using System.Collections.Generic;
using System.Text;

namespace BrightcoveAPI
{
    public class BCObject
    {

        protected DateTime DateFromUnix(object value)
        {
            long millisecs = long.Parse(value.ToString());
            double secs = millisecs / 1000;
            return new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(secs);
        }
    }
}
Then we can derive classes for each Brightcove Media API Data type. For example, the Video class can look something like this:
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Newtonsoft.Json;

namespace BrightcoveAPI
{
    public enum BCVideoEconomics { FREE, AD_SUPPORTED };

    //
    // The Video object is an aggregation of metadata and
    // asset information associated with a video
    //
    public class BCVideo : BCObject
    {
        private long _id;
        private DateTime _creationDate;
        private DateTime _publishedDate;
        private DateTime _lastModifiedDate;
        private long _length;
        private int _playsTotal;
        private int _playsTrailingWeek;

        //
        // A number that uniquely identifies this Video, assigned by
        // Brightcove when the Video is created.
        //
        public long id { get { return _id; } }

        //
        // The title of this Video.
        //
        public String name { get; set; }

        //
        // A short description describing this Video,
        // limited to 256 characters.
        //
        public String shortDescription { get; set; }

        //
        // A longer description of this Video, bounded by a
  // 1024 character limit.
        //
        public String longDescription { get; set; }

        //
        // The date this Video was created, represented as the number
	  // of milliseconds since the Unix epoch.
        //
        public DateTime creationDate { get { return _creationDate; } }

        //
        // The date this Video was last made active, represented as the
 	  // number of milliseconds since the Unix epoch.
        //
        public DateTime publishedDate { get { return _publishedDate; }}

        //
        // The date this Video was last modified, represented as the
	  // number of milliseconds since the Unix epoch.
        //
        public DateTime lastModifiedDate
  {
            get { return_lastModifiedDate; }
    	  }

        //
        // An optional URL to a related item.
        //
        public String linkURL { get; set; }

        //
        // The text displayed for the linkURL.
        //
        public String linkText { get; set; }

        //
        // A list of Strings representing the tags assigned
  // to this Video.
        //
        public List tags = new List();

        //
        // The URL to the video still image associated with this Video.
        // Video stills are 480x360 pixels.
        //
        public String videoStillURL { get; set; }

        //
        // The URL to the thumbnail image associated with this Video.
	  // Thumbnails are 120x90 pixels.
        //
        public String thumbnailURL { get; set; }

        //
        // A user-specified id that uniquely identifies this Video.
	  // ReferenceID can be used as a foreign-key to identify this
	  // video in another system.
        //
        public String referenceId { get; set; }

        //
        // The length of this video in milliseconds.
        //
        public long length { get { return _length; } }

        //
        // Either FREE or AD_SUPPORTED. AD_SUPPORTED means that ad
  // requests are enabled for this Video.
        //
        public BCVideoEconomics economics { get; set; }

        //
        // How many times this Video has been played since
  // its creation.
        //
        public int playsTotal { get { return _playsTotal; } }

        //
        // How many times this Video has been played within the past
	  // seven days, exclusive of today.
        //
        public int playsTrailingWeek { get
             { return _playsTrailingWeek; } }

        //
        // Constructor, getting a JSON Reader passed for initialization
        //
        public BCVideo(JsonReader reader)
        {
            reader.Read();
            while (reader.TokenType != JsonToken.EndObject)
            {
                if (reader.TokenType == JsonToken.PropertyName)
                {

                    switch (reader.Value.ToString())
                    {
                        case "error":
                            reader.Read();
                            Console.WriteLine(String.Format("Error: {0}", reader.Value));
                            break;

                        case "id":
                            reader.Read();
                            _id = (long)reader.Value;
                            break;

                        case "name":
                            reader.Read();
                            name = (string)reader.Value;
                            break;

                        case "shortDescription":
                            reader.Read();
                            shortDescription = (string)reader.Value;
                            break;

                        case "longDescription":
                            reader.Read();
                            longDescription = (string)reader.Value;
                            break;

                        case "creationDate":
                            reader.Read();
                            _creationDate = DateFromUnix(reader.Value);
                            break;

                        case "publishedDate":
                            reader.Read();
                            _publishedDate = DateFromUnix(reader.Value);
                            break;

                        case "lastModifiedDate":
                            reader.Read();
                            _lastModifiedDate = DateFromUnix(reader.Value);
                            break;

                        case "linkURL":
                            reader.Read();
                            linkURL = (string)reader.Value;
                            break;

                        case "linkText":
                            reader.Read();
                            linkText = (string)reader.Value;
                            break;

                        case "tags":
                            reader.Read();
                            tags.Clear();
                            if (reader.Value != null)
                            {
                                String[] ltags = reader.Value.ToString().Split(',');
                                foreach (String stag in ltags) tags.Add(stag);
                            }
                            break;

                        case "videoStillURL":
                            reader.Read();
                            videoStillURL = (string)reader.Value;
                            break;

                        case "thumbnailURL":
                            reader.Read();
                            thumbnailURL = (string)reader.Value;
                            break;

                        case "referenceId":
                            reader.Read();
                            referenceId = (string)reader.Value;
                            break;

                        case "length":
                            reader.Read();
                            _length = (long)reader.Value;
                            break;

                        case "economics":
                            reader.Read();
                            economics = (BCVideoEconomics)Enum.Parse(typeof(BCVideoEconomics), reader.Value.ToString());
                            break;

                        case "playsTotal":
                            reader.Read();
                            _playsTotal = int.Parse(reader.Value.ToString());
                            break;

                        case "playsTrailingWeek":
                            reader.Read();
                            _playsTrailingWeek = int.Parse(reader.Value.ToString());
                            break;

                        default:
                            reader.Read();
                            break;
                    }
                }
                reader.Read();
            }
            reader.Read();
        }
    }
}
Basically, what this code does is read a property entry from the JSON stream and sets the value of the associated object property. It’s quite a bit of code for such a simple operation, but we only need to define this once.

Putting it all together

Great, now we have all the building blocks, let’s implement the API. As example, we’ll use the Video read API again. If you look at the available functions, you’ll see that the calls either return one video object, or an array of video objects. Let’s do an example of both:
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Newtonsoft.Json;

namespace BrightcoveAPI
{
    public static class BCAPI
    {
        public static List FindAllVideos(int pageSize, int pageNumber, BCSortByType sortBy, BCSortOrderType sortOrder, Listfields, Boolean getItemCount)
        {
            List videos = new List();
            BCAPIRequest req = new BCAPIRequest();
            Dictionary reqparams = new Dictionary();

            //Build the REST parameter list
            reqparams.Add("command", "find_all_videos");
            reqparams.Add("token", BCAPIConfig.ReadToken);
            reqparams.Add("get_item_count", getItemCount.ToString().ToLower());
            if (fields != null) reqparams.Add("fields", Implode(fields));
            reqparams.Add("sort_order", sortOrder.ToString());
            reqparams.Add("sort_by", sortBy.ToString());
            if (pageNumber >= 0) reqparams.Add("page_number", pageNumber.ToString());
            if (pageSize >= 0) reqparams.Add("page_size", pageSize.ToString());

            //Get the JSon reader returned from the APIRequest
            JsonReader reader = req.Execute(reqparams);

            //Return a list of videos
            return GetMultipleVideos(reader);
        }

        public static BCVideo FindVideoById(long videoId, List fields)
        {
            BCAPIRequest req = new BCAPIRequest();
            Dictionary reqparams = new Dictionary();

            //Build the REST parameter list
            reqparams.Add("command", "find_video_by_id");
            reqparams.Add("token", BCAPIConfig.ReadToken);
            reqparams.Add("video_id", videoId.ToString());
            if (fields != null) reqparams.Add("fields", Implode(fields));

            //Get the JSon reader returned from the APIRequest
            JsonReader reader = req.Execute(reqparams);

            //Return a single video
            return GetSingleVideo(reader);
        }

        private static List GetMultipleVideos(JsonReader reader)
        {
            List videos = new List();
            //Get the first start object
            reader.Read();
            if (reader.TokenType == JsonToken.StartObject)
            {
                //Check if this is an array of videos
                reader.Read();
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    if (reader.Value.ToString() == "items")
                    {
                        reader.Read();
                        if (reader.TokenType == JsonToken.StartArray)
                        {
                            //Parse all video objects within the array
                            reader.Read();
                            while (reader.TokenType == JsonToken.StartObject)
                            {
                                BCVideo video = new BCVideo(reader);
                                videos.Add(video);
                            }
                        }
                    }
                    else if (reader.Value.ToString() == "error")
                    {
                        reader.Read();
                        Console.WriteLine(String.Format("Error: {0}", reader.Value));
                    }
                }
                else
                {
                    //Unexpected JSON format within string
                }
            }
            else
            {
                //Unexpected JSON format at beginning of string
            }
            return videos;
        }

        private static BCVideo GetSingleVideo(JsonReader reader)
        {
            BCVideo video = null;
            reader.Read();
            if (reader.TokenType == JsonToken.StartObject)
            {
                video = new BCVideo(reader);
            }
            else
            {
                Console.WriteLine(String.Format("Error: {0}", reader.Value));
                //Error handling
            }
            return video;
        }

        private static String Implode(List values)
        {
            String result = "";
            foreach (String s in values)
            {
                result = result + s + ",";
            }
            return result;
        }

        private static String Implode(List values)
        {
            String result = "";
            foreach (long l in values)
            {
                result = result + l.ToString() + ",";
            }
            return result;
        }

    }

    public enum BCSortByType {PUBLISH_DATE, CREATION_DATE, MODIFIED_DATE, PLAYS_TOTAL, PLAYS_TRAILING_WEEK };

    public enum BCSortOrderType { ASC, DESC };

}

Testing the code

That’s it, we’ve created all the building blocks for a reusable Video read API library. Using the code is as simple as this console application:
using System;
using System.Collections.Generic;
using BrightcoveAPI;
using System.Text;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            BCAPI.FindVideoByReferenceId("test", null);
            Console.ReadLine();
        }
    }
}

Trackback from your site.

Leave a comment