Encore - Original Project Description

(Original post on March 11, 2010 @5:32pm)

A video streaming management system.  That is what I needed.  The demands for video streaming were mounting up - the medical students at my University were requesting streaming support for video-recorded classes,  doctors were requesting educational and instructional videos to be posted on the web, news and spotlight videos to be put on the web, recorded video teleconferences, recorded seminars, etc, the list goes on...

For a couple of years, a combination of Adobe Flash Streaming Server (RTMP) and Apple's Darwin Streaming Server (RTSP) worked for me.  Darwin was free but RTSP can be problematical with firewalls and Apple Quicktime as a player is limited in it's customizations.  Adobe Flash worked better and Flash players were many and customizable except a bit daunting to configure for a particular video.  Quicktime was a bit easier in that respect.

Time went by and then the videos piled up...

Clever directory schemes and ingenious file naming conventions can only take you so far.  "I'm sorry, you want to search through a list of the archived videos? Ummmm, ya, can't do that.  How do you upload a video to the streaming server? Oh, well, you see, you use this program called secure ftp, drop it into a folder and follow my naming conventions then follow the following instructions to get the flash player embedded into your web site so it looks like the video is being streamed from your web site, not my server... easy huh?"  Not at all!

What to do?

There are a few solutions for multimedia management that handle video streaming out there such as the commercial product Accordent and the open-source program Jinzora.  I have not looked at either of them in-depth but rather I decided to try out an idea I had in the back of my head, a project idea which I ended up calling "Encore".

Encore is fusion of the Drupal Content Management System and Wowza Media Systems Wowza Media Server 2 streaming server and leverages the open-source Flash media player Flowplayer 3.1.

What is Drupal?

Drupal is an amazing, versatile, open-source, PHP-based, web content management system.  I used Drupal to provide the missing "front-end" to my streaming server.  Using Drupal in Encore, simple web front-ends replace sftp and allow the average user to upload their videos and annotate them with customizable and searchable metadata fields.  As much additional metadata as needed for each video can be added in Drupal using the Drupal module CCK.  Once the web entry form is filled out and submitted, Drupal then drops the video into a folder to which the Wowza streaming server is mapped.

Drupal, with the correct modules and modifications, then creates a web page with the open-source Flash player Flowplayer 3.1 embedded in it to show the video, but not as a http download, but as a stream from the streaming server.  The end-user doesn't need to understand anything about how the flash player is set up.

Ok, how is it all put together?  Here is the list of software that is needed:

1) Wowza Media Systems Wowza Media Server 2 - is the streaming server.

2) Flowplayer 3.1 - provides the player for the streaming embedded into the Drupal web pages

3) Drupal-6.16 - the web front with loaded of modules to provide additional functionality

4) Drupal Modules: (Drupal modules extend and enhance core Drupal functionality)

the minimal set of modules needed are:
CCK
Custom Formatters
FileField
FileField Paths
SWF Tools - I had to modify this module to support Flowplayer's Secure Streaming module
Token

I added extra functionality adding the additional Drupal modules:
Date
Taxonomy Access Control Lite
Google Analytics
jQuery UI
LDAP Integration
Views
Wysiwyg

5) about ~20 lines of PHP code that I wrote

6) Two ip's multihomed to the same server

7) Redhat RHEL 5.X (for those who can't afford Redhat RHEL, CentOS works just fine)

8) Enough network bandwidth to your server to support the streaming!

The modifications I made to the SWF Tools module were to enable the Secure Streaming support in Flow Player.  SWF Tools provides the "wrapper" around Flowplayer to bring it into Drupal.  As soon as I figure out how to write a Drupal patch, I will be submitting it the the SWF Tools Drupal module for public consumption.  If all of your videos are going to be public, this secure streaming support is not required.

Part II

 

Why Wowza for streaming?

I have to thank the FlowPlayer people for leading me to Wowza.  One of the motivations for me re-thinking how I was handling streaming at my university were requests for authenticated (password-protected) video streams.  Darwin handles this to a degree with Apache htaccess-like username/password access.  The limitation with Darwin was that there was no way to link it to an external authentication source like LDAP, at least not in the version I was using.  As it was, firewall and customization issues had already driven me to explore the use of Adobe Flash streaming as an alternative using Flowplayer as the client player.  Adobe higher-end Flash streaming server supported authenitcation, but the base product only supported developer hooks to implement authentication.  I really did not have the time to build this out so I began searching around for product that could do it.  In searching around, I had read that Flowplayer supported some form of authentication with a streaming server named Wowza already so I followed the trail.

