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 })); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"AMS v2 Function - MonitorBlobContainerCopyStatus was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // Validate input objects if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } if (data.destinationContainer == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass destinationContainer in the input object" })); } string assetId = data.assetId; string destinationContainerName = data.destinationContainer; List <string> fileNames = null; if (data.fileNames != null) { fileNames = ((JArray)data.fileNames).ToObject <List <string> >(); } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); bool copyStatus = true; JArray blobCopyStatusList = new JArray(); try { // Setup blob container /* * // Azure AD Storage API access * string accessToken = BlobStorageHelper.GetUserOAuthToken(amsCredentials.AmsAadTenantDomain, amsCredentials.AmsClientId, amsCredentials.AmsClientSecret); * TokenCredential tokenCredential = new TokenCredential(accessToken); * StorageCredentials storageCredentials = new StorageCredentials(tokenCredential); * CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(storageCredentials, storageAccountName, destinationContainerName); */ CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(BlobStorageHelper.AmsStorageAccountName, BlobStorageHelper.AmsStorageAccountKey, destinationContainerName); string blobPrefix = null; bool useFlatBlobListing = true; log.Info("Checking CopyStatus of all blobs in the source container..."); var destBlobList = destinationBlobContainer.ListBlobs(blobPrefix, useFlatBlobListing, BlobListingDetails.Copy); foreach (var dest in destBlobList) { var destBlob = dest as CloudBlob; bool found = false; foreach (var fileName in fileNames) { if (fileName == destBlob.Name) { found = true; break; } } if (found == false) { break; } if (destBlob.CopyState.Status == CopyStatus.Aborted || destBlob.CopyState.Status == CopyStatus.Failed) { // Log the copy status description for diagnostics and restart copy destBlob.StartCopyAsync(destBlob.CopyState.Source); copyStatus = false; } else if (destBlob.CopyState.Status == CopyStatus.Pending) { // We need to continue waiting for this pending copy // However, let us log copy state for diagnostics copyStatus = false; } // else we completed this pending copy string blobName = destBlob.Name as string; int blobCopyStatus = (int)(destBlob.CopyState.Status); JObject o = new JObject(); o["blobName"] = blobName; o["blobCopyStatus"] = blobCopyStatus; blobCopyStatusList.Add(o); } } catch (Exception e) { log.Info($"ERROR: Exception {e}"); return(req.CreateResponse(HttpStatusCode.BadRequest)); } JObject result = new JObject(); result["copyStatus"] = copyStatus; result["blobCopyStatusList"] = blobCopyStatusList; return(req.CreateResponse(HttpStatusCode.OK, result)); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"AMS v2 Function - StartBlobContainerCopyToAsset was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // Validate input objects if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } if (data.sourceStorageAccountName == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass sourceStorageAccountName in the input object" })); } if (data.sourceStorageAccountKey == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass sourceStorageAccountKey in the input object" })); } if (data.sourceContainer == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass sourceContainer in the input object" })); } //if (data.destinationContainer == null) // return req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass destinationContainer in the input object" }); string assetId = data.assetId; string _sourceStorageAccountName = data.sourceStorageAccountName; string _sourceStorageAccountKey = data.sourceStorageAccountKey; string sourceContainerName = data.sourceContainer; //string destinationContainerName = data.destinationContainer; List <string> fileNames = null; if (data.fileNames != null) { fileNames = ((JArray)data.fileNames).ToObject <List <string> >(); } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); IAsset asset = 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" })); } // Setup blob container CloudBlobContainer sourceBlobContainer = BlobStorageHelper.GetCloudBlobContainer(_sourceStorageAccountName, _sourceStorageAccountKey, sourceContainerName); sourceBlobContainer.CreateIfNotExists(); /* * // Azure AD Storage API access * string accessToken = BlobStorageHelper.GetUserOAuthToken(amsCredentials.AmsAadTenantDomain, amsCredentials.AmsClientId, amsCredentials.AmsClientSecret); * TokenCredential tokenCredential = new TokenCredential(accessToken); * StorageCredentials storageCredentials = new StorageCredentials(tokenCredential); * string[] uri = asset.Uri.Host.Split('.'); * string storageAccountName = uri[0]; * CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(storageCredentials, storageAccountName, asset.Uri.Segments[1]); */ CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(BlobStorageHelper.AmsStorageAccountName, BlobStorageHelper.AmsStorageAccountKey, asset.Uri.Segments[1]); // Copy Source Blob container into Destination Blob container that is associated with the asset. BlobStorageHelper.CopyBlobsAsync(sourceBlobContainer, destinationBlobContainer, fileNames, log); } catch (Exception e) { log.Info($"Exception {e}"); return(req.CreateResponse(HttpStatusCode.BadRequest)); } return(req.CreateResponse(HttpStatusCode.OK, new { destinationContainer = asset.Uri.Segments[1] })); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation($"AMS v3 Function - StartBlobContainerCopyToAsset was triggered!"); string requestBody = new StreamReader(req.Body).ReadToEnd(); dynamic data = JsonConvert.DeserializeObject(requestBody); // Validate input objects if (data.assetName == null) { return(new BadRequestObjectResult("Please pass assetName in the input object")); } if (data.sourceStorageAccountName == null) { return(new BadRequestObjectResult("Please pass sourceStorageAccountName in the input object")); } if (data.sourceStorageAccountKey == null) { return(new BadRequestObjectResult("Please pass sourceStorageAccountKey in the input object")); } if (data.sourceContainer == null) { return(new BadRequestObjectResult("Please pass sourceContainer in the input object")); } string assetName = data.assetName; string sourceStorageAccountName = data.sourceStorageAccountName; string sourceStorageAccountKey = data.sourceStorageAccountKey; string sourceContainerName = data.sourceContainer; List <string> fileNames = null; if (data.fileNames != null) { fileNames = ((JArray)data.fileNames).ToObject <List <string> >(); } string destinationBlobContainerName = null; MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper(); Asset asset = null; try { IAzureMediaServicesClient client = MediaServicesHelper.CreateMediaServicesClientAsync(amsconfig); // Get the Asset asset = client.Assets.Get(amsconfig.ResourceGroup, amsconfig.AccountName, assetName); if (asset == null) { return(new BadRequestObjectResult("Asset not found")); } // Setup blob container CloudBlobContainer sourceBlobContainer = BlobStorageHelper.GetCloudBlobContainer(sourceStorageAccountName, sourceStorageAccountKey, sourceContainerName); var response = client.Assets.ListContainerSas(amsconfig.ResourceGroup, amsconfig.AccountName, assetName, permissions: AssetContainerPermission.ReadWrite, expiryTime: DateTime.UtcNow.AddHours(4).ToUniversalTime()); var sasUri = new Uri(response.AssetContainerSasUrls.First()); CloudBlobContainer destinationBlobContainer = new CloudBlobContainer(sasUri); destinationBlobContainerName = destinationBlobContainer.Name; // Copy Source Blob container into Destination Blob container that is associated with the asset. BlobStorageHelper.CopyBlobsAsync(sourceBlobContainer, destinationBlobContainer, fileNames); } catch (ApiErrorException e) { log.LogError($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}"); return(new BadRequestObjectResult("AMS API call error: " + e.Message + "\nError Code: " + e.Body.Error.Code + "\nMessage: " + e.Body.Error.Message)); } catch (Exception e) { log.LogError($"ERROR: Exception with message: {e.Message}"); return(new BadRequestObjectResult("Error: " + e.Message)); } return((ActionResult) new OkObjectResult(new { destinationContainer = destinationBlobContainerName })); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"AMS v2 Function - AddAssetFiles was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // Validate input objects if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } if (data.primaryFileName == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass primaryFileName in the input object" })); } string assetId = data.assetId; string primaryFileName = data.primaryFileName; List <string> fileNames = null; if (data.fileNames != null) { fileNames = ((JArray)data.fileNames).ToObject <List <string> >(); } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); IAsset asset = 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]; /* * // Azure AD Storage API access * string[] uri = asset.Uri.Host.Split('.'); * string storageAccountName = uri[0]; * * string accessToken = BlobStorageHelper.GetUserOAuthToken(amsCredentials.AmsAadTenantDomain, amsCredentials.AmsClientId, amsCredentials.AmsClientSecret); * TokenCredential tokenCredential = new TokenCredential(accessToken); * StorageCredentials storageCredentials = new StorageCredentials(tokenCredential); * CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(storageCredentials, storageAccountName, destinationContainerName); */ CloudBlobContainer destinationBlobContainer = BlobStorageHelper.GetCloudBlobContainer(BlobStorageHelper.AmsStorageAccountName, BlobStorageHelper.AmsStorageAccountKey, destinationContainerName); foreach (var fileName in fileNames) { IAssetFile assetFile = asset.AssetFiles.Create(fileName); CloudBlockBlob blob = destinationBlobContainer.GetBlockBlobReference(fileName); blob.FetchAttributes(); assetFile.ContentFileSize = blob.Properties.Length; assetFile.IsPrimary = false; if (fileName == primaryFileName) { assetFile.IsPrimary = true; } assetFile.Update(); } } catch (Exception e) { log.Info($"ERROR: Exception {e}"); return(req.CreateResponse(HttpStatusCode.BadRequest)); } return(req.CreateResponse(HttpStatusCode.OK, new { assetId = assetId })); }