SALES: 1-800-867-1380

Quickstart: Using the Media Services .NET SDK

Updated: August 8, 2014

This topic is a walkthrough for new developers on Microsoft Azure Media Services. It introduces the basic Media Services workflow and the most common programming objects and tasks required for Media Services development. To get a basic understanding of the Media Services development process and the programming object model, see Azure Media Services Overview.

A C# Visual Studio project that contains the code for this tutorial is available here: Download

This walkthrough demonstrates how to:

TipTip
You also have a choice of using the Azure Media Services .NET SDK Extensions to accomplish the tasks described in this topic. The Media Services .NET SDK Extensions is a set of extension methods and helper functions that will simplify your code and make it easier to develop with Media Services. For more information, see Quickstart: Using the Media Services .NET SDK Extensions.

The following prerequisites are required for the walkthrough and for development based on the Microsoft Azure Media Services SDK.

  • A Media Services account in a new or existing Azure subscription. See the topic How to Create a Media Services Account.

  • Operating Systems: Windows 7, Windows 2008 R2, or Windows 8.

  • .NET Framework 4.

  • Visual Studio 2013, Visual Studio 2012, or Visual Studio 2010 SP1 (Professional, Premium, Ultimate, or Express).

  1. Create a new C# Console Application in Visual Studio 2013, Visual Studio 2012, or Visual Studio 2010 SP1. Enter the Name, Location, and Solution name, and then click OK.

  2. Add references to Media Services and its dependent DLLs.

    The Media Services SDK has dependency on multiple libraries (for example, Azure Storage SDK for .NET and WCF Data Services for OData). You can use windowsazure.mediaservices nuget to install and add the Media Services SDK to your project, in which case all the dependencies get installed and added to your project automatically.

    Alternatively, you can get the latest Media Services SDK bits from GitHub, build the solution, and add the references to the client project. Note that all the necessary dependencies get downloaded and extracted automatically.

    In either method, you do not need to download dependencies manually.

    To add required references using windowsazure.mediaservices NuGet package, do the following:

    1. Ensure that you have the newest version of NuGet installed.

      For more information and installation instructions, see NuGet.

    2. In Solution Explorer, right-click the name of the project and choose Manage NuGet packages ….

      The Manage NuGet Packages dialog box appears.

    3. In the Online gallery, search for MediaServices, choose Azure Media Services .NET SDK, and then click the Install button.

      The project is modified and references to Media Services assemblies are added.

    4. To promote a cleaner developer environment, consider enabling NuGet Package Restore. For more information, see NuGet Package Restore.

  3. Add a reference to the System.Configuration .NET assembly.

    To add references using the Manage References dialog, do the following:

    1. In Solution Explorer, right-click the project name. Then, select Add and References.

      The Manage References dialog appears.

    2. Under .NET framework assemblies, find and select the System.Configuration assembly.

    3. Press OK.

  4. Add the appSettings section to the app.config file, and set the values for your Media Services account name and account key. You obtained the Media Services account name and account key during the account setup process.

    noteNote
    In Visual Studio 2013 and Visual Studio 2012, the App.config file is added by default. In Visual Studio 2010, you have to manually add the Application Configuration file.

    TipTip
    To find the Name and Key values, go to the Azure Portal, select your Media Service account, and click on the “MANAGE KEYS” icon on the bottom of the portal window. Clicking on the icon next to each text box copies the value to the system clipboard.

    <?xml version="1.0"?>
    <configuration>
      <appSettings>
          <add key="MediaServicesAccountName" value="YouMediaServicesAccountName" />
          <add key="MediaServicesAccountKey" value="YouMediaServicesAccountKey" />
      </appSettings>
    </configuration>
    
  5. Create a folder on your local machine and copy a .wmv and an .mp4 files into this folder. In this example, it is assumed that the name of the folder is Media and it is located under the MediaServicesGettingStarted project directory. The Project that accompanies this walkthrough contains the Media directory with a .wmv and .mp4 files.

  6. Overwrite the existing using statements at the beginning of the Program.cs file with the following code.

    using System;
    using System.Linq;
    using System.Configuration;
    using System.IO;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.MediaServices.Client;
    

To connect to Media Services programmatically, you must have previously set up an Azure account and configured Media Services on that account. The following topic gives details about how to connect to Media Services account: Connecting to Media Services with the Media Services SDK for .NET.

