Wowza Stream Class Playlist Generator

I’ve received a few comments and e-mails to my post about the Wowza Stream Class asking if I had any kind of playlist generator. I have something in Excel that I use for our weekly live stream and scheduled rebroadcasts. It may require heavy modification to suit your purposes, but it’s helpful to really see how a playlist can come together.

The sheet makes heavy use of some utterly absurd CONCATENATE functions.

Download : WowzaPlaylistGenerator.xlsx

 

Playlist Generator Configuration

Playlist Generator Output

 

 

Windows Updates, To Go!

When I leave for my trip to Haiti in a few weeks, one of the things I’ll be doing is bringing multiple computers up to current patches. There are a few ways to do that:

One is to bring some sort of removable media (optical or flash stick) down and apply them manually. The problem with this is that once I leave, the machines stay in their current state until the next geek can come down and apply the next batch of patches. Downloading patches for multiple machines over developing-world internet connections can easily run into daily bandwidth caps, and Windows Update doesn’t cache very well through a normal proxy server such as Squid.

Another is to use Windows Server Update Services (WSUS). I initially considered setting up a Windows Server VM on my laptop, syncing up the updates stateside and temporarily configuring the machines down there to pull from my impromptu update server. Then I got the idea that a lightweight appliance-type server that lived down there permanently would be a useful solution that would download the patches once and distribute them over the LAN. Since we’re planning on using Microsoft Security Essentials for anti-malware, this solves the problem of definition updates. Daily patch sync would happen in the wee hours of the morning when the oversubscribed connections in Haiti are generally pretty clear.

I rummaged around the office and found a Dell FX160 thin client that we got as a demo unit from Dell (I have a number of blog posts on the topic of this device). It has been gathering dust for some time as it’s hobbled with a 1GB SATA flash disk and limited RAM. After checking on hardware requirements for both Windows Server and WSUS, I went out and picked up a 120GB SSD and a pair of 2GB RAM sticks and put them in. The choice of an SSD wasn’t so much for performance reasons (although it can’t hurt), but for the machine to be entirely solid-state. It’s going to live in a fairly harsh environment where mechanical failures are likely.

Once I got the hardware put together, I hooked up a USB optical drive and loaded Windows Server 2003 R2, and then installed WSUS and performed an update sync. The whole process went mostly smoothly.

Here are a few of the gotchas in installing Windows 2003 on an FX160 thin client, a job it was NEVER meant to do:

  • SATA controller needs to be in ATA mode. If it’s in AHCI mode, Windows 2003 will not recognize the disk.
  • When using a storage device that the BIOS recognizes as a hard drive, it expects to see a fan plugged into the motherboard. This fan is part of the hard drive bracket kit (Dell P/N H224H). When a fan is not detected, each boot will require a manual intervention during POST to press F1.
  • Stock Windows 2003 media does not include video drivers or network drivers for the FX160 (Broadcom NetXTreme 57XX).
  • Dell’s support site doesn’t have the most recent drivers for the Broadcom.
  • It’s virtually impossible to find a 6″ SATA extension connector, either for data, power, or both. I was finally able to find a power extension, but used a standard SATA cable to connect to the other SATA port on the motherboard.

The SSD I used for this is an OCZ Agility 3, 120GB. Disk performance on large writes is almost 100MB/sec, which is about twice as fast as my 7200RPM spindle drive in my laptop. Windows performs very well with 4GB, a SSD, and a 1.6GHz Atom processor.

The next step was to configure the clients to update from the server for testing. I still have one of the Asus netbooks that we deployed to Haiti in a previous trip. This is where I discovered that Windows Home and Windows Starter don’t include the policy editor (gpedit.msc) that I’m used to finding on Pro/Enterprise/Ultimate versions of windows. This is understandable, your average home user doesn’t (and shouldn’t) normally jack with system policy. Fortunately, all the policy editor does is manipulate registry keys, and the process of configuring Windows Update via the registry is well documented. This actually simplifies things, since all I have to do is create a .reg file that I can import on all the target machines.

