Copying existing blobs into a Media Services Asset

media services logo


Update your Azure Media Services REST API and SDKs to v3 by 29 February 2024. Version 3 of Azure Media Services REST API and client SDKs for .NET and Java offers more capabilities than version 2. We’re retiring version 2 of the Azure Media Services REST API and client SDKs for .NET and Java.

Action Required: To minimize disruption to your workloads, review the migration guide to transition your code from the version 2 API and SDKs to version 3 API and SDK before February 29th, 2024. After February 29th, 2024, Azure Media Services will no longer accept traffic on the version 2 REST API, the ARM account management API version 2015-10-01, or from the version 2 .NET client SDKs. This includes any 3rd party open-source client SDKS that may call the version 2 API. Learn about the latest version, starting with the Media Services v3 Overview.

This article shows how to copy blobs from a storage account into a new Azure Media Services (AMS) asset using Azure Media Services .NET SDK Extensions.

You should not attempt to change the contents of blob containers that were generated by Media Services without using Media Service APIs.

The extension methods work with:

  • Regular assets.
  • Live archive assets (FragBlob format).
  • Source and destination assets belonging to different Media Services accounts (even across different data centers). However, there may be charges incurred by doing so. For more information about pricing, see Data Transfers.

The article shows two code samples:

  1. Copy blobs from an asset in one AMS account into a new asset in another AMS account.
  2. Copy blobs from some storage account into a new asset in an AMS account.

Copy blobs between two AMS accounts


Two Media Services accounts. See the article How to Create a Media Services Account.

Set up your project

  1. Set up your development environment as described in Media Services development with .NET.
  2. Add the appSettings section to the .config file and update the values based on your Media Services accounts, the destination storage account, and the source asset ID.
    <add key="AMSSourceAADTenantDomain" value="tenant"/>
    <add key="AMSSourceRESTAPIEndpoint" value="endpoint"/>

    <add key="SourceAMSClientId" value="clientID"/>
    <add key="SourceAMSClientSecret" value="clientSecret"/>

    <add key="SourceAssetID" value="nb:cid:UUID:<id>"/>

    <add key="AMSDestAADTenantDomain" value="tenant"/>
    <add key="AMSDestRESTAPIEndpoint" value="endpoint"/>

    <add key="DestAMSClientId" value="clientID"/>
    <add key="DestAMSClientSecret" value="clientSecret"/>

    <add key="DestStorageAccountName" value="name"/>
    <add key="DestStorageAccountKey" value="key"/>


Copy blobs from an asset in one AMS account into an asset in another AMS account

The following code uses extension IAsset.Copy method to copy all files in the source asset into the destination asset using a single extension.

using System;
using Microsoft.WindowsAzure.MediaServices.Client;
using System.Linq;
using System.Configuration;
using Microsoft.WindowsAzure.Storage.Auth;

