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
            }));
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        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]
            }));
        }
Ejemplo n.º 4
0
        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
            }));
        }