Next post: Installing Squid. Not content to use this box for mere update caching, we’re gonna have it be our web proxy as well.

Configuring Perl for ASSP on Debian

Quick and dirty apt-get string to install all the requisite perl modules (and associated dependencies) for ASSP on Debian:


apt-get install libcompress-zlib-perl libdigest-md5-file-perl libdigest-sha1-perl libemail-valid-perl libemail-send-perl libemail-mime-perl libfile-readbackwards-perl libclamav-client-perl libweb-simple-perl libmail-spf-perl libmail-srs-perl libnet-cidr-lite-perl libnet-dns-perl libnet-ldap-perl libnet-smtp-server-perl libunix-syslog-perl

Veeam’s Next Big Thing

VeeamHyper-VIt’s official – Veeam is announcing this morning that version 6 of their award-winning backup/replication software will support Microsoft’s Hyper-V virtualization hypervisor. The new version is due out later this year.

What’s Cool about Veeam and Hyper-V

Veeam is once again delivering IT magic by building their own Changed Block Tracking functionality into Hyper-V for some of the highly efficient backup and replication that Veeam is known for. This is going to go a long way toward bringing Microsoft virtualization up to par with VMware. Also included are file-level restore and virtual lab provisioning, as well as SCOM integration.

For non-profits, this is potentially huge, since it brings advanced backup capabilities to the hypervisor that’s included with Windows Server. VMWare is great technology, but for SMB and non-profits, VMWare’s pricing point is painful. When non-profit/education customers can get Windows Datacenter licenses for around $300 a socket (which includes Hyper-V!), suddenly VMWare looks really painful, even after educational discount.

What’s still missing

The initial release will not include Veeam’s U-AIR capability, but they’re hard at work to bring that capability online.

It also lacks the ability to back up/replicate across virtualization platforms, but that’s to be expected.

Veeam hasn’t yet announced pricing/licensing details. What I’d really like to see from Veeam is a per-socket license that is platform-independent.

If you haven’t yet experienced the awesomeness that is Veeam, give the folks at Mirazon a call. Those guys know Veeam up and down and backwards.

Veeam’s Rick Vanover has more at his blog.

Kicking Skype Up a Notch

A few weeks ago, our Senior Pastor asked for some assistance with setting up a skype video conference so that Adam could participate in a meeting being held in Texas. The alternative was to have him fly down to Dallas for a 1-hour meeting, effectively blowing out an entire day of productive hours.

We don’t currently have a dedicated video conference system, so we had to improvise.

We scheduled the meeting in our studio and coordinated with the other end to make the conference happen via Skype.

On our end, we took Adam’s MacBook Pro, and hooked up a Canon XL2 via FireWire for the video, a Shure wired lapel mic hooked to the camera (for phantom power) and then the audio output from the camera into the MacBook’s line-level audio input (because it appears that Skype doesn’t recognize the audio device on the XL2). We then connected the audio and display output from the mac into a 40″ LCD TV.

Here’s what it looked like:

The end result is a conference that looks and sounds excellent.

Amazon EC2 and DNS

Just discovered an interesting little tidbit about using DNS from within Amazon’s EC2:

When resolving the public DNS name of an EC2 instance, from another EC2 instance, you will get the internal IP address of that instance.This is useful if you have multiple EC2 instances talking to each other.

For example, if you have a Wowza edge/origin setup, you have your origin set up on an elastic IP for consistency in your configuration, and point your edge servers to that IP.

Now this may seem insignificant until you remember that any traffic between EC2 instances via the public IP (elastic IP or not) is going to incur a charge of 1 cent per gigabyte. If you’ve got a large streaming setup, that can add up.

If you want to use your own domain name for your server, be sure to use a CNAME record to the public IP instead of an A record. The A record will always return the public IP. The CNAME will tell the nameserver what the public DNS name is for that instance, which EC2’s nameservers will then return as the internal address.