namespace CopyExistingBlobsIntoAsset
    class Program
        static string _sourceAADTenantDomain =
        static string _sourceRESTAPIEndpoint =
        static string _sourceClientId =
        static string _sourceClientSecret =

        static string _destAADTenantDomain =
        static string _destRESTAPIEndpoint =
        static string _destClientId =
        static string _destClientSecret =

        static string _destStorageAccountName =
        static string _destStorageAccountKey =
        static string _sourceAssetID =

        private static CloudMediaContext _sourceContext = null;
        private static CloudMediaContext _destContext = null;

        static void Main(string[] args)
            AzureAdTokenCredentials tokenCredentials1 = new AzureAdTokenCredentials(_sourceAADTenantDomain,
                   new AzureAdClientSymmetricKey(_sourceClientId, _sourceClientSecret),

            AzureAdTokenCredentials tokenCredentials2 = new AzureAdTokenCredentials(_destAADTenantDomain,
                   new AzureAdClientSymmetricKey(_destClientId, _destClientSecret),

            var tokenProvider1 = new AzureAdTokenProvider(tokenCredentials1);
            var tokenProvider2 = new AzureAdTokenProvider(tokenCredentials2);

            // Create the context for your source Media Services account.
            _sourceContext = new CloudMediaContext(new Uri(_sourceRESTAPIEndpoint), tokenProvider1);

            // Create the context for your destination Media Services account.
            _destContext = new CloudMediaContext(new Uri(_destRESTAPIEndpoint), tokenProvider2);

            // Get the credentials of the default Storage account bound to your destination Media Services account.
            StorageCredentials destinationStorageCredentials =
                new StorageCredentials(_destStorageAccountName, _destStorageAccountKey);

            // Get a reference to the source asset in the source context.
            IAsset sourceAsset = _sourceContext.Assets.Where(asset => asset.Id == _sourceAssetID).First();

            // Create an empty destination asset in the destination context.
            IAsset destinationAsset = _destContext.Assets.Create(sourceAsset.Name, AssetCreationOptions.None);

            // Copy the files in the source asset instance into the destination asset instance.
            // There is an additional overload with async support.
            sourceAsset.Copy(destinationAsset, destinationStorageCredentials);


Copy blobs from a storage account into an AMS account


  • One Storage account from which you want to copy blobs.
  • One AMS account into which you want to copy blobs.

Set up your project

  1. Set up your development environment as described in Media Services development with .NET.
  2. Add the appSettings section to the .config file and update the values based on your source storage and destination AMS accounts.
    <add key="SourceStorageAccountName" value="name" />
    <add key="SourceStorageAccountKey" value="key" />
    <add key="NameOfBlobContainerYouWantToCopy" value="BlobContainerName"/>

    <add key="AMSAADTenantDomain" value="tenant"/>
    <add key="AMSRESTAPIEndpoint" value="endpoint"/>
    <add key="AMSClientId" value="clientID"/>
    <add key="AMSClientSecret" value="clientSecret"/>
    <add key="AMSStorageAccountName" value="name"/>
    <add key="AMSStorageAccountKey" value="key"/>

Copy blobs from some storage account into a new asset in an AMS account

The following code copies blobs from a storage account into a Media Services asset.


There is a limit of 1,000,000 policies for different AMS policies (for example, for Locator policy or ContentKeyAuthorizationPolicy). You should use the same policy ID if you are always using the same days / access permissions, for example, policies for locators that are intended to remain in place for a long time (non-upload policies). For more information, see this article.

using System;
using System.Configuration;
using System.Linq;
using Microsoft.WindowsAzure.MediaServices.Client;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

namespace CopyExistingBlobsIntoAsset
    class Program
        // Read values from the App.config file.
        private static readonly string _sourceStorageAccountName =
        private static readonly string _sourceStorageAccountKey =
        private static readonly string _NameOfBlobContainerYouWantToCopy =

        private static readonly string _AMSAADTenantDomain =
        private static readonly string _AMSRESTAPIEndpoint =
        private static readonly string _AMSClientId =
        private static readonly string _AMSClientSecret =
        private static readonly string _AMSStorageAccountName =
        private static readonly string _AMSStorageAccountKey =

        // Field for service context.
        private static CloudMediaContext _context = null;
        private static CloudStorageAccount _sourceStorageAccount = null;
        private static CloudStorageAccount _destinationStorageAccount = null;

        static void Main(string[] args)
            AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_AMSAADTenantDomain,
               new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),

            var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

            // Create the context for your source Media Services account.
            _context = new CloudMediaContext(new Uri(_AMSRESTAPIEndpoint), tokenProvider);

            _sourceStorageAccount =
                new CloudStorageAccount(new StorageCredentials(_sourceStorageAccountName,
                    _sourceStorageAccountKey), true);

            _destinationStorageAccount =
                new CloudStorageAccount(new StorageCredentials(_AMSStorageAccountName,
                    _AMSStorageAccountKey), true);

            CloudBlobClient sourceCloudBlobClient =
            CloudBlobContainer sourceContainer =



        static private IAsset CreateAssetFromExistingBlobs(CloudBlobContainer sourceBlobContainer)
            CloudBlobClient destBlobStorage = _destinationStorageAccount.CreateCloudBlobClient();

            // Create a new asset.
            IAsset asset = _context.Assets.Create("NewAsset_" + Guid.NewGuid(), AssetCreationOptions.None);

            IAccessPolicy writePolicy = _context.AccessPolicies.Create("writePolicy",
                TimeSpan.FromHours(24), AccessPermissions.Write);

            ILocator destinationLocator =
                _context.Locators.CreateLocator(LocatorType.Sas, asset, writePolicy);

            // Get the asset container URI and Blob copy from mediaContainer to assetContainer.
            CloudBlobContainer destAssetContainer =
                destBlobStorage.GetContainerReference((new Uri(destinationLocator.Path)).Segments[1]);

            if (destAssetContainer.CreateIfNotExists())
                destAssetContainer.SetPermissions(new BlobContainerPermissions
                    PublicAccess = BlobContainerPublicAccessType.Blob

            var blobList = sourceBlobContainer.ListBlobs();

            foreach (CloudBlockBlob sourceBlob in blobList)
                var assetFile = asset.AssetFiles.Create((sourceBlob as ICloudBlob).Name);

                ICloudBlob destinationBlob = destAssetContainer.GetBlockBlobReference(assetFile.Name);

                CopyBlob(sourceBlob, destAssetContainer);

                assetFile.ContentFileSize = (sourceBlob as ICloudBlob).Properties.Length;
                Console.WriteLine("File {0} is of {1} size", assetFile.Name, assetFile.ContentFileSize);



            // Set the primary asset file.
            // If, for example, we copied a set of Smooth Streaming files,
            // set the .ism file to be the primary file.
            // If we, for example, copied an .mp4, then the mp4 would be the primary file.
            var ismAssetFile = asset.AssetFiles.ToList().
                Where(f => f.Name.EndsWith(".ism", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

            // The following code assigns the first .ism file as the primary file in the asset.
            // An asset should have one .ism file.
            if (ismAssetFile != null)
                ismAssetFile.IsPrimary = true;

            return asset;

        /// <summary>
        /// Copies the specified blob into the specified container.
        /// </summary>
        /// <param name="sourceBlob">The source container.</param>
        /// <param name="destinationContainer">The destination container.</param>
        static private void CopyBlob(ICloudBlob sourceBlob, CloudBlobContainer destinationContainer)
            var signature = sourceBlob.GetSharedAccessSignature(new SharedAccessBlobPolicy
                Permissions = SharedAccessBlobPermissions.Read,
                SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24)

            var destinationBlob = destinationContainer.GetBlockBlobReference(sourceBlob.Name);

            if (destinationBlob.Exists())
                Console.WriteLine(string.Format("Destination blob '{0}' already exists. Skipping.", destinationBlob.Uri));

                // Display the size of the source blob.

                Console.WriteLine(string.Format("Copy blob '{0}' to '{1}'", sourceBlob.Uri, destinationBlob.Uri));
                destinationBlob.StartCopy(new Uri(sourceBlob.Uri.AbsoluteUri + signature));

                while (true)
                    // The StartCopyFromBlob is an async operation,
                    // so we want to check if the copy operation is completed before proceeding.
                    // To do that, we call FetchAttributes on the blob and check the CopyStatus.
                    if (destinationBlob.CopyState.Status != CopyStatus.Pending)
                    //It's still not completed. So wait for some time.

                // Display the size of the destination blob.