As I read through the Wowza site, a few things caught my attention about Wowza.  The first was the secure token module.  Streams could be protected by requiring the player to pass a "secret" token to the Wowza streaming server, otherwise, the stream would not be delivered.  For additional protection of the token (since you could see the token in the HTML page that FlowPlayer was embedded in) you could compile your token into the FlowPlayer software itself.  Second, was that Wowza was written in Java and that API's were explosed for further development.  I do a lot of development in Java so this was a plus for me.  Third, Wowza supports HTTP Live Streaming which is the native streaming protocol of the iPhones.  HTTP Live Streaming is new and not widely supported yet so Wowza was the first product that I had run into that supported it.  Wowza does a lot more, but these are the things that attracted me the most.

Putting it all together

The instructions here will focus on what I had to do to get everything to work and will assume that you have some understanding of Drupal and Wowza (or at least, that you will study up on how to deal with those things)

Step 1 - Setup up your RHEL/CentOS server.  My server is 32-bit RHEL 5.X with 4GB RAM.  It actually runs as a virtual server and it's storage is on a SAN.  But a stand-alone server will work fine.  Configure and bind TWO ip addresses to your server.  The reason for this is that Wowza and Drupal will both want to use ports 80 and 443.  Ok, you could have Drupal listen on something else, but it is easier for me to tell students and faculty a URL that does not end in ":8000" or some other non-standard port.

Step 2 - install the latest JDK from http://www.javasoft.com (Wowza needs this)

Step 3 - install Drupal 6.X with the Apache http and bind to ONE of the ip addresses.

Step 4 - install Wowza on other ip address on same server

Step 5 - install CCK, Custom Formatters, FileField, FileField Paths, SWF Tools, and Token

Step 6 - create a new content type in Drupal, call it what you want, but I called my "Protected Streaming Video" as a long name and the machine name "protectedstreamingvideo" as the machine name.

Step 7 - add a field to this content type of type "FileField" and call it "Flash Video" as a long name and "flashvideo" as a short machine name.  Now, in the configuration for this field, FileField allows you to specify a path rather than defaulting to the Drupal files folder for the Drupal installation.  For mine, I set "streaming/protected".

Step 8 - configure a Wowza application and point the content source in the config file to the above path for the flash video FileField.  Use the default application.xml file for now with just the modification for content.  Later we will enable the actual protections.

Step 9 - SWF Tools - this module does alot of great things, but what we will be using for this project is that it provides a wrapper around FlowPlayer to make embedding the Flash Video much easier.  I've been using SWF Tools/Flowplayer ever since I started using Adobe Flash Server because it makes it much easier to get FlowPlayer up and running rather than configure it from scratch.  Another benefit is that when you need to update your FlowPlayer modules (the base module and the Streaming module) you can update it in one location rather than worry about all of the places in your web site that would need to be changed if you did it manually.  I had looked at other Drupal modules that handle video like "Video" and "Flashvideo", but neither did exactly what I needed them to do.

At this point, if you upload a flash video using this new content type in Drupal, the video will be dumped into a folder that Wowza will use to stream it.  If the video/node is deleted from Drupal, the flash video is removed.  However, the content type as it is will not display Flowplayer yet and give us easy streaming access.

Step 10 - custom formatters module - this module is key to bringing everything together.  It allows you to over-ride the default display of CCK field in Drupal with Tokens and/or custom PHP code.  So, go to

Custom formatters and create a new format (call it whatever you like) and set it as type "advanced" so we can put in a block of PHP code.  In the field types box, put "filefield" since we will apply this custom formatter against out flash video filefield.  Now for the PHP code.  I did not have to modify the custom formatters module, I only needed to make a PHP code block to rewrite the filefield path for streaming use.  It's actually my first PHP code ever.  Not a lot, but it works :-)  In the code we will access SWF Tools PHP style...