With an A record to the public (elastic) IP:

ubuntu@ip-10-245-bar-baz:~$ nslookup wms.domain.org.
Non-authoritative answer:
Name:   wms.domain.org
Address: 50.16.XXX.YYY

With a CNAME record to the public DNS name:

ubuntu@ip-10-245-bar-baz:~$ nslookup wms.domain.org.
Non-authoritative answer:
wms2.domain.org      canonical name = ec2-50-16-XXX-YYY.compute-1.amazonaws.com.
Name:   ec2-50-16-XXX-YYY.compute-1.amazonaws.com
Address: 10.114.AAA.BBB

Inside Wowza Startup Packages

Startup packages are one of the more useful features of Wowza Media Server for EC2 – they allow you to custom-configure a system for rapid scaling and provisioning. Wowza provides several starter packages to build on.

A startup package is a file (up to 16384 bytes in size) that’s passed to the instance through the –user-data-file parameter on the API tools (if you’re uploading it via the AWS Web Console, you’ll need to encode it to Base64 and paste it into the text box) . There are a few ways that the data can get into the instance, which Amazon documents over here. For a generic EC2 instance, this can be anything, from text to binary data, depending on what the processing on the target instance is set up to do. In the case of Wowza, it’s a zip file with a specific structure. Much of this is digested from the Wowza for EC2 guide.

File Contents

A startup package for EC2 contains the following:

  • startup.xml (startup manifest)
  • tuning folder
  • wowza folder
  • Any other folders referenced in the startup manifest

A startup package is limited to a maximum of 16KB.

Startup activities are logged to /usr/local/WowzaMediaServer/logs/wowzamediaserver_startup.log. This is a good place to look if it’s not behaving as expected. The package is unpacked to /opt/working.

Startup Manifest

This file controls the startup processing for instantiating a Wowza server on Amazon EC2. It allows three commands: Install, Download, and RunScript.

Download

The <Download> command will download content from a web server and save it to the local Amazon instance. The <Download> command includes the following elements: URL, Data, Header, Destination, and Action:

<Download>
<URL>[URL]</URL>
<Data>[data]</Data>
<Header><Name>[key-name]</Name><Value>[value]</Value></Header>
<Header><Name>[key-name]</Name><Value>[value]</Value></Header>
<Destination>[relative-or-absolute-file-path]</Destination>
<Action>[UNZIP, INSTALL]</Action>
</Download>

The only two required elements are <URL> and <Destination>. To download a file from the url http://www.mycompany.com/myfile.zip, save it to the local machine at the location /opt/myfile.zip and unzip the file after download, the command is:

<Download>
<URL>http://www.mycompany.com/myfile.zip</URL>
<Destination>/opt/myfile.zip</Destination>
<Action>UNZIP</ Action >
</Download>

When completed, the contents of the zip archive are located in /opt.

One use of the <Download> command is to work around the 16kB startup package size limitation. For example, if you need to add several .jar files into the Wowza Server “lib” folder and these files push your startup package size over the 16kB limit, you might package these files into a separate zip archive. You can then host this zip archive on a web server and use the <Download> command to install the files into the Wowza Server “lib” folder.

It’s important to remember that the zipfile path structure is critical. If it uses no paths, you’ll need your destination to be where it ultimately lives, either in the staging area, or the absolute path to the Wowza install. When creating the zipfile with relative paths, create the path tree as if you were in the Wowza installation root.

URL

The <URL> is the URL of the file to be downloaded. The download can be performed over SSL by starting the url with https:// rather than http://. The url can also contain query parameters. The file will be downloaded using the GET method unless <Data> is specified.

Data

The Data is text data that will be included as part of the body of the HTTP request. You can use post data to send user name and password information to your web server so you can protect your content.

Header: <Name> and <Value>

The <Header> elements are name value pairs added to the header part of the HTTP request. An example would be:

<Header>
<Name>Content-type</Name>
<Value>text/plain</Value>
</Header>

