Recently Microsoft released Windows Azure Media Services preview, which essentially is a Platform as a Service that empowers developers to build workflows for the creation, management, and distribution of media.
This post is a retrospective of my first experience with this new service.
Getting Started
Getting to know the services I started to look for a video I could use for my test, so I grabbed the first Canon 7D I could find and headed out to make a short video. Canon records videos as MOV files of considerable size and quality so I thought this was the perfect candidate to test the format conversion and Smooth Streaming.
Once I got my video imported on my PC I rapidly started to get setup. Using the following instructions. I downloaded and installed the following packaged.
Windows Azure SDK 1.6 (November 2011)
Windows Azure SDK 1.7 (June 2012)
Windows Azure SDK on Windows 8
Windows Azure Media Services SDK for .NET
WCF Data Services 5.0 for OData v3
Then I created a project and referenced the following DLLs
Microsoft.Data.Edm.dll
Microsoft.Data.OData.dll
Microsoft.Data.Services.Client.dll
Microsoft.Data.Services.dll
System.Spatial.dll
Microsoft.WindowsAzure.StorageClient.dll
Microsoft.WindowsAzure.MediaServices.Client.dll
If you are using Visual Studio 2012 be sure to set the Target Framework setting to .NET Framework 4.
Ingesting Media
Looking at examples of the services’ API I pieced together this ModelCommand which allowed me to upload my MOV file by creating a new Unencrypted Asset.
public class CreateAssetModelCommand : IModelCommand<CloudMediaContext> { private readonly string[] files; private readonly string primaryFile; private readonly CancellationTokenSource cancellationToken; Task<IAsset> task; public CreateAssetModelCommand(string[] files, string primaryFile) { this.files = files; this.primaryFile = primaryFile; cancellationToken = new CancellationTokenSource(); } public void Apply(CloudMediaContext model) { task = model.Assets.CreateAsync(files, primaryFile, AssetCreationOptions.None, cancellationToken.Token); task.ContinueWith(asset => { var cmd = new CreateJobModelCommand(asset.Result); cmd.Apply(model); }); } public void Cancel() { cancellationToken.Cancel(false); } }
This ModelCommand will allow us to create an Asset. An asset contains files that make up the media content. After creating and uploading an Asset I noticed that the Asset –> Files structure strongly resembled the
Blob Storage Container –> Blob structure.
Further investigation confirmed my intuition, the assets are stored in the storage account which I provided when I configured the Media Services instance. Using tools like visual studio I was able to browse my assets located in the storage account.
The dashboard found in the Management Portal shows storage consumption and other useful information.
Executing the above ModelCommand will result in creating the Asset and uploading the files to the storage account. I specified that I did not want the Asset to be encrypted and provided a cancelation token. Large files will be chunked and uploaded as blobk blobs. This will be done automatically by the CloudStorageClient used by the CloudMediaContext.
Once the upload is complete, the ModelCommand creates a new ModelCommand which will build and start a Job to convert and encode the Asset to Smooth Streaming for consumption by SilverLight.
Encoding & Format Conversion
I then set out to convert my MOV file to MP4 using the Windows Azure Media Encoder. This encoder lets you run encoding tasks using the Media Encoder. My plan was to then use the MP4 to Smooth Streams Task to convert my media assets from .mp4 to the smooth streaming format.
I rapidly hit a wall when I found out that MOV was not a supported format by the Windows Azure Media Encoder. So I set out to find out what formats were supported.
Media Encoder Import Formats
Video Codecs
|
Audio Codecs
|
File Format | File Extensions |
---|---|
3GPP, 3GPP2 |
.3gp, .3g2, .3gp2 |
Advanced Systems Format (ASF) |
.asf |
Advanced Video Coding High Definition (AVCHD) [MPEG-2 Transport Stream] |
.mts, .m2ts |
Audio-Video Interleaved (AVI) |
.avi |
AviSynth |
.avs |
Digital camcorder MPEG-2 (MOD) |
.mod |
Digital video (DV) camera file |
.dv |
DVD transport stream (TS) file |
.ts |
DVD video object (VOB) file |
.vob |
Expression Encoder Screen Capture Codec file |
.xesc |
MP4 |
.mp4 |
MPEG-1 System Stream |
.mpeg, .mpg |
MPEG-2 video file |
.m2v |
Smooth Streaming File Format (PIFF 1.3) |
.ismv |
Windows Media Video (WMV) |
.wmv |
File Format | File Extensions |
---|---|
AC-3 (Dolby Digital) audio |
.ac3 |
Audio Interchange File Format (AIFF) |
.aiff |
Broadcast Wave Format |
.bwf |
MP3 (MPEG-1 Audio Layer 3) |
.mp3 |
MP4 audio |
.m4A |
MPEG-4 audio book |
.m4b |
WAVE file |
.wav |
Windows Media Audio |
.wma |
File Format | File Extensions |
---|---|
Bitmap |
.bmp |
GIF, Animated GIF |
.gif |
JPEG |
.jpeg, .jpg |
PNG |
.png |
TIFF |
.tif |
WPF Canvas XAML |
.xaml |
File Format | Video Codec | Audio Codec |
---|---|---|
Windows Media (*.asf; *.wmv; *.wma) |
VC-1 (Advanced, Main, and Simple Profiles) |
WMA Standard, WMA Professional, WMA Voice, WMA Lossless |
MP4 (*.mp4) |
H.264 (High, Main, and Baseline Profiles) |
AAC-LC, HE-AAC v1, HE-AAC v2 |
Smooth Streaming File Format (PIFF 1.3) (*.ismv; *.isma) |
VC-1 (Advanced Profile) H.264 (High, Main, and Baseline Profiles) |
WMA Standard, WMA Professional AAC-LC, HE-AAC v1, HE-AAC v2 |
Once I found this information, I started to hunt for a conversion application that would allow me to go from MOV to MP4 and proceeded to the conversion on my local machine. I deleted the previously created Asset and created a new one with my MP4 video.
The following code will find all locators for an Asset and it will revoke them. Trying to delete an Asset without revoking the locators will result in errors.
try { var ls = context .Locators .Where(l => l.AssetId == SelectedAsset.Id) .Select(l => l) .ToList(); ls.ForEach(l=> context.Locators.Revoke(l)); context.Assets.Delete(SelectedAsset); } catch(Exception e) { Debug.WriteLine(e.ToString()); }
The following ModelCommand is instantiated and Applied once the Asset files have been uploaded. The ModelCommand creates and starts a job that converts the MP4 to Smooth Streaming using the MP4 to Smooth Streams Task from the Media Processors made available by the Media Services.
Jobs are submitted to the Media Services and the processing is deferred to Windows Azure.
public class CreateJobModelCommand : IModelCommand<CloudMediaContext> { private readonly IAsset asset; IJob job; public CreateJobModelCommand(IAsset asset) { this.asset = asset; } public void Apply(CloudMediaContext model) { job = model.Jobs.Create("Encoding Job"); // Get a media processor reference, and pass to it the name of the // processor to use for the specific task. Use a method like the // GetMediaProcessor method shown in this document. var processor = GetMediaProcessor("MP4 to Smooth Streams Task", model); // Create a task with the encoding details, using a configuration file. ITask task = job.Tasks.AddNew("Mp4 to Smooth Task", processor, Resources.MP4_to_Smooth_Streams, TaskCreationOptions.ProtectedConfiguration); // Specify the input asset to be encoded. task.InputMediaAssets.Add(asset); // Add an output asset to contain the results of the job. task.OutputMediaAssets.AddNew("Output " + asset.Name, true, AssetCreationOptions.None); // Launch the job. job.Submit(); } private IMediaProcessor GetMediaProcessor(string mediaProcessor, CloudMediaContext model) { // Query for a media processor to get a reference. var theProcessor = from p in model.MediaProcessors where p.Name == mediaProcessor select p; // Cast the reference to an IMediaprocessor. IMediaProcessor processor = theProcessor.First(); if (processor == null) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Unknown processor", mediaProcessor)); } return processor; } }
The above code uses the task presets found below for the MP4 to Smooth Streaming conversion.
Jobs are used to specify and configure Tasks to be executed over Assets. The task presets for each Media Processor can be found below.
Windows Azure Media Encoder – Lets you run encoding tasks using the Media Encoder.
– Task Preset Strings for Windows Azure Media Encoder
– Task Preset for Thumbnail Generation
PlayReady Protection Task – Lets you encrypt media assets using PlayReady Protection.
– Task Preset for Playready Protection
MP4 to Smooth Streams Task – Lets you convert media assets from .mp4 to smooth streaming format.
– Task Preset for MP4 to Smooth Streams Conversion
Smooth Streams to HLS Task – Lets you convert media assets from smooth streaming to the Apple HTTP Live Streaming (HLS) format.
– Task Preset for Smooth Streams to Apple HLS Conversion
Storage Decryption – Lets you decrypt media assets that were encrypted using storage encryption.
Content Protection
Since I did not have any requirements I did not explore this aspect of the workflow. This will be for a future blog post.
On-Demand Streaming
The following ModelQuery requests a Shared Access allowing the consumer to temporarily access files from the asset for 1 day. The resulting URI is used in a media player that can consume Smooth Streaming.
public class GetAssetStreamingUrl : IModelQuery<CloudMediaContext, string> { private readonly IAsset selectedAsset; public GetAssetStreamingUrl(IAsset selectedAsset) { this.selectedAsset = selectedAsset; } public string Execute(CloudMediaContext model) { // Get a reference to the manifest file from the collection // of streaming files in the asset. var theManifest = from f in selectedAsset.Files where f.Name.EndsWith(".ism") select f; // Cast the reference to a true IFileInfo type. var manifestFile = theManifest.FirstOrDefault(); if (manifestFile != null) { // Create an 1-day readonly access policy. var streamingPolicy = model .AccessPolicies .Create("Streaming policy", TimeSpan.FromDays(1), AccessPermissions.Read); // Create the origin locator. Set the start time as 5 minutes // before the present so that the locator can be // accessed immediately // if there is clock skew between the client and server. var originLocator = model .Locators .CreateOriginLocator(selectedAsset, streamingPolicy, DateTime.UtcNow.AddMinutes(-5)); // Create a full URL to the manifest file. Use this for playback // in streaming media clients. string urlForClientStreaming = originLocator.Path + manifestFile.Name + "/manifest"; return urlForClientStreaming; } return string.Empty; } }
Wrapping it up
After playing around with the services for a while, I truly see a huge potential and tons of possibilities! The Windows Azure Media Services give you control over your media asset distribution workflow. Empowering you to provide scalable and reliable media streaming sources for your customers.
I can’t wait for these services to be released.