The following code demonstrates how to read the connection values from the App.config file and how to create the CloudMediaContext object in order to connect to Media Services.

  1. Replace the default Program class definition with the following code.

    class Program
    {
        // Read values from the App.config file.
        private static readonly string _mediaServicesAccountName = 
            ConfigurationManager.AppSettings["MediaServicesAccountName"];
        private static readonly string _mediaServicesAccountKey =
            ConfigurationManager.AppSettings["MediaServicesAccountKey"];
    
        // Field for service context.
        private static CloudMediaContext _context = null;
        private static MediaServicesCredentials _cachedCredentials = null;
    
        static void Main(string[] args)
        {
            // Create and cache the Media Services credentials in a static class variable.
            _cachedCredentials = new MediaServicesCredentials(
                            _mediaServicesAccountName,
                            _mediaServicesAccountKey);
            // Used the chached credentials to create CloudMediaContext.
            _context = new CloudMediaContext(_cachedCredentials);
           . . .
        }
    }
    
    
    

The code in this section does the following:

  1. Creates an empty Asset

    When you create assets, you can specify three different options for encrypting them.

    • AssetCreationOptions.None. If you want to create an unencrypted asset, you must set this option.

    • AssetCreationOptions.CommonEncryptionProtected. Specify this option if you have Common Encryption Protected (CENC) files. An example is a set of files that are encrypted with PlayReady.

    • AssetCreationOptions.StorageEncrypted. Encrypts a clear input file before it is uploaded to Azure storage.

      noteNote
      Note that Media Services provide on-disk storage encryption, not over the wire like Digital Rights Manager (DRM.)

  2. Creates an AssetFile instance that we want to upload to storage and associate with the asset.

  3. Creates an AccessPolicy instance that defines the permissions and duration of access to the asset.

  4. Creates a SAS Locator instance that provides access to the asset.

  5. Uploads a single media file into Media Services. The process of creating and uploading is also called ingesting assets.

static public IAsset CreateAssetAndUploadSingleFile(AssetCreationOptions assetCreationOptions, string singleFilePath)
{
    var assetName = "UploadSingleFile_" + DateTime.UtcNow.ToString();
    var asset = CreateEmptyAsset(assetName, assetCreationOptions);

    var fileName = Path.GetFileName(singleFilePath);

    var assetFile = asset.AssetFiles.Create(fileName);

    Console.WriteLine("Created assetFile {0}", assetFile.Name);

    var accessPolicy = _context.AccessPolicies.Create(assetName, TimeSpan.FromDays(30),
                                                        AccessPermissions.Write | AccessPermissions.List);

    var locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);

    Console.WriteLine("Upload {0}", assetFile.Name);

    assetFile.Upload(singleFilePath);
    Console.WriteLine("Done uploading {0}", assetFile.Name);

    locator.Delete();
    accessPolicy.Delete();

    return asset;
}

static private IAsset CreateEmptyAsset(string assetName, AssetCreationOptions assetCreationOptions)
{
    var asset = _context.Assets.Create(assetName, assetCreationOptions);

    Console.WriteLine("Asset name: " + asset.Name);
    Console.WriteLine("Time created: " + asset.Created.Date.ToString());

    return asset;
}