Destination

The <Destination>element is the path to which the file will be saved (including the filename). This path can be relative or absolute. The base directory when calculating a relative file path, is the root directory of the startup package (the folder that contains the startup.xml file).

Action

The <Action> element is the action performed after the file is downloaded. The action can either be UNZIP or INSTALL. If the action is UNZIP the downloaded file will be unzipped using the unzip command. If the action is INSTALL the downloaded file will be unzipped and the contents of the folder will be installed (copied) into the Wowza Server installation folder.

Install

The <Install> command will copy the contents of a folder into the Wowza Server installation folder. The <Install> command can either contain a single <Package> element or single <Folder> element.

<Install>
<Package>[path-to-package]</Package>
</Install>
<Install>
<Folder>[foldername]</Folder>
</Install>

The Package path can reference an external URL, like http://wowzamediasystems.s3.amazonaws.com

The Folder path can reference either a relative path (relative to the root of the startup package where Startup.xml is located) or an absolute path on the local file system.

RunScript

The <RunScript> command will execute a script on a running Amazon instance.

<RunScript>
<Script>[relative-or-absolute-file-path]</Script>
<Param>[parameter]</Param>
<Param>[parameter]</Param>
</RunScript>

Script

The <Script> element is the path to the script file to be executed. This path can be relative or absolute. The base directory when calculating a relative file path, is the root directory of the startup package (the folder that contains the startup.xml file). This can refer to a script, or be a single-line command.

Any files referenced in the script need absolute paths or a path relative to the startup package root.

Param

The <Param> elements are parameters that will be passed to the running script. For example the following <RunScript> command:

<RunScript>
<Script>scripts/copyfile.sh</Script>
<Param>filea.txt</Param>
<Param>fileb.txt</Param>
</RunScript>

Would be the equivalent of executing the command:

./scripts/copyfile.sh filea.txt fileb.txt

Environment Variables

The following environment variables are available to scripts launched by the startup processor:

AWSEC2_METADATA_INSTANCE_ID - Amazon instance id
AWSEC2_METADATA_SECURITY_GROUPS - Security group
AWSEC2_METADATA_LOCAL_IPV4 - Local IP address
AWSEC2_METADATA_AMI_LAUNCH_INDEX - Launch index
AWSEC2_METADATA_PUBLIC_HOSTNAME - Public host name
AWSEC2_METADATA_PRODUCT_CODES - DevPay product code
AWSEC2_METADATA_INSTANCE_TYPE - instance type (m1-small, m1-large, m1-xlarge)
AWSEC2_METADATA_HOSTNAME - Public host name
AWSEC2_METADATA_LOCAL_HOSTNAME - Local host name
AWSEC2_METADATA_PUBLIC_IPV4 - Public IP address
AWSEC2_METADATA_AMI_MANIFEST_PATH - S3 manifest path
AWSEC2_METADATA_RESERVATION_ID - Instance reservation ID
AWSEC2_METADATA_AMI_ID - AMI ID

Wowza Folder

The Wowza folder in the startup package is meant to mirror the Wowza installation folder on the server. When the Install command in the startup manifest is invoked with this folder, the file structure of this folder will be copied to the installation folder.

Applications Tree

Contains folders for each Wowza application configured. There are not typically any files in this tree, just folders.

Conf Tree