**********************************************************************
// this line grabs the file path as it is in Drupal
$eb = ($element['#item']['filepath']) ? $element['#item']['filepath'] : '';

// now we manipulate the path to create the Wowza streaming URL that SWF Tools will use
$eb = str_replace("sites/myserver.edu/files/streaming/protected/","",$eb);

//  this section deal with the different way that flv and f4v URLS are handled
$ebext = substr($eb,-4);
if ( $ebext == '.f4v') {
     $eb = "mp4:".$eb;
} else {
      $eb = $eb;
}

// now we create the SWF Tools call to embed Flowplayer (it assume you configured SWF Tools with Flowplayer correctly)
print swf($eb, array(
             'params' => array('width' => '640', 'height' => '480'),
            'flashvars' => array('type' => 'rtmp'),
            'othervars' => array('stream' => 'rtmp://streaming.informatics.stonybrook.edu/protected','methods' => array('action' =>
'swftools_flv_display'))
          ));
**********************************************************************

Enter this PHP code and save the custom formatter.

Step 11 - go back to the configure of the content type created earlier and go to "Display Fields".  For the "Flash Video" filefield, set both label and teaser to "HIDDEN" and set the full node to the name of

the custom formatter we created in #10.  Click save.  At this point, if you did everything correctly and I did not botch the instructions, an uploaded flv/f4v video should now be visible with Flowplayer as a STREAM"

Now at this point, the video plays but it is not protected.  To protect the video with encryption and the secure token aspect of Wowza, a few more steps are required.

Step 12 - download and install secure token module for Wowza.  Also, either set up Wowza for SSL (RTMPE).  Either used the self-signed or buy a certificate from a CA.

Step 13 - reconfigure your Application.xml (in my case, i call the application "protected") as follows (my modifications to the default Application.xml are in bold):