In Media Services, you can create jobs that process media content in several ways: encoding, encrypting, doing format conversions, and so on. A Media Services job always contains one or more tasks that specify the details of the processing work. This section defines a method that creates a single encoding task, and then runs a job that performs the task using Azure Media Encoder. The task uses a preset string to specify the type of encoding to perform. To see the available preset encoding values, see Media Services Encoder System Presets. Media Services support the same media file input and output formats as Microsoft Expression Encoder. For a list of supported formats, see Supported File Types for Media Services.

  1. Add the following CreateEncodingJob method definition to your class. This method accomplishes several required steps for an encoding job:

    • Declare a new job.

    • Declare a media processor to handle the job. A media processor is a component that handles encoding, encrypting, format conversion, and other related processing jobs. There are several types of available media processors (you can iterate through all of them using _context.MediaProcessors.) The GetLatestMediaProcessorByName method, shown later in this walkthrough, returns the Azure Media Encoder processor.

    • Declare a new task. Every job has one or more tasks. Notice that with the task, you pass to it a friendly name, a media processor instance, a task configuration string, and task creation options. The configuration string specifies encoding settings. For example, the H264 Broadband 720p setting produces a single MP4 file. For more information about this and other presets, see Media Services Encoder System Presets.

    • Add an input asset to the task. In this example, the input asset is the one you created in the previous section.

    • Add an output asset to the task. For an output asset, specify a friendly name, a Boolean value to indicate whether to save the output on the server after job completion, and an AssetCreationOptions.None value to indicate that the output is not encrypted for storage and transport.

    • Submit the job.

      Submitting a job is the last step that is required to do an encoding job.



    The method performs other useful but optional tasks such as tracking job progress and logging job details.

    static public IAsset CreateEncodingJob(IAsset asset, string preset)
    {
        // Declare a new job.
        IJob job = _context.Jobs.Create(preset + " encoding job");
        // Get a media processor reference, and pass to it the name of the 
        // processor to use for the specific task.
        IMediaProcessor processor = GetLatestMediaProcessorByName("Azure Media Encoder");
    
        // Create a task with the encoding details, using a string preset.
        ITask task = job.Tasks.AddNew(preset + " encoding task",
            processor,
            preset, 
            Microsoft.WindowsAzure.MediaServices.Client.TaskOptions.ProtectedConfiguration);
    
        // Specify the input asset to be encoded.
        task.InputAssets.Add(asset);
        // Add an output asset to contain the results of the job. 
        // This output is specified as AssetCreationOptions.None, which 
        // means the output asset is not encrypted. 
        task.OutputAssets.AddNew("Output asset",
            AssetCreationOptions.None);
    
        // Use the following event handler to check job progress.  
        job.StateChanged += new
                EventHandler<JobStateChangedEventArgs>(StateChanged);
    
        // Launch the job.
        job.Submit();
    
        // Optionally log job details. This displays basic job details
        // to the console and saves them to a JobDetails-{JobId}.txt file 
        // in your output folder.
        LogJobDetails(job.Id);
    
        // Check job execution and wait for job to finish. 
        Task progressJobTask = job.GetExecutionProgressTask(CancellationToken.None);
        progressJobTask.Wait();
    
        // If job state is Error the event handling 
        // method for job progress should log errors.  Here we check 
        // for error state and exit if needed.
        if (job.State == JobState.Error)
        {
            throw new Exception("\nExiting method due to job error.");
        }
    
        return job.OutputMediaAssets[0];
    }
    

To stream a file you need to create an OnDemandOrigin locator. Locators provide an entry point to access the files contained in an asset. Media Services supports two types of locators: OnDemandOrigin locators, used to stream media (for example, MPEG DASH, HLS, or Smooth Streaming) and Access Signature (SAS) URL locators, used to download media files.

To generate the full URL, you create an OnDemandOriginLocator and append the desired streaming format. For example:

 

Smooth Streaming

{media services account name}.origin.mediaservices.net/{locator ID}/{filename}.ism/Manifest

You can use the http://smf.cloudapp.net/healthmonitor player to test your Smooth Streaming.

DASH Live Profile manifest with Common Streaming Format media

{media services account name}.origin.mediaservices.net/{locator ID}/{filename}.ism/Manifest(format=mpd-time-csf) 

You can use the http://dashif.org/reference/players/javascript/ player to test your Smooth Streaming.

Apple HTTP Live Streaming (HLS)

{media services account name}.origin.mediaservices.net/{locator ID}/{filename}.ism/Manifest(format=m3u8-aapl)

The following example shows the Smooth Streaming, HLS, and DASH URLs that are based on the OnDemandOrigin locator path.

http://test001.origin.mediaservices.windows.net/fecebb23-46f6-490d-8b70-203e86b0df58/BigBuckBunny.ism/Manifest
http://test001.origin.mediaservices.windows.net/fecebb23-46f6-490d-8b70-203e86b0df58/BigBuckBunny.ism/Manifest(format=m3u8-aapl)
http://test001.origin.mediaservices.windows.net/fecebb23-46f6-490d-8b70-203e86b0df58/BigBuckBunny.ism/Manifest(format=mpd-time-csf)

For more information, see Delivering Content.