Contains the configuration files for the server (at the root of the tree) and for each application (in folders matching the applications tree

Content Tree

Contains any content referenced by the applications. This is where SMIL files, stream schedules, and such go. Any audio/video content that goes here won’t fit in the startup package and will need to be downloaded separately.

Lib Tree

Contains any additional modules for the server.

Tuning Folder

This folder contains tuning scripts that tune the Wowza server.  It copies the requisite environment variables and tuning commands to a script executed as part of the Wowza startup, which happens after the startup processor is run.

Scripting

The following useful linux tools are available on the standard EC2 build (based on Fedora):

  • MySQL client commands
  • zip/unzip, bzip/bunzip, gzip/gunzip
  • s3fs
  • Compiler and build tools
  • WGet
  • RSync
  • SSH commands
  • dos2unix/unix2dos
  • curl
  • perl 5.8.8 (with MySQL support)
  • GPG
  • Shells: bash, sh
  • RRDTool
  • PHP5
  • EC2 API tools

Services

The following services are available on the EC2 build of Wowza, in startup order:

  • SNMP
  • SSH
  • FTP (Anonymous access to /var/ftp/)
  • MySQL (default password = “password”)
  • Wowza
  • Apache 2 – port 8080, content in /var/www/html
    • Cacti
  • Java Console

Startup package scripts and data are invoked by the Wowza startup script. If you modify any applications started prior to that, you’ll need to restart them.

Example

Here’s what my startup.xml looks like:

<Startup>
 <Commands>

 <!--
  Comments
  -->

 <Download>
  <URL>http://webserver/wowza/wms-plugin-collection.zip</URL>
  <Destination>wowza/lib/wms-plugin-collection.zip</Destination>
  <Action>UNZIP</Action>
 </Download>

 <RunScript>
  <Script>scripts/mount-s3.sh</Script>
 </RunScript>

 <Install>
  <Folder>wowza</Folder>
 </Install>

 <RunScript>
  <Script>tuning/tune.sh</Script>
 </RunScript>

 <RunScript>
 <Script>scripts/enable_cacti.sh</Script>
 </RunScript>
 </Commands>
</Startup>

How this works:

  • Download the wms-plugin-collection.zip file and dump it in the staging area for wowza (/opt/working/wowza/lib)
  • Unzip it (this leaves the zip file behind, but that doesn’t matter)
  • Run the a script that mounts some s3 buckets and copies them into the content folder:
#!/bin/sh
mkdir -p /usr/local/WowzaMediaServer/content/s3
mkdir -p /usr/local/WowzaMediaServer/content/archives

s3fs bucket1 -o accessKeyId=XXX -o secretAccessKey=YYY /usr/local/WowzaMediaServer/content/s3

s3fs bucket2 -o accessKeyId=XXX -o secretAccessKey=YYY /usr/local/WowzaMediaServer/content/archives/

cp /usr/local/WowzaMediaServer/content/s3/* /usr/local/WowzaMediaServer/content
  • Install the Wowza configs from the staging area
  • Run the tuning scripts
  • Run a script that automatically enables Cacti (since polling the local host is disabled by default):
#!/bin/sh
mysql -u root -ppassword < scripts/enable_cacti.sql

enable_cacti.sql contains the following statement:

update cacti.host set disabled='' where id='2';

(note that if you’re using an Elastic IP, you’ll need to restart the Wowza Service for Cacti to behave)

In my Wowza directories, I have:

  • applicationsdirectory
    • live directory (think of this as a mount point – it’s an empty directory, but has to exist)
  • confdirectory
    • Server.xml (general server parameters)
    • VHost.xml (host bindings, HTTP providers, etc.)
    • livedirectory (this is the application configuration for the live application)
      • Application.xml (defining the live application)
  • content directory
    • ipad.smil ( multi-bitrate stream selection for iOS devices)
    • mobile.smil (defining where the Roku stream goes – this abstracts a potentially changing stream name, as well as giving me a way to track Roku traffic using this perl stats collection script)
    • streamschedule.smil (defines the schedule for the Stream Class module)
    • Additional material is pulled from S3 in the aforementioned script
  • lib directory (empty mount point)

To start my Wowza instances, I create the startup package file and tree structure, and then call this startup script that packs up the zip file and fires off the instance.

More Updated Code

Updated the Wowza Launch Script. Changed it to be more friendly to a non-root user directory, as well as adding logic that makes the startup package on the fly, so that if you want to edit the contents, the next launch will send the current incarnation.

Stay tuned for a post soon on the anatomy of a Wowza startup package for EC2.