<Root>
        <Application>
                <!-- Uncomment to set application level timeout values
                <ApplicationTimeout>60000</ApplicationTimeout>
                <PingTimeout>12000</PingTimeout>
                <ValidationFrequency>8000</ValidationFrequency>
                <MaximumPendingWriteBytes>0</MaximumPendingWriteBytes>
                <MaximumSetBufferTime>60000</MaximumSetBufferTime>
                <MaximumStorageDirDepth>25</MaximumStorageDirDepth>
                -->
                <Connections>
                        <AutoAccept>true</AutoAccept>
                        <AllowDomains></AllowDomains>
                </Connections>
                <!--
                        StorageDir path variables

                        ${com.wowza.wms.AppHome} - Application home directory
                        ${com.wowza.wms.ConfigHome} - Configuration home directory
                        ${com.wowza.wms.context.VHost} - Virtual host name
                        ${com.wowza.wms.context.VHostConfigHome} - Virtual host config directory
                        ${com.wowza.wms.context.Application} - Application name
                        ${com.wowza.wms.context.ApplicationInstance} - Application instance name

                -->
                <Streams>
                        <StreamType>default</StreamType>
                        <StorageDir>/www/files/streaming/protected</StorageDir>
                        <KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir>
                        <!-- LiveStreamPacketizers (separate with commas): cupertinostreamingpacketizer, smoothstreamingpacketizer, cupertinostreamingrepeater, smoothstreamingrepeater -->
                        <LiveStreamPacketizers></LiveStreamPacketizers>
                        <!-- Properties defined here will override any properties defined in conf/Streams.xml for any streams types loaded by this application -->
                        <Properties>
                        </Properties>
                </Streams>
                <!-- HTTPStreamers (separate with commas): cupertinostreaming, smoothstreaming -->
                <HTTPStreamers>cupertinostreaming,smoothstreaming</HTTPStreamers>
                <SharedObjects>
                        <StorageDir></StorageDir>
                </SharedObjects>
                <Client>
                        <IdleFrequency>-1</IdleFrequency>
                        <Access>
                                <StreamReadAccess>*</StreamReadAccess>
                                <StreamWriteAccess>*</StreamWriteAccess>
                                <StreamAudioSampleAccess></StreamAudioSampleAccess>
                                <StreamVideoSampleAccess></StreamVideoSampleAccess>
                                <SharedObjectReadAccess>*</SharedObjectReadAccess>
                                <SharedObjectWriteAccess>*</SharedObjectWriteAccess>
                        </Access>
                </Client>
                <RTP>
                        <!-- RTP/Authentication/[type]Methods defined in Authentication.xml. Default setup includes; none, basic, digest -->
                        <Authentication>
                                <PublishMethod>digest</PublishMethod>
                                <PlayMethod>digest</PlayMethod>
                        </Authentication>
                        <!-- RTP/AVSyncMethod. Valid values are: senderreport, systemclock, rtptimecode -->
                        <AVSyncMethod>senderreport</AVSyncMethod>
                        <MaxRTCPWaitTime>12000</MaxRTCPWaitTime>
                        <IncomingDatagramPortRanges>*</IncomingDatagramPortRanges>
                        <!-- Properties defined here will override any properties defined in conf/RTP.xml for any depacketizers loaded by this application -->
                        <Properties>
                        </Properties>
                </RTP>
                <MediaCaster>
                        <!-- Properties defined here will override any properties defined in conf/MediaCasters.xml for any MediaCasters loaded by this applications -->
                        <Properties>
                        </Properties>
                </MediaCaster>
                <MediaReader>
                        <!-- Properties defined here will override any properties defined in conf/MediaReaders.xml for any MediaReaders loaded by this applications -->
                        <Properties>
                        </Properties>
                </MediaReader>
                <LiveStreamPacketizer>
                        <!-- Properties defined here will override any properties defined in conf/LiveStreamPacketizers.xml for any LiveStreamPacketizers loaded by this applications -->
                        <Properties>
                        </Properties>
                </LiveStreamPacketizer>
                <HTTPStreamer>
                        <!-- Properties defined here will override any properties defined in conf/HTTPStreamers.xml for any HTTPStreamer loaded by this applications -->
                        <Properties>
                        </Properties>
                </HTTPStreamer>
                <Repeater>
                        <OriginURL></OriginURL>
                        <QueryString><![CDATA[]]></QueryString>
                </Repeater>
                <Modules>
                        <Module>
                                <Name>base</Name>
                                <Description>Base</Description>
                                <Class>com.wowza.wms.module.ModuleCore</Class>
                        </Module>
                        <Module>
                                <Name>properties</Name>
                                <Description>Properties</Description>
                                <Class>com.wowza.wms.module.ModuleProperties</Class>
                        </Module>
                        <Module>
                                <Name>logging</Name>
                                <Description>Client Logging</Description>
                                <Class>com.wowza.wms.module.ModuleClientLogging</Class>
                        </Module>
                        <Module>
                                <Name>flvplayback</Name>
                                <Description>FLVPlayback</Description>
                                <Class>com.wowza.wms.module.ModuleFLVPlayback</Class>
                        </Module>
                        <Module>
                                <Name>ModuleRequireSecureConnection</Name>
                                <Description>ModuleRequireSecureConnection</Description>
                                <Class>com.wowza.wms.plugin.security.ModuleRequireSecureConnection</Class>
                        </Module>
                        <Module>
                                <Name>ModuleSecureToken</Name>
                                <Description>ModuleSecureToken</Description>
                                <Class>com.wowza.wms.plugin.security.ModuleSecureToken</Class>
                        </Module>
                </Modules>
                <!-- Properties defined here will be added to the IApplication.getProperties() and IApplicationInstance.getProperties() collections -->
                <Properties>
                        <Property>
                                <Name>requireSecureConnection</Name>
                                <Value>true</Value>
                                <Type>Boolean</Type>
                        </Property>
                        <Property>
                                <Name>secureTokenSharedSecret</Name>
                                <Value>mysecrettoken</Value>
                        </Property>

                </Properties>
        </Application>
</Root>

Step 14 - modifying the Application.xml will require you to restart Wowza

Step 15 - compile your secret token into Flowplayer.  The steps for this are at http://www.flowplayer.org.  You will also need to download the Flowplayer "secure streaming" module.

Step 16 - Since we are using the SWF Tools module to wrap Flowplayer we are left with the problem that SWF Tools for Drupal does not support the Flowplayer "secure streaming" module.  This marks my next

