Chris Mendez in Radio, For Developers, AWS, Audio

Cloud-Based Radio Using Adobe Media Server

Adobe Flash may be dead but Adobe Media Server carries a lot of really powerful features. This entry aims to identify a few of those worthwhile features so that you can use this information while shopping for a better solution.

The Challenge of Cloud-Based Radio

Here's a quote from Apple's documentation. I truly believe Apple hit the nail on the head.

Many existing streaming services require specialized servers to distribute content to end users. These servers require specialized skills to set up and maintain, and in a large-scale deployment this can be costly. HTTP Live Streaming avoids this by using standard HTTP to deliver the media. Additionally, HTTP Live Streaming is designed to work seamlessly in conjunction with media distribution networks for large scale operations.

Source: HTTP Live Streaming Overview

The Adobe Media Server pretty much embodies everything Apple believes is wrong with streaming today. It's expensive to set-up, expensive to maintain and unnecessarily complicated.

Although Apple has a lot of strong opinions, instead of challenging them, Adobe smartly created a server that embraces those opinions as well as their own. Therefore, Adobe Media Server offers three types of solutions:

  1. Video/Audio delivery using Adobe Flash using the RTMP protocol.
  2. HTTP Dynamic Streaming using Adobe Flash using the RTMP protocol or HTTP protocol.
  3. HTTP Live Streaming using using HTTP protocol.

SOLUTIONS

Adobe Media Server offers HTTP Live Streaming (HLS) which enables you to deliver just-in-time on-demand, adaptive bitrate audio using MP4 over HTTP connections.

You may hear about HDS which is not the same as HLS. Here's the explainer.
HLS is an Apple solution. HDS is Adobe's solution to the exact same problem. Source

This is great news because HTTP delivery means that your office's firewall won't block it. Just-in-time means that Apache will chop up the media file and deliver it as a continuous stream instead of a progressive download. This enables users to seek ahead from within a song the same way they would seek ahead within a Netflix movie. The adaptive bitrate means that if your internet connection becomes slow, it can switch over to a small file size. Finally, every browser and device supports MP4 format.

If you want to learn more about adaptive bitrate, watch Adaptive bitrate streaming to iOS.


TRYING IT OUT

Adobe Media Server is unique because it can deliver streaming media to web browsers, iOS, and Android devices using HTTP Dynamic Streaming. There are many packages to purchase but I only suggest this one for now:

Option 1 - Fully Managed

Adobe Media Server on AWS offers a pre-packaged Adobe Media Server sold by Orbitera. It's the fastest way to get up and running.

Option 2 - Self Managed

UPDATED: If you want to install Adobe Media Server on your own, here's an article I wrote on how to install AMS on EC2.


Managing Streaming Services

We want to publish over HTTP so we're going to be very selective in the types of services we can deliver.

On-Demand Streaming

On-demand streaming over HTTP means that the media server will get your file, chop it up into a dozen fragments and issue it over the web in real-time. This job is done by the jit module specifically built for Apache.

You can see how this works by placing a file within this directory and acecssing it through a browser.

/opt/adobe/ams/webroot/vod/

Source

Adaptive Steaming

Adaptive streaming (aka multi-bitrate streaming, dynamic streaming) means that you create multiple renditions of the same piece of content (150kbps, 300kbps, 1500kbps) and publish a manifest file that holds the URI paths (Flash = .f4m or iOS = .m3u8).

HTTP Dynamic Steaming. Flash Media Playback using Strobe.

http://[domain]/hds-vod/[filename][extension].f4m

HTTP Live Streaming. iOS Media Playback using Safari.

http://[domain]/hls-vod/[filename][extension].m3u8

Managing Formats, File Types and Codecs

The number of file formats, file types and codecs available today is daunting. For example, there's MP3, MP4, F4M, 3GPP, M4A, OGG, WAV, AC3.

For compressing media, there's H.264, AAC, HE-AAC, MP3.

