Example #1
0
        public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log)
        {
            {
                log.Info($"Webhook was triggered!");

                string jsonContent = await req.Content.ReadAsStringAsync();

                dynamic data = JsonConvert.DeserializeObject(jsonContent);

                log.Info(jsonContent);

                if (data.assetId == null)
                {
                    // for test
                    // data.assetId = "nb:cid:UUID:c0d770b4-1a69-43c4-a4e6-bc60d20ab0b2";
                    return(req.CreateResponse(HttpStatusCode.BadRequest, new {
                        error = "Please pass asset ID in the input object (assetId)"
                    }));
                }

                string playerUrl   = "";
                string smoothUrl   = "";
                string pathUrl     = "";
                string preferredSE = data.preferredSE;
                string serveType   = data.serveType;

                MediaServicesCredentials amsCredentials = new MediaServicesCredentials();
                log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}");

                try {
                    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
                    string assetid     = data.assetId;
                    var    outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault();

                    if (outputAsset == null)
                    {
                        log.Info($"Asset not found {assetid}");

                        return(req.CreateResponse(HttpStatusCode.BadRequest, new {
                            error = "Asset not found"
                        }));
                    }

                    // publish with a streaming locator (100 years)
                    log.Info(serveType);
                    if (serveType == "OnDemandOrigin")
                    {
                        IAccessPolicy readPolicy2    = _context.AccessPolicies.Create("readPolicy", TimeSpan.FromDays(365 * 100), AccessPermissions.Read);
                        ILocator      outputLocator2 = _context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, readPolicy2);

                        var publishurlsmooth = MediaServicesHelper.GetValidOnDemandURI(_context, outputAsset, preferredSE);
                        var publishurlpath   = MediaServicesHelper.GetValidOnDemandPath(_context, outputAsset, preferredSE);

                        if (outputLocator2 != null && publishurlsmooth != null)
                        {
                            smoothUrl = publishurlsmooth.ToString();
                            playerUrl = "https://ampdemo.azureedge.net/?url=" + HttpUtility.UrlEncode(smoothUrl);
                            log.Info($"smooth url : {smoothUrl}");
                        }

                        if (outputLocator2 != null && publishurlpath != null)
                        {
                            pathUrl = publishurlpath.ToString();
                            log.Info($"path url : {pathUrl}");
                        }
                    }
                    if (serveType == "sas")
                    {
                        IAccessPolicy readPolicy1    = _context.AccessPolicies.Create("readPolicy", TimeSpan.FromDays(365 * 100), AccessPermissions.Read);
                        ILocator      outputLocator1 = _context.Locators.CreateLocator(LocatorType.Sas, outputAsset, readPolicy1);
                    }
                } catch (Exception ex) {
                    string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : "");
                    log.Info($"ERROR: Exception {message}");
                    return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message }));
                }

                log.Info($"");
                return(req.CreateResponse(HttpStatusCode.OK, new {
                    playerUrl = playerUrl,
                    smoothUrl = smoothUrl,
                    pathUrl = pathUrl
                }));
            }
        }
