public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"AMS v2 Function - GetCaptionBlobSasUri was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // parameter handling if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } string assetId = data.assetId; string timecodeOffset = null; if (data.timecodeOffset != null) { timecodeOffset = data.timecodeOffset; } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); IAsset asset = null; string vttContent = ""; string vttContentTimeOffset = ""; string vttBlobSasUri = null; string ttmlContent = ""; string ttmlContentTimeOffset = ""; string ttmlBlobSasUri = null; try { // Load AMS account context log.Info($"Using AMS v2 REST API Endpoint : {amsCredentials.AmsRestApiEndpoint.ToString()}"); AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Get the Asset asset = _context.Assets.Where(a => a.Id == assetId).FirstOrDefault(); if (asset == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } string destinationContainerName = asset.Uri.Segments[1]; var vttAssetFile = asset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".VTT")).FirstOrDefault(); var ttmlAssetFile = asset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".TTML")).FirstOrDefault(); if (vttAssetFile != null) { vttContent = MediaServicesHelper.GetContentFromAssetFile(vttAssetFile); CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(BlobStorageHelper.AmsStorageAccountName, BlobStorageHelper.AmsStorageAccountKey, destinationContainerName); CloudBlockBlob blobVTT = destinationBlobContainer.GetBlockBlobReference(vttAssetFile.Name); if (timecodeOffset != null) // let's update the ttml with new timecode { var tcOffset = TimeSpan.Parse(timecodeOffset); string arrow = " --> "; System.Text.StringBuilder sb = new System.Text.StringBuilder(); string[] delim = { Environment.NewLine, "\n" }; // "\n" added in case you manually appended a newline string[] vttlines = vttContent.Split(delim, StringSplitOptions.None); foreach (string vttline in vttlines) { string line = vttline; if (vttline.Contains(arrow)) { TimeSpan begin = TimeSpan.Parse(vttline.Substring(0, vttline.IndexOf(arrow))); TimeSpan end = TimeSpan.Parse(vttline.Substring(vttline.IndexOf(arrow) + 5)); line = (begin + tcOffset).ToString(@"d\.hh\:mm\:ss\.fff") + arrow + (end + tcOffset).ToString(@"d\.hh\:mm\:ss\.fff"); } sb.AppendLine(line); } vttContentTimeOffset = sb.ToString(); if (vttContentTimeOffset != null) { string blobName = "Converted-" + vttAssetFile.Name; blobVTT = MediaServicesHelper.WriteContentToBlob(asset, destinationBlobContainer, blobName, vttContentTimeOffset); } } // Get Blob URI with SAS Token var sasBlobPolicy = new SharedAccessBlobPolicy(); sasBlobPolicy.SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5); sasBlobPolicy.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10); sasBlobPolicy.Permissions = SharedAccessBlobPermissions.Read; string sasBlobToken = blobVTT.GetSharedAccessSignature(sasBlobPolicy); vttBlobSasUri = blobVTT.Uri + sasBlobToken; } if (ttmlAssetFile != null) { ttmlContent = MediaServicesHelper.GetContentFromAssetFile(ttmlAssetFile); CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(BlobStorageHelper.AmsStorageAccountName, BlobStorageHelper.AmsStorageAccountKey, destinationContainerName); CloudBlockBlob blobTTML = destinationBlobContainer.GetBlockBlobReference(ttmlAssetFile.Name); if (timecodeOffset != null) // let's update the vtt with new timecode { var tcOffset = TimeSpan.Parse(timecodeOffset); //log.Info("tsoffset : " + tcOffset.ToString(@"d\.hh\:mm\:ss\.fff")); XNamespace xmlns = "http://www.w3.org/ns/ttml"; XDocument docXML = XDocument.Parse(ttmlContent); var tt = docXML.Element(xmlns + "tt"); var ttmlElements = docXML.Element(xmlns + "tt").Element(xmlns + "body").Element(xmlns + "div").Elements(xmlns + "p"); foreach (var ttmlElement in ttmlElements) { var begin = TimeSpan.Parse((string)ttmlElement.Attribute("begin")); var end = TimeSpan.Parse((string)ttmlElement.Attribute("end")); ttmlElement.SetAttributeValue("end", (end + tcOffset).ToString(@"d\.hh\:mm\:ss\.fff")); ttmlElement.SetAttributeValue("begin", (begin + tcOffset).ToString(@"d\.hh\:mm\:ss\.fff")); } ttmlContentTimeOffset = docXML.Declaration.ToString() + Environment.NewLine + docXML.ToString(); if (ttmlContentTimeOffset != null) { string blobName = "Converted-" + ttmlAssetFile.Name; blobTTML = MediaServicesHelper.WriteContentToBlob(asset, destinationBlobContainer, blobName, ttmlContentTimeOffset); } } // Get Blob URI with SAS Token var sasBlobPolicy = new SharedAccessBlobPolicy(); sasBlobPolicy.SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5); sasBlobPolicy.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10); sasBlobPolicy.Permissions = SharedAccessBlobPermissions.Read; string sasBlobToken = blobTTML.GetSharedAccessSignature(sasBlobPolicy); ttmlBlobSasUri = blobTTML.Uri + sasBlobToken; } } catch (Exception e) { log.Info($"Exception {e}"); return(req.CreateResponse(HttpStatusCode.BadRequest)); } return(req.CreateResponse(HttpStatusCode.OK, new { vttBlobSasUri = vttBlobSasUri, ttmlBlobSasUri = ttmlBlobSasUri })); }