27 Oct 2017

[Blog] Library playback with the STREAM_SOURCE trigger

Hello readers! Today I will talk about how MistServer can be set up to work with a large video library.

The issue

When you want MistServer to serve a VOD file, you'd normally add a stream, and configure the path to the file as the stream source.
If you have a folder of several video files, you'd add a folder stream, with its source pointing to the path of the folder. The individual files are then accessible using the main streamname, a +, and then the filename, myfolderstream+video.mp4 for example.
However, these implementations have limits. Having too many configured streams will considerably slow down MistServer. Folder streams are inconvenient for larger libraries, look unprofessional, and are not able to access subfolders.
Once your video library grows beyond a certain point, it's wise to consider a different configuration. You can set up one or more streams with the settings you'd like to use, and then use the STREAM_SOURCE trigger to rewrite the stream source to which file you'd like to stream.

In this blog post I'll discuss an example implementation of this method, using PHP.


Understanding the STREAM_SOURCE trigger

I'd like to explain the inner workings of this method by setting up a stream, that, when requested, plays a random video from the library.
The first step is to configure the stream in MistServer, through the Management Interface.
Let's create a new stream, and call it random. The source doesn't really matter, as we'll be overwriting it, but let's set it to one of our video files. That way, if the trigger doesn't work for some reason, that video will be played.

Now, let's go ahead and configure the trigger.
It should trigger on STREAM_SOURCE. Applies to should be set to the stream we just created, random. The handler url should point to where our trigger script will be hosted. We want MistServer to use the page output, so it should be set to blocking. Let's set the default response to the same fallback video we configured as the stream source.

Alright, to the PHP! We'll need to echo the path to the video we want the stream to play.

First, confirm the page is being requested by MistServer's STREAM_SOURCE trigger:

  error_log("Unsupported trigger type.");
  echo("Unsupported trigger type.");

Next, we want to retrieve the stream name that MistServer reports to the PHP script. This is sent on the first line of the POST body.

//retrieve the post body
$post_body = file_get_contents("php://input");
//convert to an array
$post_body = explode("\n",$post_body);
$stream = $post_body[0];

If the stream name equals random, we'll select a random video id from the library, and return the path. Make sure the path is the only thing that is sent.

if ($stream == "random") {    
  //select a random video from the library array
  $library = get_library();
  $random_video_id = array_rand($library);

  //return the path
  echo $library[$random_video_id];

To simulate a video library, I've set up a little function that indexes video files from a folder, just for this demo. This should be replaced with the library database system when implemented.

That's all. When the stream random is requested, a random video will be shown.
There's a little caveat here, though. If the stream random is already active, a new request will receive the same video. We can prevent this by adding a unique wildcard token to the stream name; that way the stream won't be active yet. In the trigger script, edit the stream name condition:

if (($stream == "random") || (substr($stream,0,7)) == "random+") {

And, on the video page:

$streamname = "random+".rand();

Embed the stream on a page, and every page load a random video will be selected.

Back to the library scenario

Now that we understand how the trigger should be used, let's get back to a more practical use case. There isn't that much of a difference: we want to pass the desired video id to the trigger script, and return the appropriate path. We can simply add the video id to the stream as the wildcard token.
I've also created a new stream, library, and applied the trigger to it.

if ((substr($stream,0,8)) == "library+") {
  $wildcard = substr($stream,8); //strip the "library+" part

  $library = get_library();

  echo $library[$wildcard];

With, on the video page:

$streamname = "library+".intval($_GET["video_id"]);

The URL to our video page could be something user friendly like /Movies/45/Big Buck Bunny Goes To Town/. Simply configure your HTTP server to rewrite the url so that the video id can be extracted.

You can consider using multiple streams (movies, shows, live) for different categories. That way, you can have different stream settings in MistServer to suit your needs.

I hope these examples can help you if you are looking to set up a video library using MistServer. As always, if you have any questions or want to tell us about your awesome project, feel free to contact us.
Next time, Jaron will be back with another behind the scenes blog post.
In the meantime: happy streaming!