Example #2
0
        public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log)
        {
            {
                log.Info($"Webhook was triggered!");

                // Init variables
                string  pathUrl            = "";
                dynamic pngThumbnails      = new JArray() as dynamic;
                string  prefixpng          = "";
                string  copyToContainer    = "";
                string  targetContainerUri = "";

                TimeSpan timeOffset = new TimeSpan(0);

                string jsonContent = await req.Content.ReadAsStringAsync();

                dynamic data = JsonConvert.DeserializeObject(jsonContent);

                var attachedstoragecred = KeyHelper.ReturnStorageCredentials();

                log.Info(jsonContent);

                MediaServicesCredentials amsCredentials = new MediaServicesCredentials();
                log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}");

                try
                {
                    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);


                    //
                    // MES Thumbnails
                    //
                    if (data.mesThumbnails != null && data.mesThumbnails.assetId != null)
                    {
                        List <CloudBlob> listPNGCopies = new List <CloudBlob>();

                        // Get the asset
                        string assetid     = data.mesThumbnails.assetId;
                        var    outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault();

                        if (outputAsset == null)
                        {
                            log.Info($"Asset not found {assetid}");
                            return(req.CreateResponse(HttpStatusCode.BadRequest, new
                            {
                                error = "Asset not found"
                            }));
                        }

                        var pngFiles = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".PNG"));

                        Uri publishurl = MediaServicesHelper.GetValidOnDemandPath(_context, outputAsset);
                        if (publishurl != null)
                        {
                            pathUrl = publishurl.ToString();
                        }
                        else
                        {
                            log.Info($"Asset not published");
                        }

                        // Let's copy the PNG Thumbnails
                        if (data.mesThumbnails.copyToContainer != null)
                        {
                            copyToContainer = data.mesThumbnails.copyToContainer + DateTime.UtcNow.ToString("yyyyMMdd");
                            // let's copy PNG to a container
                            prefixpng = outputAsset.Uri.Segments[1] + "-";
                            log.Info($"prefixpng {prefixpng}");

                            string storname = amsCredentials.StorageAccountName;
                            string storkey  = amsCredentials.StorageAccountKey;
                            if (outputAsset.StorageAccountName != amsCredentials.StorageAccountName)
                            {
                                if (attachedstoragecred.ContainsKey(outputAsset.StorageAccountName)) // asset is using another storage than default but we have the key
                                {
                                    storname = outputAsset.StorageAccountName;
                                    storkey  = attachedstoragecred[storname];
                                }
                                else // we don't have the key for that storage
                                {
                                    log.Info($"MES Thumbnails Asset is in {outputAsset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings");
                                    return(req.CreateResponse(HttpStatusCode.BadRequest, new
                                    {
                                        error = "Storage key is missing"
                                    }));
                                }
                            }

                            var sourceContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, outputAsset.Uri.Segments[1]);

                            CloudBlobContainer targetContainer;
                            if (data.mesThumbnails.copyToContainerAccountName != null)
                            {
                                // copy to a specific storage account
                                targetContainer = CopyBlobHelpers.GetCloudBlobContainer((string)data.mesThumbnails.copyToContainerAccountName, (string)data.mesThumbnails.copyToContainerAccountKey, copyToContainer);
                            }
                            else
                            {
                                // copy to ams storage account
                                targetContainer = CopyBlobHelpers.GetCloudBlobContainer(amsCredentials.StorageAccountName, amsCredentials.StorageAccountKey, copyToContainer);
                            }

                            listPNGCopies = await CopyBlobHelpers.CopyFilesAsync(sourceContainer, targetContainer, prefixpng, "png", log);

                            targetContainerUri = targetContainer.Uri.ToString();
                        }

                        foreach (IAssetFile file in pngFiles)
                        {
                            string index   = file.Name.Substring(file.Name.Length - 10, 6);
                            int    index_i = 0;
                            if (int.TryParse(index, out index_i))
                            {
                                dynamic entry = new JObject();
                                entry.id       = index_i;
                                entry.fileId   = file.Id;
                                entry.fileName = file.Name;
                                if (copyToContainer != "")
                                {
                                    entry.url = targetContainerUri + "/" + prefixpng + file.Name;
                                }
                                else if (!string.IsNullOrEmpty(pathUrl))
                                {
                                    entry.url = pathUrl + file.Name;
                                }
                                pngThumbnails.Add(entry);
                            }
                        }

                        if (data.mesThumbnails.deleteAsset != null && ((bool)data.mesThumbnails.deleteAsset))
                        {
                            // If asset deletion was asked
                            // let's wait for the copy to finish before deleting the asset..
                            if (listPNGCopies.Count > 0)
                            {
                                log.Info("PNG Copy with asset deletion was asked. Checking copy status...");
                                bool continueLoop = true;
                                while (continueLoop)
                                {
                                    listPNGCopies = listPNGCopies.Where(r => r.CopyState.Status == CopyStatus.Pending).ToList();
                                    if (listPNGCopies.Count == 0)
                                    {
                                        continueLoop = false;
                                    }
                                    else
                                    {
                                        log.Info("PNG Copy not finished. Waiting 3s...");
                                        Task.Delay(TimeSpan.FromSeconds(3d)).Wait();
                                        listPNGCopies.ForEach(r => r.FetchAttributes());
                                    }
                                }
                            }
                            outputAsset.Delete();
                        }
                    }
                }
                catch (Exception ex)
                {
                    string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : "");
                    log.Info($"ERROR: Exception {message}");
                    return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message }));
                }

                log.Info($"");
                return(req.CreateResponse(HttpStatusCode.OK, new
                {
                    mesThumbnail = new
                    {
                        pngThumbnails = Newtonsoft.Json.JsonConvert.SerializeObject(pngThumbnails)
                    }
                }));
            }
        }
        public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log)
        {
            {
                log.Info($"Webhook was triggered!");

                // Init variables
                string vttUrl      = "";
                string pathUrl     = "";
                string ttmlUrl     = "";
                string vttContent  = "";
                string ttmlContent = "";
                string ttmlContentTimeCorrected = "";
                string vttContentTimeCorrected  = "";

                string jsonContent = await req.Content.ReadAsStringAsync();

                dynamic data = JsonConvert.DeserializeObject(jsonContent);

                log.Info(jsonContent);

                if (data.assetId == null)
                {
                    // for test
                    // data.assetId = "nb:cid:UUID:d9496372-32f5-430d-a4c6-d21ec3e01525";

                    return(req.CreateResponse(HttpStatusCode.BadRequest, new
                    {
                        error = "Please pass asset ID in the input object (AssetId)"
                    }));
                }

                MediaServicesCredentials amsCredentials = new MediaServicesCredentials();
                log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}");

                try
                {
                    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
                    string assetid     = data.assetId;
                    var    outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault();

                    if (outputAsset == null)
                    {
                        log.Info($"Asset not found {assetid}");
                        return(req.CreateResponse(HttpStatusCode.BadRequest, new
                        {
                            error = "Asset not found"
                        }));
                    }

                    var vttSubtitle  = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".VTT")).FirstOrDefault();
                    var ttmlSubtitle = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".TTML")).FirstOrDefault();

                    Uri publishurl = MediaServicesHelper.GetValidOnDemandPath(_context, outputAsset);
                    if (publishurl != null)
                    {
                        pathUrl = publishurl.ToString();
                    }
                    else
                    {
                        log.Info($"Asset not published");
                    }

                    if (vttSubtitle != null)
                    {
                        if (publishurl != null)
                        {
                            vttUrl = pathUrl + vttSubtitle.Name;
                            log.Info($"vtt url : {vttUrl}");
                        }
                        vttContent = MediaServicesHelper.ReturnContent(vttSubtitle);

                        if (data.timeOffset != null) // let's update the ttml with new timecode
                        {
                            var           tsoffset = TimeSpan.Parse((string)data.timeOffset);
                            string        arrow    = " --> ";
                            StringBuilder sb       = new 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 + tsoffset).ToString(@"d\.hh\:mm\:ss\.fff") + arrow + (end + tsoffset).ToString(@"d\.hh\:mm\:ss\.fff");
                                }
                                sb.AppendLine(line);
                            }
                            vttContentTimeCorrected = sb.ToString();
                        }
                    }

                    if (ttmlSubtitle != null)
                    {
                        if (publishurl != null)
                        {
                            ttmlUrl = pathUrl + vttSubtitle.Name;
                            log.Info($"ttml url : {ttmlUrl}");
                        }
                        ttmlContent = MediaServicesHelper.ReturnContent(ttmlSubtitle);
                        if (data.timeOffset != null) // let's update the vtt with new timecode
                        {
                            var tsoffset = TimeSpan.Parse((string)data.timeOffset);
                            log.Info("tsoffset : " + tsoffset.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        subtitles = docXML.Element(xmlns + "tt").Element(xmlns + "body").Element(xmlns + "div").Elements(xmlns + "p");
                            foreach (var sub in subtitles)
                            {
                                var begin = TimeSpan.Parse((string)sub.Attribute("begin"));
                                var end   = TimeSpan.Parse((string)sub.Attribute("end"));
                                sub.SetAttributeValue("end", (end + tsoffset).ToString(@"d\.hh\:mm\:ss\.fff"));
                                sub.SetAttributeValue("begin", (begin + tsoffset).ToString(@"d\.hh\:mm\:ss\.fff"));
                            }
                            ttmlContentTimeCorrected = docXML.Declaration.ToString() + Environment.NewLine + docXML.ToString();
                        }
                    }

                    if (ttmlContent != "" && vttContent != "" && data.deleteAsset != null && ((bool)data.deleteAsset))
                    // If asset deletion was asked
                    {
                        outputAsset.Delete();
                    }
                }
                catch (Exception ex)
                {
                    string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : "");
                    log.Info($"ERROR: Exception {message}");
                    return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message }));
                }

                log.Info($"");
                return(req.CreateResponse(HttpStatusCode.OK, new
                {
                    vttUrl = vttUrl,
                    ttmlUrl = ttmlUrl,
                    pathUrl = pathUrl,
                    ttmlDocument = ttmlContent,
                    ttmlDocumentWithOffset = ttmlContentTimeCorrected,
                    vttDocument = vttContent,
                    vttDocumentWithOffset = vttContentTimeCorrected
                }));
            }
        }