The following method gets the URL to the on-demand origin service plus the manifest file. Once you have this URL, you can build the full streaming URL as described above.

static public string GetStreamingOriginLocatorURL(IAsset assetToStream)
{
    // Get a reference to the streaming manifest file from the  
    // collection of files in the asset. 
    var theManifest =
                        from f in assetToStream.AssetFiles
                        where f.Name.EndsWith(".ism")
                        select f;

    // Cast the reference to a true IAssetFile type. 
    IAssetFile manifestFile = theManifest.First();

    // Create a 30-day readonly access policy. 
    IAccessPolicy policy = _context.AccessPolicies.Create("Streaming policy",
        TimeSpan.FromDays(30),
        AccessPermissions.Read);

    // Create a locator to the streaming content on an origin. 
    ILocator originLocator = _context.Locators.CreateLocator(LocatorType.OnDemandOrigin, 
        assetToStream,
        policy,
        DateTime.UtcNow.AddMinutes(-5));

    // Display the base path to the streaming asset on the origin server.
    Console.WriteLine("Streaming asset base path on origin: ");
    Console.WriteLine(originLocator.Path);
    Console.WriteLine();

    // Create a full URL to the manifest file. 
    return originLocator.Path + manifestFile.Name;
}

To download a file to your machine you first need to create a SAS locator. Locators provide an entry point to access the files contained in an asset. Media Services supports two types of locators: OnDemandOrigin locators, used to stream media (for example, MPEG DASH, HLS, or Smooth Streaming) and Access Signature (SAS) URL locators, used to download media files. To build the URL, you need to embed the file name between the host and SAS signature.

The following example shows the URL that is based on the SAS locator:

https://test001.blob.core.windows.net/asset-ca7a4c3f-9eb5-4fd8-a898-459cb17761bd/BigBuckBunny.mp4?sv=2012-02-12&se=2014-05-03T01%3A23%3A50Z&sr=c&si=7c093e7c-7dab-45b4-beb4-2bfdff764bb5&sig=msEHP90c6JHXEOtTyIWqD7xio91GtVg0UIzjdpFscHk%3D

For more information, see Delivering Content.

The following method downloads files to the specified output location.

static public IAsset DownloadAssetToLocal(IAsset asset, string outputFolder)
{
    IAccessPolicy accessPolicy = _context.AccessPolicies.Create("File Download Policy", TimeSpan.FromDays(30), AccessPermissions.Read);
    ILocator locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);
    BlobTransferClient blobTransfer = new BlobTransferClient
    {
        NumberOfConcurrentTransfers = 10,
        ParallelTransferThreadCount = 10
    };

    Console.WriteLine("Files will be downloaded to:");
    Console.WriteLine("{0}", outputFolder);
    Console.WriteLine();

    var downloadTasks = new List<Task>();
    foreach (IAssetFile outputFile in asset.AssetFiles)
    {
        // Use the following event handler to check download progress.
        outputFile.DownloadProgressChanged += DownloadProgress;

        string localDownloadPath = Path.Combine(outputFolder, outputFile.Name);

        downloadTasks.Add(outputFile.DownloadAsync(Path.GetFullPath(localDownloadPath), blobTransfer, locator, CancellationToken.None));

        outputFile.DownloadProgressChanged -= DownloadProgress;
    }

    Task.WaitAll(downloadTasks.ToArray());

    return asset;
}

static private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
    Console.WriteLine(string.Format("{0} % download progress. ", e.Progress));
}

This section contains the full listing of the code described in this topic.

noteNote
  • Make sure to update the following variables to point to the folders where your input (MP4 and WMV) files are located and where you want for the output to go.

    private static readonly string _supportFiles =
        Path.GetFullPath(@"../..\Media");
    
    // Paths to support files (within the above base path). You can use 
    // the provided sample media files from the "supportFiles" folder, or 
    // provide paths to your own media files below to run these samples.
    private static readonly string _singleWMVInputFilePath =
        Path.GetFullPath(_supportFiles + @"\interview1.wmv");
    
    private static readonly string _singleMP4InputFilePath =
        Path.GetFullPath(_supportFiles + @"\BigBuckBunny.mp4");
    
    private static readonly string _outputFilesFolder =
        Path.GetFullPath(_supportFiles + @"\OutputFiles");
    