forray into PHP and my first Drupal module hack.  Not a lot, but it worked.  Insert the following around line 200 in flowplayer3.module in SWF Tools just under the lines:

    // Set the path to the source of the stream
    $flowplayer['plugins']['stream']['netConnectionUrl'] = $vars->othervars['stream'];

    // EB Hack - define connectionProvider
    if (isset($vars->othervars['lock'])) {
      $flowplayer['clip']['connectionProvider'] = 'lock';
      $flowplayer['plugins']['lock']['url'] = $vars->othervars['lock'];
    }

At this point in my project, it would be nice to add the GUI aspect of Flowplayer secure streaming module support and make it more generalized and submit it as a patch to the Drupal SWF Tools project. 

Please let me note though, that when I went to submit the request for securestreaming support for Flowplayer in SWF Tools and to post my above hack as proof-of-concept, that another gentleman had wrote his own securestreaming patch for SWL Tools and had already rounded out the modifications with GUI and made it generalized.  *bows*  What would also be nice to see in SWF Tools is the additional support for Wowza Secure Token so that the secure toekn could be modified and updated.  It is a bit more secure to compile it in, but not everyone has the time or expertise to do that.

Step 17 - update the configuration for the custom formatter that we created in the above.  Change the PHP block to:

*************

$eb = ($element['#item']['filepath']) ? $element['#item']['filepath'] : '';
$eb = str_replace("sites/encore.informatics.stonybrook.edu/files/streaming/protected/","",$eb);
$ebext = substr($eb,-4);
if ( $ebext == '.f4v') {
     $eb = "mp4:".$eb;
} else {
      $eb = $eb;
}
print swf($eb, array(
             'params' => array('width' => '640', 'height' => '480'),
            'flashvars' => array('type' => 'rtmp'),
            'othervars' => array('stream' => 'rtmpe://myserver.edu/protected','methods' => array('action' =>
'swftools_flv_display'), 'lock' => 'http://encore.informatics.stonybrook.edu/sites/all/modules/swftools/shared/flowplayer3/flowplayer.securestreaming-3.1.3-dev.swf')
          ));

*****************
I will update the code here when SWF Tools is updated to support flowplayer securetoken.

The's the nutshell of it.....

At this point, the video will be shown in the web page with Flowplayer and streamed over RTMPE (encrypted RTMP).  Since the secure token is compiled into Flowplayer, it would be difficult to play the video from another site without knowing or having the secure token.  I've have also added to the Encore solution the following Drupal modules:

LDAP integration - my students authenticate off the LDAP that I porvide in out CommuniGate Pro mail server.  I had to make a small modification in LDAP integration to deal with the way CommunniGate deals with user IDs.  Write to me if you are trying to authenticate off of CommuniGate and I will send you the modification.

Taxonomy Access Control Lite - this module allows me to control access to different groups of videos based on taxonomies.  Some professors only want the students of their class to see their videos.

Google Analytics - This Drupal module allows me to gather analytics on what people are watching what videos and everything that Google Analytics has to offer.

CCK - CCK allows us to add many additional fields to each web/node in Drupal.  This allows for fields such as "recorded on", "start showing on", "stop showing on", "video is for class name.." and so forth.

Views - allows custom lists and views on various node meta data including content, taxonomy, and CCK.

Drupal allows for discussion threads to be added to *any* web/node/video for interactive discussions.  Leveraging Drupal with Wowza makes for a very powerful solution for video streaming management. 

Currently, my Encore installation is delivering videos for most of my first years medical students and many faculty.  The system, both Drupal and Wowza have been operating stable since February 18, 2010 and has been well received by the users.  Currently, I am testing the auto-creation of HTTP Live streaming links so that in addition to the Flowplayer, a link will be displayed so that an iPhone user can trigger the stream player on the iPhone for iPhone stream viewing.  This will be part of a "unprotected" Drupal node type.  I did not include iPhone on the protected videos since the iPhone will not send the secure token that the protected Application.xml requires.  But the working code is just a variant of the above technique.  The real work on this project was done by all of the people who developed Drupal and Wowza Media Server.  My hat goes off to them all.  My additions are just clever tricks at best.  But they work! :-)  - E