We don't need to be bogged down by all of this. Since we're doing radio, all we need to worry about is an MP4/M4A filetype with an AAC codec wrapped in an M3U8 or F4M manifest file.

Manifest File Types

  • M3U8 - This is how we will achieve multi-bit streaming on iOS devices.
  • F4M - This is a manifest file created by Adobe that we will use for HTTP Dynamic Streaming.
  • PLS - This is Apple's playlist format.

Media File Formats

  • MP3 - Works on browsers, iOS, and Android.
  • MP4 - Works on all browsers, iOS, and Android.
  • MP4 Audio AAC - Is a subset of MPEG-4 which focuses on Audio only. Other subset names are HE-AAC or ISO/IEC 14496-3. This is probably the best format for Internet audio.

Codecs

  • H.264 is pretty much the winner.

Sources


Managing Scale Through CloudFront

Since we're using AWS, we can use CloudFront to handle scale. Easy.

Start at 30:45. Source


Client Side Development

Connecting your App

Connect to a media file through Adobe's HTTP Dynamic Streaming. Take notice that you have to include f4m which is Adobe's manifest file.

http://[domain]/hds-vod/audio/000.m4a.f4m

Connect to a media file through Apple's HTTP Live Streaming.

http://[domain]/hls-vod/audio/000.m4a.f4m

Source: Streaming On-Demand Media Documentation


DevOps

Step 1 - Create an AMS host

The quickest, easiest, fastest way to create an Adobe Media Server is purchasing this pre-packaged EC2 instance from Orbitera.

I use Ruby Rake to connect to my AMS on EC2 instance. Here are a few basic commands:

Create a Rakefile and paste this Ruby code.

APP_ROOT = File.dirname(__FILE__)

namespace :aws do
  desc %Q{ SSH to Adobe Media Server offered by Orbital }
  task :ams, [:pem, :ip] do |task, args|
    pem       = args.pem || pem_path
    user      = user('amsadmin')
    ip_or_url = args.ip || "ec2-00-000-000-000.compute-1.amazonaws.com"
    sh %{ ssh -i #{pem} #{user}@#{ip_or_url} }
  end

  desc %Q{ – SSH to Adobe Media Server on EC2 }
  task :centos, [:pem, :ip] do |task, args|
    pem       = args.pem || pem_path
    user      = user('centos')
    ip_or_url = args.ip || "ec2-00-000-000-000.compute-1.amazonaws.com"
    sh %{ ssh -i #{pem} #{user}@#{ip_or_url} }
  end
  
  desc %Q{ SSH to an Adobe Media Server installed on a CentOS EC2 instance. }
  task :upload, [:pem, :ip, :source_dir] do |task, args|
    assets_dir = args.source_dir || "/path/to/files/you/want/to/upload/*"
    pem        = args.pem || pem_path
    user       = user('amsadmin')
    ip_or_url  = args.ip || "sub.domain.org"
    aws_dir    = "/opt/adobe/ams/webroot/vod/music/"
    sh %{ scp -i #{pem} #{assets_dir} #{user}@#{ip_or_url}:#{aws_dir} }
  end
  
  desc %Q{ – Get External IP }
  task :external_ip do
    sh %{ curl -s http://checkip.dyndns.org/ | sed 's/[a-zA-Z<>/ :]//g' }
  end 
end

private 

def user(os)
  user = case os
  when "ubuntu" then "ubuntu"
  when "ams"    then "amsadmin"
  when "fms"    then "fmsadmin"
  when "ami"    then "ec2-user"
  when "debian" then "admin"
  when "redhat" then "ec2-user"
  when "fedora" then "fedora"
  when "centos" then "centos"
  when "bitnami" then "bitnami"
  when "freebsd" then "ec2-user"
  else "ec2-user"
  end
  return user
end

def pem_path
  File.join(ENV['HOME'], "Users", "MyUser", "Desktop", "mypem.pem")
end

SSH into AMS:

rake ams:ssh[path_to_pem.pem,ip_address]

Upload a file to AMS:

rake ams:upload[path_to_pem.pem,ip_address]

Resources