using System;
using System.Linq;
using System.Configuration;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.MediaServices.Client;
 
namespace MediaServicesGettingStarted
    {
    class Program
    {
        private static readonly string _supportFiles =
            Path.GetFullPath(@"../..\Media");

        // Paths to support files (within the above base path). You can use 
        // the provided sample media files from the "supportFiles" folder, or 
        // provide paths to your own media files below to run these samples.
        private static readonly string _singleWMVInputFilePath =
            Path.GetFullPath(_supportFiles + @"\interview1.wmv");

        private static readonly string _singleMP4InputFilePath =
            Path.GetFullPath(_supportFiles + @"\BigBuckBunny.mp4");

        private static readonly string _outputFilesFolder =
            Path.GetFullPath(_supportFiles + @"\OutputFiles");
        // Read values from the App.config file.
        private static readonly string _mediaServicesAccountName = 
            ConfigurationManager.AppSettings["MediaServicesAccountName"];
        private static readonly string _mediaServicesAccountKey =
            ConfigurationManager.AppSettings["MediaServicesAccountKey"];

        // Field for service context.
        private static CloudMediaContext _context = null;
        private static MediaServicesCredentials _cachedCredentials = null;

        static void Main(string[] args)
        {
            // Create and cache the Media Services credentials in a static class variable.
            _cachedCredentials = new MediaServicesCredentials(
                            _mediaServicesAccountName,
                            _mediaServicesAccountKey);
            // Used the chached credentials to create CloudMediaContext.
            _context = new CloudMediaContext(_cachedCredentials);

            IAsset singleWMVAsset = CreateAssetAndUploadSingleFile(AssetCreationOptions.None, 
                _singleWMVInputFilePath);

            // EncodeToH264 creates a job with one task
            // that converts a mezzanine file (in this case interview1.wmv)
            // into an MP4 file (in this case, "H264 Broadband 720p").
            IAsset MP4Asset = CreateEncodingJob(singleWMVAsset, "H264 Broadband 720p");

            // BuildSasUrlForMP4File creates a SAS Locator
            // and builds the SAS Url that can be used to 
            // progressively download the MP4 file.
            string fullSASURL = BuildSasUrlForMP4File(MP4Asset);

            Console.WriteLine("Progressive download URL: {0}", fullSASURL);

            // Download all the files in the asset locally
            // (that includes the mainifest.xml file).
            DownloadAssetToLocal(MP4Asset, _outputFilesFolder);

            Console.WriteLine();

            IAsset singleMP4Asset = CreateAssetAndUploadSingleFile(AssetCreationOptions.None,
                                                     _singleMP4InputFilePath);
            // EncodeToAdaptiveBitrate creates a job with one task
            // that encodes a mezzanine file (in this case BigBuckBunny.mp4)
            // into an adaptive bitrate MP4 set (in this case, "H264 Adaptive Bitrate MP4 Set 720p").
            IAsset adaptiveBitrateAsset = CreateEncodingJob(singleMP4Asset, "H264 Adaptive Bitrate MP4 Set 720p");

            // Get the Streaming Origin Locator URL.
            string streamingURL = GetStreamingOriginLocatorURL(adaptiveBitrateAsset);

            // Add Smooth Streaming, HLS, and DASH format to the streaming URL.  
            // NOTE: To be able to play these streams based on the 
            // adaptiveBitrateAsset asset, you MUST have at least one
            // On-demand Streaming reserved unit. 
            // For more information, see: 
            //    Dynamic Packaging (http://msdn.microsoft.com/en-us/library/azure/jj889436.aspx)
            Console.WriteLine("Smooth Streaming format:");
            Console.WriteLine("{0}", streamingURL + "/Manifest");
            Console.WriteLine("Apple HLS format:");
            Console.WriteLine("{0}", streamingURL + "/Manifest(format=m3u8-aapl)");
            Console.WriteLine("MPEG DASH format:");
            Console.WriteLine("{0}", streamingURL + "/Manifest(format=mpd-time-csf)"); 

        }

        static public IAsset CreateAssetAndUploadSingleFile(AssetCreationOptions assetCreationOptions, string singleFilePath)
        {
            var assetName = "UploadSingleFile_" + DateTime.UtcNow.ToString();
            var asset = CreateEmptyAsset(assetName, assetCreationOptions);

            var fileName = Path.GetFileName(singleFilePath);

            var assetFile = asset.AssetFiles.Create(fileName);

            Console.WriteLine("Created assetFile {0}", assetFile.Name);

            var accessPolicy = _context.AccessPolicies.Create(assetName, TimeSpan.FromDays(30),
                                                                AccessPermissions.Write | AccessPermissions.List);

            var locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);

            Console.WriteLine("Upload {0}", assetFile.Name);

            assetFile.Upload(singleFilePath);
            Console.WriteLine("Done uploading {0}", assetFile.Name);

            locator.Delete();
            accessPolicy.Delete();

            return asset;
        }

        static private IAsset CreateEmptyAsset(string assetName, AssetCreationOptions assetCreationOptions)
        {
            var asset = _context.Assets.Create(assetName, assetCreationOptions);

            Console.WriteLine("Asset name: " + asset.Name);
            Console.WriteLine("Time created: " + asset.Created.Date.ToString());

            return asset;
        }

        static public IAsset CreateEncodingJob(IAsset asset, string preset)
        {
            // Declare a new job.
            IJob job = _context.Jobs.Create(preset + " encoding job");
            // Get a media processor reference, and pass to it the name of the 
            // processor to use for the specific task.
            IMediaProcessor processor = GetLatestMediaProcessorByName("Azure Media Encoder");

            // Create a task with the encoding details, using a string preset.
            ITask task = job.Tasks.AddNew(preset + " encoding task",
                processor,
                preset, 
                Microsoft.WindowsAzure.MediaServices.Client.TaskOptions.ProtectedConfiguration);

            // Specify the input asset to be encoded.
            task.InputAssets.Add(asset);
            // Add an output asset to contain the results of the job. 
            // This output is specified as AssetCreationOptions.None, which 
            // means the output asset is not encrypted. 
            task.OutputAssets.AddNew("Output asset",
                AssetCreationOptions.None);

            // Use the following event handler to check job progress.  
            job.StateChanged += new
                    EventHandler<JobStateChangedEventArgs>(StateChanged);

            // Launch the job.
            job.Submit();

            // Optionally log job details. This displays basic job details
            // to the console and saves them to a JobDetails-{JobId}.txt file 
            // in your output folder.
            LogJobDetails(job.Id);

            // Check job execution and wait for job to finish. 
            Task progressJobTask = job.GetExecutionProgressTask(CancellationToken.None);
            progressJobTask.Wait();

            // If job state is Error the event handling 
            // method for job progress should log errors.  Here we check 
            // for error state and exit if needed.
            if (job.State == JobState.Error)
            {
                throw new Exception("\nExiting method due to job error.");
            }

            return job.OutputMediaAssets[0];
        }
    
        static public string GetStreamingOriginLocatorURL(IAsset assetToStream)
        {
            // Get a reference to the streaming manifest file from the  
            // collection of files in the asset. 
            var theManifest =
                                from f in assetToStream.AssetFiles
                                where f.Name.EndsWith(".ism")
                                select f;

            // Cast the reference to a true IAssetFile type. 
            IAssetFile manifestFile = theManifest.First();

            // Create a 30-day readonly access policy. 
            IAccessPolicy policy = _context.AccessPolicies.Create("Streaming policy",
                TimeSpan.FromDays(30),
                AccessPermissions.Read);

            // Create a locator to the streaming content on an origin. 
            ILocator originLocator = _context.Locators.CreateLocator(LocatorType.OnDemandOrigin, 
                assetToStream,
                policy,
                DateTime.UtcNow.AddMinutes(-5));

            // Display the base path to the streaming asset on the origin server.
            Console.WriteLine("Streaming asset base path on origin: ");
            Console.WriteLine(originLocator.Path);
            Console.WriteLine();

            // Create a full URL to the manifest file. Use this for playback
            // in smooth streaming and HLS media clients. 
            return originLocator.Path + manifestFile.Name;
        }

        static public string BuildSasUrlForMP4File(IAsset asset)
        {
            // Declare an access policy for permissions on the asset. 
            // You can call an async or sync create method. 
            IAccessPolicy policy =
                _context.AccessPolicies.Create("My 30 days readonly policy",
                    TimeSpan.FromDays(30),
                    AccessPermissions.Read);

            // Create a SAS locator to enable direct access to the asset 
            // in blob storage. You can call a sync or async create method.  
            // You can set the optional startTime param as 5 minutes 
            // earlier than Now to compensate for differences in time  
            // between the client and server clocks. 

            ILocator locator = _context.Locators.CreateLocator(LocatorType.Sas,
                asset,
                policy,
                DateTime.UtcNow.AddMinutes(-5));

            var mp4File = asset.AssetFiles.ToList().
                           Where(f => f.Name.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase)).
                           FirstOrDefault();


            // Take the locator path, add the file name, and build 
            // a full SAS URL to access this file. This is the only 
            // code required to build the full URL.
            var uriBuilder = new UriBuilder(locator.Path);
            uriBuilder.Path += "/" + mp4File.Name;

            Console.WriteLine("Full URL to file: ");
            Console.WriteLine(uriBuilder.Uri.AbsoluteUri);
            Console.WriteLine();

            //Return the SAS URL.
            return uriBuilder.Uri.AbsoluteUri;
        }

        static public IAsset DownloadAssetToLocal(IAsset asset, string outputFolder)
        {
            IAccessPolicy accessPolicy = _context.AccessPolicies.Create("File Download Policy", TimeSpan.FromDays(30), AccessPermissions.Read);
            ILocator locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);
            BlobTransferClient blobTransfer = new BlobTransferClient
            {
                NumberOfConcurrentTransfers = 10,
                ParallelTransferThreadCount = 10
            };

            Console.WriteLine("Files will be downloaded to:");
            Console.WriteLine("{0}", outputFolder);
            Console.WriteLine();

            var downloadTasks = new List<Task>();
            foreach (IAssetFile outputFile in asset.AssetFiles)
            {
                // Use the following event handler to check download progress.
                outputFile.DownloadProgressChanged += DownloadProgress;

                string localDownloadPath = Path.Combine(outputFolder, outputFile.Name);

                downloadTasks.Add(outputFile.DownloadAsync(Path.GetFullPath(localDownloadPath), blobTransfer, locator, CancellationToken.None));

                outputFile.DownloadProgressChanged -= DownloadProgress;
            }

            Task.WaitAll(downloadTasks.ToArray());

            return asset;
        }

        static private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
        {
            Console.WriteLine(string.Format("{0} % download progress. ", e.Progress));
        }


        static private IMediaProcessor GetLatestMediaProcessorByName(string mediaProcessorName)
        {
            // The possible strings that can be passed into the 
            // method for the mediaProcessor parameter:
            //   Azure Media Encoder
            //   Azure Media Packager
            //   Azure Media Encryptor
            //   Storage Decryption

            var processor = _context.MediaProcessors.Where(p => p.Name == mediaProcessorName).
                ToList().OrderBy(p => new Version(p.Version)).LastOrDefault();

            if (processor == null)
                throw new ArgumentException(string.Format("Unknown media processor", mediaProcessorName));

            return processor;
        }

        static private void StateChanged(object sender, JobStateChangedEventArgs e)
        {
            Console.WriteLine("Job state changed event:");
            Console.WriteLine("  Previous state: " + e.PreviousState);
            Console.WriteLine("  Current state: " + e.CurrentState);

            switch (e.CurrentState)
            {
                case JobState.Finished:
                    Console.WriteLine();
                    Console.WriteLine("********************");
                    Console.WriteLine("Job is finished.");
                    Console.WriteLine("Please wait while local tasks or downloads complete...");
                    Console.WriteLine("********************");
                    Console.WriteLine();
                    Console.WriteLine();
                    break;
                case JobState.Canceling:
                case JobState.Queued:
                case JobState.Scheduled:
                case JobState.Processing:
                    Console.WriteLine("Please wait...\n");
                    break;
                case JobState.Canceled:
                case JobState.Error:
                    // Cast sender as a job.
                    IJob job = (IJob)sender;
                    // Display or log error details as needed.
                    LogJobStop(job.Id);
                    break;
                default:
                    break;
            }
        }

        static private void LogJobStop(string jobId)
        {
            StringBuilder builder = new StringBuilder();
            IJob job = GetJob(jobId);

            builder.AppendLine("\nThe job stopped due to cancellation or an error.");
            builder.AppendLine("***************************");
            builder.AppendLine("Job ID: " + job.Id);
            builder.AppendLine("Job Name: " + job.Name);
            builder.AppendLine("Job State: " + job.State.ToString());
            builder.AppendLine("Job started (server UTC time): " + job.StartTime.ToString());
            builder.AppendLine("Media Services account name: " + _mediaServicesAccountName);
            // Log job errors if they exist.  
            if (job.State == JobState.Error)
            {
                builder.Append("Error Details: \n");
                foreach (ITask task in job.Tasks)
                {
                    foreach (ErrorDetail detail in task.ErrorDetails)
                    {
                        builder.AppendLine("  Task Id: " + task.Id);
                        builder.AppendLine("    Error Code: " + detail.Code);
                        builder.AppendLine("    Error Message: " + detail.Message + "\n");
                    }
                }
            }
            builder.AppendLine("***************************\n");
            // Write the output to a local file and to the console. The template 
            // for an error output file is:  JobStop-{JobId}.txt
            string outputFile = _outputFilesFolder + @"\JobStop-" + JobIdAsFileName(job.Id) + ".txt";
            WriteToFile(outputFile, builder.ToString());
            Console.Write(builder.ToString());
        }

        static private void LogJobDetails(string jobId)
        {
            StringBuilder builder = new StringBuilder();
            IJob job = GetJob(jobId);

            builder.AppendLine("\nJob ID: " + job.Id);
            builder.AppendLine("Job Name: " + job.Name);
            builder.AppendLine("Job submitted (client UTC time): " + DateTime.UtcNow.ToString());
            builder.AppendLine("Media Services account name: " + _mediaServicesAccountName);

            // Write the output to a local file and to the console. The template 
            // for an error output file is:  JobDetails-{JobId}.txt
            string outputFile = _outputFilesFolder + @"\JobDetails-" + JobIdAsFileName(job.Id) + ".txt";
            WriteToFile(outputFile, builder.ToString());
            Console.Write(builder.ToString());
        }

        static void WriteToFile(string outFilePath, string fileContent)
        {
            StreamWriter sr = File.CreateText(outFilePath);
            sr.Write(fileContent);
            sr.Close();
        }

        static private string JobIdAsFileName(string jobID)
        {
            return jobID.Replace(":", "_");
        }
        static IJob GetJob(string jobId)
        {
            // Use a Linq select query to get an updated 
            // reference by Id. 
            var jobInstance =
                from j in _context.Jobs
                where j.Id == jobId
                select j;
            // Return the job reference as an Ijob. 
            IJob job = jobInstance.FirstOrDefault();

            return job;
        }
        static IAsset GetAsset(string assetId)
        {
            // Use a LINQ Select query to get an asset.
            var assetInstance =
                from a in _context.Assets
                where a.Id == assetId
                select a;
            // Reference the asset as an IAsset.
            IAsset asset = assetInstance.FirstOrDefault();

            return asset;
        }

        //////////////////////////////////////////////////
        // Delete tasks
        //////////////////////////////////////////////////

        static void DeleteAsset(IAsset asset)
        {
            // Delete Asset's locators before
            // deleting the asset.
            foreach (var l in asset.Locators)
            {
                Console.WriteLine("Deleting the Locator {0}", l.Id); 
                l.Delete();
            }

            Console.WriteLine("Deleting the Asset {0}", asset.Id);
            // delete the asset
            asset.Delete();
        }

        static void DeleteAllAccessPoliciesInThisAccount(string existingPolicyId)
        {
            // To delete a specific access policy, get a reference to the policy.  
            // based on the policy Id passed to the method.
            var policy = _context.AccessPolicies.
                Where(p => p.Id == existingPolicyId).FirstOrDefault();

            Console.WriteLine("Deleting policy {0}", existingPolicyId);
            policy.Delete();

        }
    }
}

Run the program (press F5).

This walkthrough has demonstrated a sequence of programming tasks to build a simple Media Services application. You learned the fundamental Media Services programming tasks including getting the server context, creating assets, encoding assets, and downloading or accessing assets on the server. For more advanced development tasks, see the following sections:


Build Date:

2014-09-30
Was this page helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft