Chris Mendez in Radio, For Developers, AWS

Cloud-Based Radio Using Adobe Media Server

Yes, I understand that Adobe Flash-type products are dead but Adobe Media Server is really powerful. The only problem with the product is that Adobe was terrible at explaining it, selling it, promoting it and documenting it.

That said, Adobe Media Server is still a decent product, and my goal is to help you sort through the noise to create a cloud-based radio station.

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.

The Solution

Adobe Media Server offers one type of service that's worthwhile. It's called
HTTP Live Streaming (HLS) which enables you to deliver just-in-time on-demand, adaptive bitrate audio using MP4 over HTTP connections.

HLS is Apple's 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.

Building Your Media Server Stack

Here's the media stack we will be using:

  • Amazon EC2 for server instances.
  • Adobe Media Server for media hosting and HTTP Live Streaming (iOS).
  • AWS S3 for storing media files.
  • AWS VPC for virtual private cloud.
  • AWS Load Balancer for Load Balancing.
  • AWS Cloudfront for worldwide endpoints and caching.

Installing the Adobe Media Server

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:

Managing Firewalls

On AWS EC2, you manage Firewalls through Security Groups. In order to get Adobe Media Server working, you will need to make sure your firewall is open on both your EC2 instance and local office.

Host Firewall

You manage PORTS on EC2 using Security Groups. When you create your security group, make sure you provide access to:

  • SSH => Port 22
  • HTTP => Port 80
  • Adobe Media Server Admin Console => 1111
  • Real Time Media Protocol (RTMP) => 1935

Client Firewall

If you work in an office, you might need to double check that you can access content on Port 1935. This Flash Port Tester can help you accomplish that.

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

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).

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.


  • H.264 is pretty much the winner.


Managing Scale Through CloudFront

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

Client Side Development

Connecting your App

  • Connect to a media file through HTTP Dynamic Streaming
  • Connect to a media file through HTTP Live Streaming


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.

namespace :aws do
  desc %Q{ – SSH to Adobe Media Server on EC2 }
  task :ssh, [:pem, :ip] do |task, args|
    aws_pem       = args.pem || "/path/to/aws/keypair/awspem.pem"
    aws_user      = "amsadmin"
    aws_ip_or_url = args.ip || ""
    sh %{ ssh -i #{aws_pem} #{aws_user}@#{aws_ip_or_url} }
  desc %Q{ – Upload files using SCP }
  task :upload, [:pem, :ip] do |task, args|
    assets_dir    = "/path/to/files/you/want/to/upload/*"

    aws_pem       = args.pem || "/path/to/aws/keypair/awspem.pem"
    # This particular package uses amsadmin
    aws_user      = "amsadmin"
    aws_ip_or_url = args.ip || ""
    aws_dir       = "/mnt/webroot/vod/audio"
    sh %{ scp -i #{aws_pem} #{assets_dir} #{aws_user}@#{aws_ip_or_url}:#{aws_dir} }
  desc %Q{ – Get External IP }
   task :external_ip do
     sh %{ curl -s | sed 's/[a-zA-Z<>/ :]//g' }

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]