Versioning the Player Management API

Highlights

Introduction

Brightcove’s Player Management API handles the creation, editing, and management of players as a resource to publishers. Its REST API provides endpoints to create, configure, preview, and publish player instances. In order to create innovative but backwards-incompatible changes to the public API, we created a new endpoint for the next major version.

The Problem

Many Brightcove Players use scripts and stylesheets to configure plugins available during playback. These can take on the form of either customer-created scripts for third party integrations, or Brightcove-created scripts for plugins available in the Brightcove Studio. Because the Studio creates the most requests to the Player Management API and provides easy access to many popular plugins (advertising, social media, playlists, etc.), the scripts and stylesheets associated with these plugins are extremely common in publishers’ configurations.

However, the scripts and stylesheets the Studio added to the players it managed through the API did not account for backwards-incompatible changes within the plugin code itself - it merely provided static URIs for the latest code of each plugin. Non-Studio users of the API also had to manage scripts and stylesheets themselves, their URIs scattered across plugin documentation.

Below is an example snippet of a player configuration created by the Studio after a publisher adds the social media plugin.

{
 "scripts": [ "//players.brightcove.net/videojs-social/3/videojs-social.min.js" ],
 "stylesheets": [ "//players.brightcove.net/videojs-social/3/videojs-social.css" ],
 "plugins": [ { "name": "social" } ]
}

These scripts and stylesheets added by the Studio are problematic for a few reasons:

  1. There is no consideration for compatibility between the player version and the plugin’s scripts and stylesheets

    As newer Brightcove player versions are released or publishers update their players in the studio, there is a greater chance the static URIs injected by the Studio are no longer compatible.

  2. The resource specified by the URI will change as new versions of Brightcove’s social media plugin are released

    Due to the way plugin scripts and stylesheets are stored within Brightcove’s domain, specifying  /3/ in the URI’s path refers to the latest code compatible with major version 3 of the social media plugin. As new versions are released, new player publish requests will pull in the updated code to automatically get the latest functionality. This affected publishers electing to use “Manual Update Mode” within the Studio to maintain a constant version of their player - republishing their player could end up including newer plugin code even with no related modifications to their configuration.

  3. There is no way to update existing script and stylesheet URIs across major versions

    In order to be semver-compliant, backwards incompatible changes to the plugin code require a new major version of the scripts and stylesheets and their corresponding URIs. However, there was no built-in way to change the static URIs in the Studio and there was no way to migrate players from publishers not using the Studio to the newest URIs in a maintainable fashion.

It’s a Bird -- It’s a Plane -- It’s … the Plugin Registry!

The newest major version of the Player Management API solves these problems through its newest component, the plugin registry. The plugin registry maintains a curated list of the versions of plugins currently utilized by the Studio.

By combining the registry_id of Brightcove’s social media plugin with an appropriate major version, we can modify the player configuration snippet above to be the following:

{
 "scripts": [],
 "stylesheets": [],
 "plugins": [ { "registry_id": "@brightcove/videojs-social", "version": "3.x" } ]
}

The combination of registry_id and version within the plugin array element indicates to the Player Management API to use the plugin registry to manage this plugin. When the player is published, the corresponding scripts and stylesheets are injected into the player configuration without having to be specified directly by the publisher.

If we wanted even finer control over the plugin's version, we can specify it directly:

{
 "scripts": [],
 "stylesheets": [],
 "plugins": [ { "registry_id": "@brightcove/videojs-social", "version": "3.6.0" } ]
}

Now the player will continue to get the scripts and stylesheets for version 3.6.0 of the social media plugin for all future publish requests.

Game Changer

Let's revisit the problems we identified with the existing system of managing plugin scripts and stylesheets within the Studio to highlight the importance of the plugin registry:

  1. There is no consideration for compatibility between the player version and the plugin’s scripts and stylesheets

    This is now automatically managed by the Player Management API during the creation, editing, and publishing of players. Attempting to specify a version property of a plugin that is incompatible with the player’s version is rejected by the API with an appropriate error message.

    Moreover, the Studio now uses the plugin registry to request plugin versions compatible with the player version. This guarantees compatibility between players and their plugins as new versions of each are released.

  2. The resource specified by the URI will change as new versions of Brightcove’s social media plugin are released

    Scripts and stylesheets for a plugin no longer need to reference these URIs, as they will be injected into the player at publish time based on the plugin’s version property.

    In addition, players locked to a specific version through the “Manual Update Mode” will now have their plugin versions locked as well. This means that if a player specifies a major version of a plugin, the corresponding version of the plugin at the exact time the player’s version was locked will remain constant throughout any future publish requests.

  3. There is no way to update existing script and stylesheet URIs across major versions

    The new version property of the plugins can specify any major version of the plugin - past, present, or future!

Separation of Player Management API Versions

While migration of existing player configurations into the new plugin registry compatible format solves the immediate problem, it is incompatible with current consumers of the Player Management API. Many third party integrations expect the plugins specified in a player’s configuration will have a name property rather than registry_id and version properties.

So if we can’t utilize any of the new plugin registry behavior in the current version of the Player Management API, we have only one option - new major version!

In /v2/ of the Player Management API, we are free to return the newer format compatible with the plugin registry because we are no longer limited by existing interactions with third party consumers of the API. These integrations will need to update themselves in order to utilize the advantages of the plugin registry.

Deprecation Period

Rather than immediately stop serving requests to /v1/ of the Player Management API, we are now in a transitionary period where both /v1/ and /v2/ are valid endpoints. This introduces a new challenge, as we must maintain interoperability of players across major versions of the API while also supporting plugins in differing formats.

To achieve this we added a translation layer for player configuration modifications through the API while also migrating existing player configurations into the newer plugin registry compatible format. Any read requests for player configurations matching the /v1/ endpoint are modified such that plugins with registry_id and version properties are removed and replaced with the matching script and stylesheet URIs within their corresponding arrays.

The same process happens in reverse for player configuration modifications at the /v1/ endpoint. Any player configurations containing scripts and stylesheets matching a plugin stored in the registry will be automatically migrated to the newer format. For example, creating or modifying a player configuration at the /v1/ endpoint with the following data…

{
  "scripts": [ "//players.brightcove.net/videojs-social/3/videojs-social.min.js" ],
  "stylesheets": [ "//players.brightcove.net/videojs-social/3/videojs-social.css" ],
  "plugins": [ { "name": "social" } ]
}

… will yield the following player configuration available at the /v2/ endpoint automatically:

{
  "scripts": [],
  "stylesheets": [],
  "plugins": [ { "registry_id": "@brightcove/videojs-social", "version": "3.x" } ]
}

Requests for the player configuration at the /v1/ endpoint will be unmodified with scripts and stylesheets matching the input. This process is in effect for scripts and stylesheets matching both major and specific versions of the registry plugins. Scripts and stylesheets that do not match registry plugins are unaffected. We advise not to use the old format against the /v2/ endpoint because translation will not occur - this could introduce compatibility issues, as the Studio is expecting the newer format.

The following picture helps illustrate the translation process:

v2 blog (1).png

This process allows the Player Management API to maintain fluidity between the two major versioned endpoints while maintaining a single format of plugin entries for internal player configuration storage.

Inlining Scripts & Stylesheets

In addition to the plugin registry, /v2/ of the Player Management API supports inlining plugin scripts and stylesheets directly within the plugin array element. This helps with readability, logical organization of player configurations, and avoiding configuration errors.

The player configuration snippet below demonstrates a custom plugin inlining its scripts and stylesheets:

{ 
  "plugins": [ 
    {
      "name": "helloPlugin",
       "scripts": [ "http://solutions.brightcove.com/truggles/helloPlugin.js" ],
       "stylesheets": [ "http://solutions.brightcove.com/truggles/hello.css" ]
    }
  ]
}

Conclusion

The Plugin Registry within the Player Management API makes managing versions of plugins intuitive, maintainable, and safely automatic. The translation layer allows for an easier development transition to the newer data format for current Brightcove API consumers. The plugin registry was designed to support not only future versions of existing plugins, but also the addition of entirely new plugins - keep an eye out for the growing list of plugins and how they make configuring your player even easier.

FAQs

Q. When is /v1/ of the Player Management API going to be officially removed?

A. March 31st, 2018. At that point all API consumers, including third party integrations, MUST use the /v2/ endpoint.

Q. Will this affect any of my custom plugins?

A. No. Only plugins specified in the registry may be used in the newer format, and the translation of plugins in the registry does not interfere with custom plugins.

Q. Does this change the order of plugin execution at player runtime?

A. Scripts and stylesheets for registry plugins are injected at the beginning of their respective arrays when a player is published. This means all custom plugins will be invoked after Brightcove plugins specified by registry_id within player configurations.

Q. How do I find out which plugins are currently in the registry?

A. The Plugin Registry API documentation provides instructions on how to access the plugins stored in the registry.