As per continue
thread on encoding and indexing process via Azure media service, in this part I
would share technical implementation pf those steps via source code.
We need
to Install the Azure SDK for an additional set of templates and tools which
help you access even more cloud resources and services to improve your Azure
development experience directly from Visual Studio. Also you can install library
using NuGet packages.
Below are
the some of namespace which I have import for this implementation:
using Microsoft.WindowsAzure.MediaServices.Client;
using
Microsoft.WindowsAzure.MediaServices.Client.ContentKeyAuthorization;
using Microsoft.WindowsAzure.MediaServices.Client.DynamicEncryption;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
As mentioned
above - we are using Azure storage and media service class library, first of all
we wold create instance of storage account’s container blob client to pull the
Media files.
CloudQueueClient AzureQueueClient;
CloudQueue AzureCloudQueue;
CloudQueueMessage AzureQueueMessage;
public ProcessorService()
{
var
tokenCredentials = new AzureAdTokenCredentials(AppConfiguration.AADTenantDomain,
new AzureAdClientSymmetricKey(AppConfiguration.ClientId,
AppConfiguration.ClientSecret),
AzureEnvironments.AzureCloudEnvironment);
var
tokenProvider = new AzureAdTokenProvider(tokenCredentials);
context = new CloudMediaContext(new Uri(AppConfiguration.RESTAPIEndpoint),
tokenProvider);
sourceStorageAccount = new CloudStorageAccount(new StorageCredentials(AppConfiguration.SourceStorageAccountName,
AppConfiguration.SourceStorageAccountKey), true);
amsStorageAccount = new CloudStorageAccount(new StorageCredentials(AppConfiguration.AMSStorageAccountName,
AppConfiguration.AMSStorageAccountKey), true);
issuer = AppConfiguration.Issuer;
Audience = AppConfiguration.Audience;
AzureQueueClient =
sourceStorageAccount.CreateCloudQueueClient();
}
Get the
respective blob file :
CloudBlockBlob
blob = (CloudBlockBlob)sourceFile;
Copy
blob file to Azure media service storage container file.
var
amsFile = amsAssetContainer.GetBlockBlobReference(strFilename);
if
(!amsFile.Exists())
{
amsFile.StartCopyAsync(new Uri(sourceFile.Uri.AbsoluteUri
+ signature));
while (true)
{
amsFile.FetchAttributes();
if
(amsFile.CopyState.Status != CopyStatus.Pending)
{
break;
}
//It's
still not completed. So wait for some time.
System.Threading.Thread.Sleep(1000);
}
}
After copy of blob file need to initiate encoding process job
public IAsset
EncodeToAdaptiveBitrateMP4Set(IAsset asset)
{
// Declare a new job.
var job
= context.Jobs.Create(string.Format("Media Encoder
Standard processing of {0}", asset.Name));
var
processor = GetLatestMediaProcessorByName("Media Encoder Standard");
// In this case
"Adaptive Streaming" preset is used.
var
task = job.Tasks.AddNew(string.Format("Media Encoder
Standard processing of {0}", asset.Name),
processor,
"Adaptive
Streaming",
TaskOptions.None);
task.Priority = 100;
task.InputAssets.Add(asset);
task.OutputAssets.AddNew(string.Format("{0}
- Media Encoder Standard encoded", asset.Name),
AssetCreationOptions.None);
job.StateChanged += new EventHandler<JobStateChangedEventArgs>(JobStateChanged);
job.Submit();
job.GetExecutionProgressTask(CancellationToken.None).Wait();
return
job.OutputMediaAssets[0];
}
After continue monitor of job state – finally we would need to publish
URL
private string
GetStreamingOriginLocator(IAsset asset)
{
var
assetFile = asset.AssetFiles.Where(f => f.Name.ToLower().
EndsWith(".ism")).
FirstOrDefault();
IAccessPolicy
policy = context.AccessPolicies.Create("Streaming policy",
TimeSpan.FromDays(1825),
AccessPermissions.Read);
// Create a locator to
the streaming content on an origin.
ILocator
originLocator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin,
asset,
policy,
DateTime.UtcNow.AddMinutes(-5));
// Create a URL to the
manifest file.
return
originLocator.Path + assetFile.Name;
}
You would get streaming locator which would be used in Media play for streaming content.
In the same manner – After Encoding you should initiate the Indexing process job
like below
public IAsset
RunIndexingJob(IAsset asset)
{
// Declare a new job.
IJob job
= context.Jobs.Create(string.Format("Media Indexing
processing of {0}", asset.Name));
// grab an instance of
Azure Media Indexer and run a job
IMediaProcessor
indexer = GetLatestMediaProcessorByName("Azure Media Indexer");
string
title = asset.Name;
title =
System.Text.RegularExpressions.Regex.Replace(title, @"[^\w\.@-]", "
");
string
configuration = "<?xml version=\"1.0\" encoding=\"utf-8\"?><configuration
version=\"2.0\"><input><metadata key=\"title\"
value=\"@title\" /><metadata key=\"description\"
value=\"\" /></input><settings></settings><features><feature
name=\"ASR\"><settings><add key=\"Language\"
value=\"English\"/><add key=\"CaptionFormats\"
value=\"ttml; sami; webvtt\"/><add
key=\"GenerateAIB\" value =\"true\" /><add
key=\"GenerateKeywords\" value =\"true\"
/></settings></feature></features></configuration>";
configuration =
configuration.Replace("@title",
title);
ITask
task = job.Tasks.AddNew(string.Format("Media Indexing
processing of {0}", asset.Name),
indexer,
configuration,
TaskOptions.None);
task.Priority = 100;
// Specify the input
asset to be encoded.
task.InputAssets.Add(asset);
task.OutputAssets.AddNew(string.Format("{0}
- Media Indexed file", asset.Name), AssetCreationOptions.None);
job.StateChanged += new EventHandler<JobStateChangedEventArgs>(JobStateChanged);
job.Submit();
job.GetExecutionProgressTask(CancellationToken.None).Wait();
return
job.OutputMediaAssets[0];
}
After completion of indexing process – you would able to download files.
static void DownloadAsset(IAsset
asset, string outputDirectory)
{
try
{
foreach (IAssetFile
file in asset.AssetFiles)
{
file.Download(Path.Combine(outputDirectory,
file.Name));
}
}
catch (Exception ex)
{
throw ex;
}
}
An
indexing job can generate the following outputs:
- Closed caption files
in the following formats: SAMI, TTML, and WebVTT.
- Keyword file (XML).
- Audio indexing blob file (AIB)
for use with SQL server.
Thank
you!