public static async Task Run([EventGridTrigger] JObject eventGridEvent, TraceWriter log, ExecutionContext executionContext)
        {
            Guid   newReqId = Guid.NewGuid();
            bool   result   = true;
            string reqId    = string.Empty;

            try
            {
                log.Info($"Start RedactorProcessing requestId: {newReqId} {eventGridEvent.ToString(Formatting.Indented)} ticks: {DateTime.Now.Ticks}");
                var eventGrid = eventGridEvent.ToObject <Event <VideoAssetData> >();
                reqId = eventGrid.Data.RequestId;
                IAsset asset = FaceHelper.GetAsset(eventGrid.Data.AssetName);
                if (asset != null)
                {
                    string assetName  = eventGrid.Data.JobName + "_" + eventGrid.Data.Step;
                    string configFile = Directory.GetParent(executionContext.FunctionDirectory).FullName + "\\config.json";
                    await FaceHelper.RunFaceRedactionJob(asset, assetName, configFile, log);

                    log.Info($"request {newReqId} for {reqId} started redactor process send event grid to start copy process ticks: {DateTime.Now.Ticks}");
                }
                else
                {
                    log.Info($"request {newReqId} for {reqId} didn't start redactor no related asset name {eventGrid.Data.AssetName} ticks: {DateTime.Now.Ticks}");
                }
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {newReqId} for {reqId}, ticks: {DateTime.Now.Ticks}", ex);
                result = false;
            }
            string succeed = result ? "" : "unsuccessful";

            log.Info($"Finished {succeed} RedactorProcessing requestId: {newReqId} for {reqId} ticks: {DateTime.Now.Ticks}");
        }
        public static async Task Run([EventGridTrigger] JObject eventGridEvent, TraceWriter log)
        {
            Guid   newReqId = Guid.NewGuid();
            bool   result   = true;
            string reqId    = string.Empty;

            try
            {
                log.Info($"Start EncodeProcessing requestId: {newReqId} {eventGridEvent.ToString(Formatting.Indented)} ticks: {DateTime.Now.Ticks}");
                var eventGrid = eventGridEvent.ToObject <Event <VideoAssetData> >();
                reqId = eventGrid.Data.RequestId;
                IAsset asset = FaceHelper.GetAsset(eventGrid.Data.AssetName);
                if (asset != null)
                {
                    string assetName = eventGrid.Data.JobName + "_" + VideoAnalysisSteps.Encode;
                    await FaceHelper.EncodeToAdaptiveBitrateMP4Set(asset, assetName, ConfigurationManager.AppSettings["AMSPreset"]);

                    log.Info($"request {newReqId} for {reqId} started encode process, send event grid to start redactor process ticks: {DateTime.Now.Ticks}");
                }
                else
                {
                    log.Info($"request {newReqId} for {reqId} didn't start encode no related asset name {eventGrid.Data.AssetName} ticks: {DateTime.Now.Ticks}");
                }
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {newReqId} for {reqId}, ticks: {DateTime.Now.Ticks}", ex);
                result = false;
            }
            string succeed = result ? "" : "unsuccessful";

            log.Info($"Finished {succeed} EncodeProcessing requestId: {newReqId} for {reqId} ticks: {DateTime.Now.Ticks}");
        }
        public static async Task Run([EventGridTrigger] JObject eventGridEvent,
                                     [Blob("{data.url}", FileAccess.Read, Connection = "myblobconn")] Stream incomingThumbnail,
                                     [DocumentDB("YOUR_COSMOS_DB_NAME", "YOUR_STREAN_COLLECTION_NAME", CreateIfNotExists = false, ConnectionStringSetting = "myCosmosDBConnection")] IAsyncCollector <object> outputItem,
                                     TraceWriter log)
        {
            Guid requestID = Guid.NewGuid();

            log.Info($"Start TriggerByStreamThumnail request id: {requestID} ticks: {DateTime.Now.Ticks}");
            string eventdetails = eventGridEvent.ToString();
            bool   result       = true;

            try
            {
                string   url      = eventGridEvent["data"]["url"].ToString();
                string[] splitted = url.Split('/');
                if (splitted.Length > 1)
                {
                    string   name             = splitted[splitted.Length - 1];
                    string   videoname        = splitted[splitted.Length - 2];
                    string[] splittedfilename = videoname.Split('-');
                    if (splittedfilename.Length == 2)
                    {
                        string source = splittedfilename[0];
                        result = await FaceHelper.RunDetect(requestID, ConfigurationManager.AppSettings["apis"], name, source, incomingThumbnail,
                                                            ConfigurationManager.AppSettings["streamsourcecontainername"],
                                                            ConfigurationManager.AppSettings["streamresultcontainername"], outputItem, log, videoname);
                    }
                    else
                    {
                        throw new IncorrectFileName(name);
                    }
                }
                else
                {
                    throw new IncorrectFileName(url);
                }
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {requestID}, ticks: {DateTime.Now.Ticks}", ex);
                result = false;
            }
            string succeed = result ? "" : "unsuccessful";

            log.Info($"Finished {succeed} TriggerByStreamThumnail requestId: {requestID} details: {eventdetails} ticks: {DateTime.Now.Ticks}");
        }
        public static async Task Run([EventGridTrigger] JObject eventGridEvent, TraceWriter log, ExecutionContext executionContext)
        {
            Guid   newReqId = Guid.NewGuid();
            bool   result   = true;
            string reqId    = string.Empty;

            try
            {
                log.Info($"Start CopyFaceProcessing requestId: {newReqId} {eventGridEvent.ToString(Formatting.Indented)} ticks: {DateTime.Now.Ticks}");
                var eventGrid = eventGridEvent.ToObject <Event <VideoAssetData> >();
                reqId = eventGrid.Data.RequestId;
                IAsset asset = FaceHelper.GetAsset(eventGrid.Data.AssetName);
                if (asset != null)
                {
                    Func <string, bool> op = FaceHelper.IsPictureType;
                    if (eventGrid.Data.PrevStep == VideoAnalysisSteps.Subclip)
                    {
                        op = FaceHelper.IsVideoType;
                    }
                    string container  = eventGrid.Data.ContainerName;
                    string sourceConn = ConfigurationManager.AppSettings["myamsconn"];
                    string targetConn = ConfigurationManager.AppSettings["myblobconn"];
                    await FaceHelper.CopyFromAssetToBlob(asset, sourceConn, targetConn, container, eventGrid.Data.VideoName, op);

                    log.Info($"request {newReqId} for {reqId} completed copy process to {container} ticks: {DateTime.Now.Ticks}");
                }
                else
                {
                    log.Info($"request {newReqId} for {reqId} didn't start copy no related asset name {eventGrid.Data.AssetName} ticks: {DateTime.Now.Ticks}");
                }
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {newReqId} for {reqId}, ticks: {DateTime.Now.Ticks}", ex);
                result = false;
            }
            string succeed = result ? "" : "unsuccessful";

            log.Info($"Finished {succeed} CopyFaceProcessing requestId: {newReqId} for {reqId} ticks: {DateTime.Now.Ticks}");
        }
        public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log)
        {
            Guid requestId = Guid.NewGuid();

            log.Info($"Notification webhook started, request {requestId} RequestUri={req.RequestUri}");
            try
            {
                Task <byte[]> taskForRequestBody = req.Content.ReadAsByteArrayAsync();
                byte[]        requestBody        = await taskForRequestBody;

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

                log.Info($"Notification webhook request {requestId} Request Body = {jsonContent}");
                IEnumerable <string> values = null;
                if (req.Headers.TryGetValues("ms-signature", out values))
                {
                    byte[] signingKey          = Convert.FromBase64String(FaceHelper.SigningKey);
                    string signatureFromHeader = values.FirstOrDefault();

                    if (VerifyWebHookRequestSignature(requestBody, signatureFromHeader, signingKey))
                    {
                        string requestMessageContents = Encoding.UTF8.GetString(requestBody);

                        NotificationMessage msg = JsonConvert.DeserializeObject <NotificationMessage>(requestMessageContents);

                        if (VerifyHeaders(req, msg, log))
                        {
                            string newJobStateStr = (string)msg.Properties.Where(j => j.Key == "NewState").FirstOrDefault().Value;
                            if (newJobStateStr == "Finished")
                            {
                                log.Info($"Notification webhook finished for request Id:{requestId}");
                                IJob job = FaceHelper.MediaContext.Jobs.Where(j => j.Id == msg.Properties["JobId"]).FirstOrDefault();
                                if (job != null)
                                {
                                    if (job.OutputMediaAssets.Count > 0)
                                    {
                                        IAsset asset     = job.OutputMediaAssets[job.OutputMediaAssets.Count - 1]; //always we want to take the last output
                                        string strStep   = asset.Name.Substring(asset.Name.LastIndexOf('_') + 1);
                                        string jobName   = asset.Name.Substring(0, asset.Name.LastIndexOf('_'));
                                        string videoname = jobName.Substring(0, jobName.LastIndexOf('_')) + ".mp4"; //TODO fix
                                        string requestid = jobName.Substring(jobName.LastIndexOf('_') + 1);
                                        log.Info($"Notification webhook finished duration: {job.RunningDuration} for request Id:{requestId} details: {strStep} {jobName} {videoname}");
                                        VideoAnalysisSteps step;
                                        if (Enum.TryParse(strStep, out step))
                                        {
                                            HttpClient         client        = FaceHelper.GetHttpClientForVideo(log);
                                            VideoAnalysisSteps nextStep      = VideoAnalysisSteps.Unknown;
                                            string             containerName = string.Empty;
                                            switch (step)
                                            {
                                            case VideoAnalysisSteps.Encode:
                                                nextStep = VideoAnalysisSteps.Redactor;
                                                break;

                                            case VideoAnalysisSteps.Redactor:
                                                containerName = ConfigurationManager.AppSettings["videoresultcontainername"];
                                                nextStep      = VideoAnalysisSteps.Copy;
                                                break;

                                            case VideoAnalysisSteps.LiveRedactor:
                                                containerName = ConfigurationManager.AppSettings["streamresultcontainername"];
                                                nextStep      = VideoAnalysisSteps.Copy;
                                                break;
                                            }
                                            if (nextStep != VideoAnalysisSteps.Unknown)
                                            {
                                                await new SendToEventGrid(log, client).SendVideoData(new VideoAssetData()
                                                {
                                                    RequestId     = requestid,
                                                    AssetName     = asset.Name,
                                                    JobName       = jobName,
                                                    VideoName     = videoname,
                                                    ContainerName = containerName,
                                                    Step          = nextStep,
                                                    PrevStep      = step,
                                                    TimeStamp     = DateTime.UtcNow
                                                });

                                                //copy the subclip video to stream container in case it was set in the setting
                                                if ((step == VideoAnalysisSteps.LiveRedactor) && (ConfigurationManager.AppSettings["copysubclip"] == "1") &&
                                                    (job.OutputMediaAssets.Count > 1))
                                                {
                                                    await new SendToEventGrid(log, client).SendVideoData(new VideoAssetData()
                                                    {
                                                        RequestId     = requestid,
                                                        AssetName     = job.OutputMediaAssets[job.OutputMediaAssets.Count - 2].Name, //assume that the second from the last item is the subclip output
                                                        JobName       = jobName,
                                                        VideoName     = videoname,
                                                        ContainerName = ConfigurationManager.AppSettings["streamsourcecontainername"],
                                                        Step          = VideoAnalysisSteps.Copy,
                                                        PrevStep      = VideoAnalysisSteps.Subclip,
                                                        TimeStamp     = DateTime.UtcNow
                                                    });
                                                }
                                            }
                                            else
                                            {
                                                log.Info($"Notification webhookfor request Id:{requestId} didn't find next step: {nextStep}");
                                            }
                                        }
                                        else
                                        {
                                            log.Info($"Notification webhookfor request Id:{requestId} didn't cast step: {strStep}");
                                        }
                                    }
                                    else
                                    {
                                        log.Info($"Notification webhookfor request Id:{requestId} didn't find output asset for job: {job.Name}");
                                    }
                                }
                                else
                                {
                                    log.Info($"Notification webhookfor request Id:{requestId} didn't find jobid: {msg.Properties["JobId"]}");
                                }
                            }

                            return(req.CreateResponse(HttpStatusCode.OK, string.Empty));
                        }
                        else
                        {
                            log.Info($"Notification webhook for VerifyHeaders request {requestId} failed.");
                            return(req.CreateResponse(HttpStatusCode.BadRequest, "VerifyHeaders failed."));
                        }
                    }
                    else
                    {
                        log.Info($"Notification webhook for VerifyWebHookRequestSignature request {requestId} failed.");
                        return(req.CreateResponse(HttpStatusCode.BadRequest, "VerifyWebHookRequestSignature failed."));
                    }
                }
            }
            catch (Exception ex)
            {
                log.Info($"Notification webhook for request Id:{requestId} failed with exception {ex.Message}");
                return(req.CreateResponse(HttpStatusCode.BadRequest, "Exception Error " + ex.Message));
            }
            log.Info($"Notification webhook for request Id:{requestId} failed");
            return(req.CreateResponse(HttpStatusCode.BadRequest, "Generic Error"));
        }
        public static async Task Run([EventGridTrigger] JObject eventGridEvent,
                                     [Blob("{data.url}", FileAccess.Read, Connection = "myblobconn")] Stream incomingVideo,
                                     TraceWriter log)
        {
            Guid requestID = Guid.NewGuid();

            log.Info($"Start TriggerByVideoUploadFunc request id: {requestID} ticks: {DateTime.Now.Ticks}");
            string eventdetails = eventGridEvent.ToString();
            bool   result       = true;

            try
            {
                string   url  = eventGridEvent["data"]["url"].ToString();
                string   name = url.Substring(url.LastIndexOf('/') + 1);
                string   nameWithoutExtension = name.Substring(0, name.IndexOf('.'));
                string[] splittedfilename     = name.Split('-');
                if (splittedfilename.Length == 2)
                {
                    string jobName   = nameWithoutExtension + "_" + requestID;
                    string assetName = nameWithoutExtension + "_" + requestID + "_" + VideoAnalysisSteps.Upload;
                    log.Info($"started uploaded new asset for {requestID} ticks: {DateTime.Now.Ticks}");
                    IAsset asset = FaceHelper.CreateAssetAndUploadSingleFile(incomingVideo, assetName, AssetCreationOptions.None);
                    log.Info($"completed uploaded asset for {requestID} send event grid to start encode process ticks: {DateTime.Now.Ticks}");
                    HttpClient client = FaceHelper.GetHttpClientForVideo(log);

                    await new SendToEventGrid(log, client).SendVideoData(new VideoAssetData()
                    {
                        RequestId     = requestID.ToString(),
                        ContainerName = string.Empty,
                        AssetName     = asset.Name,
                        JobName       = jobName,
                        VideoName     = name,
                        Step          = VideoAnalysisSteps.Encode,
                        PrevStep      = VideoAnalysisSteps.Upload,
                        TimeStamp     = DateTime.UtcNow
                    });

                    /* API V3 Not working for now  */
                    //ConfigWrapper config = new ConfigWrapper();
                    //IAzureMediaServicesClient client = FaceHelper.CreateMediaServicesClient(config);
                    //client.LongRunningOperationRetryTimeout = 2;
                    //string uniqueness = Guid.NewGuid().ToString().Substring(0, 13);
                    //string jobName = FaceHelper.GenerateJobNameByUnique(nameWithoutExtension, uniqueness);
                    //string jobName = "job-" + uniqueness;
                    //string outputAssetName = "output-" + uniqueness;
                    //string inputAssetName = "input-" + uniqueness;
                    //string adaptiveStreamingTransformName = ConfigurationManager.AppSettings["AdaptiveStreamingTransformName"];
                    //EncoderNamedPreset encodePreset = ConfigurationManager.AppSettings["EncoderPreset"];

                    //log.Info($"init job encode process {requestID} jobName: {jobName} input: {inputAssetName} output: {outputAssetName}  ticks: {DateTime.Now.Ticks}");
                    //Transform transform = FaceHelper.EnsureEncoderTransformExists(client,
                    //    config.ResourceGroup, config.AccountName, adaptiveStreamingTransformName, encodePreset, log);
                    //log.Info($"after get transform for encode process {requestID} jobName: {jobName} ticks: {DateTime.Now.Ticks}");

                    //FaceHelper.CreateInputAsset(client, config.ResourceGroup, config.AccountName, inputAssetName, name, incomingVideo);
                    //log.Info($"after create input asset for encode process {requestID} jobName: {jobName} ticks: {DateTime.Now.Ticks}");
                    //JobInput jobInput = new JobInputAsset(assetName: inputAssetName);
                    //log.Info($"before create output asset for encode process {requestID} jobName: {jobName} ticks: {DateTime.Now.Ticks}");
                    //Asset outputAsset = FaceHelper.CreateOutputAsset(client, config.ResourceGroup, config.AccountName, outputAssetName);
                    //log.Info($"after create output asset for encode process {requestID} jobName: {jobName} input: {inputAssetName} output: {outputAssetName}");
                    //FaceHelper.SubmitJob(client, config.ResourceGroup, config.AccountName,
                    //    adaptiveStreamingTransformName, jobName, jobInput, outputAssetName);
                    //log.Info($"after submit job encode process {requestID} jobName: {jobName} input: {inputAssetName} output: {outputAssetName} ticks: {DateTime.Now.Ticks}");
                }
                else
                {
                    throw new IncorrectFileName(name);
                }
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {requestID}, details: {eventdetails}, ticks: {DateTime.Now.Ticks}", ex);
                result = false;
            }
            string succeed = result ? "" : "unsuccessful";

            log.Info($"Finished {succeed} TriggerByVideoUploadFunc requestId: {requestID} ticks: {DateTime.Now.Ticks}");
        }
Beispiel #7
0
        public static async Task Run([CosmosDBTrigger(
                                          databaseName: "YOUR_COSMOS_DB_NAME",
                                          collectionName: "YOUR_PHOTO_COLLECTION_NAME",
                                          ConnectionStringSetting = "myCosmosDBConnection",
                                          LeaseCollectionName = "leases", CreateLeaseCollectionIfNotExists = true)] IReadOnlyList <Document> documents,
                                     TraceWriter log)
        {
            Guid   requestID    = Guid.NewGuid();
            string strException = string.Empty;

            log.Info($"Processing SaveResultImage request id: {requestID} document count: {documents.Count} ticks: {DateTime.Now.Ticks}");
            try
            {
                BlobManager blobManager = new BlobManager(ConfigurationManager.AppSettings["myblobconn"]);
                if (documents != null && documents.Count > 0)
                {
                    for (int i = 0; i < documents.Count; i++)
                    {
                        var doc = JsonConvert.DeserializeObject <FaceIdentifyResult>(documents[i].ToString());
                        if (doc.DetectResultList.Length > 0)
                        {
                            using (MemoryStream stream = await blobManager.DownloadAsync(doc.ContainerName, doc.BlobName))
                            {
                                for (int j = 0; j < doc.DetectResultList.Length; j++)
                                {
                                    log.Info($"Save new face candidate {requestID} face id: {doc.DetectResultList[j].FaceId} ticks: {DateTime.Now.Ticks}");
                                    string resultBlobName = doc.DetectResultList[j].FaceBlobName;
                                    //TODO : find better way to calc the x,y
                                    int x      = doc.DetectResultList[j].FaceRectangle.Left - 100;
                                    int y      = doc.DetectResultList[j].FaceRectangle.Top - 100;
                                    int width  = (int)Math.Round(doc.DetectResultList[j].FaceRectangle.Width * 2.5);
                                    int height = (int)Math.Round(doc.DetectResultList[j].FaceRectangle.Height * 2.5);

                                    Rectangle sourceRectangle      = new Rectangle(x, y, width, height);
                                    Rectangle destinationRectangle = new Rectangle(0, 0, width, height);

                                    Bitmap croppedImage = new Bitmap(destinationRectangle.Width, destinationRectangle.Height, PixelFormat.Format24bppRgb);
                                    using (Bitmap src = Image.FromStream(stream) as Bitmap)
                                    {
                                        croppedImage.SetResolution(src.HorizontalResolution, src.VerticalResolution);
                                        using (Graphics g = Graphics.FromImage(croppedImage))
                                        {
                                            g.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                                            g.CompositingQuality = CompositingQuality.HighQuality;
                                            g.SmoothingMode      = SmoothingMode.HighQuality;
                                            g.PixelOffsetMode    = PixelOffsetMode.HighQuality;
                                            g.DrawImage(src, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel);
                                            using (var newStream = FaceHelper.ToStream(croppedImage, src.RawFormat))
                                            {
                                                Task t1 = blobManager.UploadAsync(doc.ResultContainerName, resultBlobName, newStream);
                                                t1.Wait();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            log.Info($"SaveResultImage requestId: {requestID} no detection for {doc.BlobName} ticks: {DateTime.Now.Ticks}");
                        }
                    }
                }
                else
                {
                    log.Info($"SaveResultImage  requestId: {requestID} no documents received  ticks: {DateTime.Now.Ticks}");
                }
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {requestID}, ticks: {DateTime.Now.Ticks}", ex);
                strException = "unsuccessfully";
            }
            log.Info($"Finished {strException} SaveResultImage requestId: {requestID} ticks: {DateTime.Now.Ticks}");
        }
        public static ManifestTimingData GetManifestTimingData(IAsset asset, TraceWriter log)
        {
            ManifestTimingData response = new ManifestTimingData()
            {
                IsLive = false, Error = false, TimestampOffset = 0, TimestampList = new List <ulong>()
            };

            try
            {
                ILocator mytemplocator = null;
                Uri      myuri         = FaceHelper.GetValidOnDemandURI(asset);
                if (myuri == null)
                {
                    mytemplocator = CreatedTemporaryOnDemandLocator(asset);
                    myuri         = FaceHelper.GetValidOnDemandURI(asset);
                }
                if (myuri != null)
                {
                    XDocument manifest              = XDocument.Load(myuri.ToString());
                    var       smoothmedia           = manifest.Element("SmoothStreamingMedia");
                    var       videotrack            = smoothmedia.Elements("StreamIndex").Where(a => a.Attribute("Type").Value == "video");
                    string    timescalefrommanifest = smoothmedia.Attribute("TimeScale").Value;
                    if (videotrack.FirstOrDefault().Attribute("TimeScale") != null) // there is timescale value in the video track. Let's take this one.
                    {
                        timescalefrommanifest = videotrack.FirstOrDefault().Attribute("TimeScale").Value;
                    }
                    ulong timescale = ulong.Parse(timescalefrommanifest);
                    response.TimeScale = (ulong?)timescale;
                    if (videotrack.FirstOrDefault().Element("c").Attribute("t") != null)
                    {
                        response.TimestampOffset = ulong.Parse(videotrack.FirstOrDefault().Element("c").Attribute("t").Value);
                    }
                    else
                    {
                        response.TimestampOffset = 0; // no timestamp, so it should be 0
                    }

                    ulong totalduration         = 0;
                    ulong durationpreviouschunk = 0;
                    ulong durationchunk;
                    int   repeatchunk;
                    foreach (var chunk in videotrack.Elements("c"))
                    {
                        durationchunk = chunk.Attribute("d") != null?ulong.Parse(chunk.Attribute("d").Value) : 0;

                        repeatchunk = chunk.Attribute("r") != null?int.Parse(chunk.Attribute("r").Value) : 1;

                        totalduration += durationchunk * (ulong)repeatchunk;
                        if (chunk.Attribute("t") != null)
                        {
                            //totalduration = ulong.Parse(chunk.Attribute("t").Value) - response.TimestampOffset; // new timestamp, perhaps gap in live stream....
                            response.TimestampList.Add(ulong.Parse(chunk.Attribute("t").Value));
                        }
                        else
                        {
                            response.TimestampList.Add(response.TimestampList[response.TimestampList.Count() - 1] + durationpreviouschunk);
                        }

                        for (int i = 1; i < repeatchunk; i++)
                        {
                            response.TimestampList.Add(response.TimestampList[response.TimestampList.Count() - 1] + durationchunk);
                        }

                        durationpreviouschunk = durationchunk;
                    }
                    response.TimestampEndLastChunk = response.TimestampList[response.TimestampList.Count() - 1] + durationpreviouschunk;
                    if (smoothmedia.Attribute("IsLive") != null && smoothmedia.Attribute("IsLive").Value == "TRUE")
                    { // Live asset.... No duration to read (but we can read scaling and compute duration if no gap)
                        response.IsLive        = true;
                        response.AssetDuration = TimeSpan.FromSeconds((double)totalduration / ((double)timescale));
                    }
                    else
                    {
                        totalduration          = ulong.Parse(smoothmedia.Attribute("Duration").Value);
                        response.AssetDuration = TimeSpan.FromSeconds((double)totalduration / ((double)timescale));
                    }
                }
                else
                {
                    response.Error = true;
                }
                if (mytemplocator != null)
                {
                    mytemplocator.Delete();
                }
            }
            catch (Exception)
            {
                response.Error = true;
            }
            return(response);
        }
        public static async Task <bool> RunDetect(Guid requestID, string apis, string name, string source,
                                                  Stream incomingPicture, string sourceContainerName, string resultContainerName, IAsyncCollector <object> outputItem, TraceWriter log, string videoName = null)
        {
            string apikey = string.Empty;

            try
            {
                string[] apiArr    = apis.Split(',');
                int      randomApi = FaceHelper.Instance.Next(0, apiArr.Length);
                apikey = apiArr[randomApi];
                log.Info($"RunDetect request id: {requestID} apiKey: {apikey} ticks: {DateTime.Now.Ticks}");
                Tuple <HttpClient, PolicyWrap <HttpResponseMessage> > tuple = FaceHelper.HttpClientList.GetOrAdd(apikey, new Tuple <HttpClient, PolicyWrap <HttpResponseMessage> >(
                                                                                                                     new HttpClient(),
                                                                                                                     FaceHelper.DefineAndRetrieveResiliencyStrategy(log)));
                HttpClient client = tuple.Item1;
                PolicyWrap <HttpResponseMessage> policy = tuple.Item2;
                IDatabase cache = FaceHelper.Connection.GetDatabase(int.Parse(FaceHelper.Connection.GetDatabase(1).StringGet(apikey)));

                //the large group id it's based on the mac address we get - each MAC address can work with different face api group
                string largegroupid = ConfigurationManager.AppSettings[source];
                if (videoName == null)
                {
                    log.Info($"Detecting {name} requestId: {requestID} apiKey: {apikey} ticks: {DateTime.Now.Ticks}");
                }
                else
                {
                    log.Info($"Detecting thumbnail {name} from {videoName} requestId: {requestID} apiKey: {apikey} ticks: {DateTime.Now.Ticks}");
                }
                byte[] pictureImage;
                // Convert the incoming image stream to a byte array.
                using (var br = new BinaryReader(incomingPicture))
                {
                    pictureImage = br.ReadBytes((int)incomingPicture.Length);
                }
                var detectionResult = await new FaceDetect(log, client).DetectFaces(pictureImage, apikey, requestID, policy);
                if ((detectionResult != null) && (detectionResult.Length > 0))
                {
                    //prepare identify request
                    int    maxCandidate     = int.Parse(ConfigurationManager.AppSettings["maxNumOfCandidatesReturned"]);
                    double threshold        = double.Parse(ConfigurationManager.AppSettings["confidenceThreshold"]);
                    var    identifyResquest = new FaceIdentifyRequest()
                    {
                        ConfidenceThreshold        = threshold,
                        MaxNumOfCandidatesReturned = maxCandidate,
                        LargePersonGroupId         = largegroupid,
                        FaceIds = detectionResult.Select(s => s.FaceId).ToArray()
                    };
                    var identifyResult = await new FaceIdentify(log, client).IdentifyFaces(identifyResquest, apikey, requestID, policy);
                    if ((identifyResult == null) || (identifyResult.Length == 0))
                    {
                        log.Info($"No identification result requestId: {requestID}, apiKey:{apikey} ticks: {DateTime.Now.Ticks}");
                    }
                    var personResult = new PersonDetails(log, client);
                    //merging results and find person name
                    for (int i = 0; i < detectionResult.Length; i++)
                    {
                        if (videoName == null)
                        {
                            detectionResult[i].FaceBlobName = string.Concat(detectionResult[i].FaceId, "_", name);
                        }
                        else
                        {
                            detectionResult[i].FaceBlobName = videoName + "/" + name;
                        }
                        if ((identifyResult != null) && (identifyResult.Length > 0))
                        {
                            detectionResult[i].Candidates = identifyResult[i].Candidates;
                            for (int j = 0; j < detectionResult[i].Candidates.Length; j++)
                            {
                                string personid   = detectionResult[i].Candidates[j].PersonId.ToString();
                                string personName = cache.StringGet(largegroupid + "-" + personid);
                                if (string.IsNullOrEmpty(personName) == true)
                                {
                                    log.Info($"Missing cache requestId: {requestID} apiKey: {apikey} personId: {personid} ticks: {DateTime.Now.Ticks}");
                                    var tPerson = await personResult.GetPersonName(personid, apikey, largegroupid, requestID, policy);

                                    personName = tPerson.Name;
                                    cache.StringSet(largegroupid + "-" + personid, personName, null, When.Always);
                                }
                                detectionResult[i].Candidates[j].PersonName = new InternalPersonDetails()
                                {
                                    PersonId = detectionResult[i].Candidates[j].PersonId,
                                    Name     = personName
                                };
                            }
                        }
                    }
                }
                else
                {
                    log.Info($"No dectection result requestId: {requestID}, apiKey:{apikey} ticks: {DateTime.Now.Ticks}");
                    //in case of video, we want to create a link to the face detected by AMS (Azure Media Services) although face api didn't recognize it
                    if (videoName != null)
                    {
                        detectionResult = new FaceDetectResult[1] {
                            new FaceDetectResult()
                            {
                                FaceBlobName = videoName + "/" + name
                            }
                        }
                    }
                    ;
                }
                string blobname     = videoName ?? name;
                var    actionResult = new FaceIdentifyResult()
                {
                    BlobName            = blobname,
                    ContainerName       = sourceContainerName,
                    ResultContainerName = resultContainerName,
                    BlobLength          = incomingPicture.Length,
                    CreatedDateTime     = DateTime.UtcNow,
                    RequestId           = requestID,
                    ApiKey           = apikey,
                    LargeGroupId     = largegroupid,
                    Source           = source,
                    DetectResultList = detectionResult
                };
                string strResult = JsonConvert.SerializeObject(actionResult);
                await outputItem.AddAsync(strResult);
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {requestID}, apiKey:{apikey} ticks: {DateTime.Now.Ticks}", ex);
                return(false);
            }
            return(true);
        }
        public static HttpClient GetHttpClientForVideo(TraceWriter log)
        {
            Tuple <HttpClient, PolicyWrap <HttpResponseMessage> > tuple = HttpClientList.GetOrAdd("video", new Tuple <HttpClient, PolicyWrap <HttpResponseMessage> >(
                                                                                                      new HttpClient(),
                                                                                                      FaceHelper.DefineAndRetrieveResiliencyStrategy(log)));

            return(tuple.Item1);
        }
Beispiel #11
0
        public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, TraceWriter log)
        {
            Guid requestID = Guid.NewGuid();

            try
            {
                log.Info($"LoadPersonGroup was triggered request id {requestID}");
                string largepersongroupid = req.GetQueryNameValuePairs()
                                            .FirstOrDefault(q => string.Compare(q.Key, "groupid", true) == 0)
                                            .Value;
                if (largepersongroupid == null)
                {
                    // Get request body
                    dynamic data = await req.Content.ReadAsAsync <object>();

                    largepersongroupid = data?.groupid;
                }
                if (largepersongroupid != null)
                {
                    string   apis   = ConfigurationManager.AppSettings["apis"];
                    string[] apiArr = apis.Split(',');
                    if (apiArr.Length > 0)
                    {
                        _loadPersonClient = _loadPersonClient ?? new HttpClient();
                        PolicyWrap <HttpResponseMessage> resilientPolicy = FaceHelper.DefineAndRetrieveResiliencyStrategy(log);
                        int i;
                        //setting the map of api to database in database 1
                        IDatabase cache = Connection.GetDatabase(1);
                        for (i = 1; i <= apiArr.Length; i++)
                        {
                            cache.StringSet(apiArr[i - 1], i + 1);
                        }
                        var personResult = new ListPersonGroup(log, _loadPersonClient);
                        for (i = 1; i <= apiArr.Length; i++)
                        {
                            bool   isComplete = false;
                            string lastPerson = string.Empty;
                            Task <InternalPersonDetails[]> task;
                            List <InternalPersonDetails>   personList = new List <InternalPersonDetails>();
                            cache = Connection.GetDatabase(i + 1);
                            while (!isComplete)
                            {
                                task = personResult.GetListPersonGroup(lastPerson, apiArr[i - 1], largepersongroupid, requestID, resilientPolicy);
                                task.Wait();

                                if (task.Result.Length < 1000)
                                {
                                    isComplete = true;
                                }
                                if (task.Result.Length > 0)
                                {
                                    lastPerson = task.Result[task.Result.Length - 1].PersonId.ToString();
                                    personList.AddRange(task.Result.ToList());
                                }

                                int loop = task.Result.Length / 100;
                                var tmplist = task.Result.ToList();
                                int k = 0, len = 0;
                                for (k = 0; k < loop; k++)
                                {
                                    var tmpinnerlist = tmplist.GetRange(k * 100, 100);
                                    len += tmpinnerlist.Count;
                                    cache.StringSet(tmpinnerlist.Select(s =>
                                                                        new KeyValuePair <RedisKey, RedisValue>(largepersongroupid + "-" + s.PersonId, s.Name)).ToArray(), When.Always);
                                }
                                if (tmplist.Count - len > 0)
                                {
                                    var tmpinnerlist = tmplist.GetRange(k * 100, tmplist.Count - len);
                                    cache.StringSet(tmpinnerlist.Select(s =>
                                                                        new KeyValuePair <RedisKey, RedisValue>(largepersongroupid + "-" + s.PersonId, s.Name)).ToArray(), When.Always);
                                }
                            }
                        }
                        return(req.CreateResponse(HttpStatusCode.OK, "Redis loaded successfully"));
                    }
                    else
                    {
                        string msg = "List of Api setting is empty";
                        log.Error($"Error-LoadPersonGroup: {msg} requestId: {requestID} ticks: {DateTime.Now.Ticks}");
                        return(req.CreateResponse(HttpStatusCode.BadRequest, "List of Api setting is empty"));
                    }
                }
                else
                {
                    string msg = "Please pass a large person group id on the query string or in the request body";
                    log.Error($"Error-LoadPersonGroup: {msg} requestId: {requestID} ticks: {DateTime.Now.Ticks}");
                    return(req.CreateResponse(HttpStatusCode.BadRequest, msg));
                }
            }
            catch (Exception e)
            {
                log.Error($"Exception-LoadPersonGroup: {e.Message} requestId: {requestID} ticks: {DateTime.Now.Ticks}", e);
                return(req.CreateResponse(HttpStatusCode.BadRequest, e.Message));
            }
        }
        public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, TraceWriter log,
                                                           ExecutionContext execContext)
        {
            Guid requestID = Guid.NewGuid();

            log.Info($"Start TriggerLiveStream request id: {requestID} ticks: {DateTime.Now.Ticks}");
            int      lastTableId = 0;
            int      intervalsec = 60;
            TimeSpan starttime   = TimeSpan.FromSeconds(0);

            try
            {
                string triggerStart = DateTime.UtcNow.ToString("o");
                string jsonContent  = await req.Content.ReadAsStringAsync();

                dynamic data = JsonConvert.DeserializeObject(jsonContent);
                log.Info($"TriggerLiveStream request id: {requestID} content: {jsonContent}");
                if (data.channelName == null || data.programName == null)
                {
                    log.Error($"TriggerLiveStream request id: {requestID} no channel name and program name in the input object");
                    return(req.CreateResponse(HttpStatusCode.BadRequest, new
                    {
                        error = "Please pass channel name and program name in the input object (channelName, programName)"
                    }));
                }
                if (data.intervalSec != null)
                {
                    intervalsec = (int)data.intervalSec;
                }
                string restApiEndpoint = ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];

                // find the Channel, Program and Asset
                string channelName = (string)data.channelName;
                var    channel     = FaceHelper.MediaContext.Channels.Where(c => c.Name == channelName).FirstOrDefault();
                if (channel == null)
                {
                    log.Error($"TriggerLiveStream request id: {requestID} channel not found");
                    return(req.CreateResponse(HttpStatusCode.BadRequest, new
                    {
                        error = "Channel not found"
                    }));
                }
                string programName = (string)data.programName;
                var    program     = channel.Programs.Where(p => p.Name == programName).FirstOrDefault();
                if (program == null)
                {
                    log.Error($"TriggerLiveStream request id: {requestID} program not found");
                    return(req.CreateResponse(HttpStatusCode.BadRequest, new
                    {
                        error = "Program not found"
                    }));
                }

                string programState = program.State.ToString();
                string programid    = program.Id;
                var    asset        = FaceHelper.GetAssetFromProgram(programid);
                if (asset == null)
                {
                    log.Info($"TriggerLiveStream Program asset not found for program {programid}");
                    return(req.CreateResponse(HttpStatusCode.BadRequest, new
                    {
                        error = "Program asset not found"
                    }));
                }
                log.Info($"TriggerLiveStream request id: {requestID} using program asset Id : {asset.Id}");
                CloudTable table = FaceHelper.GetCloudTable(ConfigurationManager.AppSettings["myamsconn"], "liveanalytics");
                var        lastendtimeInTable = FaceHelper.RetrieveLastEndTime(table, programid);
                var        assetmanifestdata  = FaceHelper.GetManifestTimingData(asset, log);
                //log.Info($"request id: {requestID} timestamps: " + string.Join(",", assetmanifestdata.TimestampList.Select(n => n.ToString()).ToArray()));
                var livetime = TimeSpan.FromSeconds((double)assetmanifestdata.TimestampEndLastChunk / (double)assetmanifestdata.TimeScale);
                starttime = FaceHelper.ReturnTimeSpanOnGOP(assetmanifestdata, livetime.Subtract(TimeSpan.FromSeconds(intervalsec)));
                log.Info($"TriggerLiveStream request id: {requestID} value starttime: {starttime} livetime: {livetime}");
                if (lastendtimeInTable != null)
                {
                    string lastProgramState        = lastendtimeInTable.ProgramState;
                    var    lastendtimeInTableValue = TimeSpan.Parse(lastendtimeInTable.LastEndTime);
                    lastTableId = int.Parse(lastendtimeInTable.Id);
                    log.Info($"TriggerLiveStream request id: {requestID} value id retrieved: {lastTableId} ProgramState: {lastProgramState} lastendtimeInTable: {lastendtimeInTableValue}");
                    if (lastendtimeInTableValue != null)
                    {
                        var delta = (livetime - lastendtimeInTableValue - TimeSpan.FromSeconds(intervalsec)).Duration();
                        log.Info($"TriggerLiveStream request id: {requestID} delta: {delta}");
                        if (delta < (TimeSpan.FromSeconds(3 * intervalsec))) // less than 3 times the normal duration
                        {
                            starttime = lastendtimeInTableValue;
                            log.Info($"TriggerLiveStream request id: {requestID} value new starttime : {starttime}");
                        }
                    }
                }
                TimeSpan duration = livetime - starttime;
                log.Info($"TriggerLiveStream request id: {requestID} value duration: {duration}");
                string fileName             = channelName + "-" + programName + "_" + requestID + ".mp4";
                string configurationSubclip =
                    File.ReadAllText(Directory.GetParent(execContext.FunctionDirectory).FullName + "\\streamconfig.json").Replace("0:00:00.000000",
                                                                                                                                  starttime.Subtract(TimeSpan.FromMilliseconds(100)).ToString()).Replace("0:00:30.000000", duration.Add(TimeSpan.FromMilliseconds(200)).ToString())
                    .Replace("ArchiveTopBitrate_{Basename}.mp4", fileName);
                string configurationRedactor = File.ReadAllText(Directory.GetParent(execContext.FunctionDirectory).FullName + "\\config.json");

                int priority = 10;
                if (data.priority != null)
                {
                    priority = (int)data.priority;
                }
                string outputAssetSubclip      = fileName + "_" + VideoAnalysisSteps.Subclip;
                string outputAssetLiveRedactor = fileName + "_" + VideoAnalysisSteps.LiveRedactor;
                await FaceHelper.RunSubclippingWithRedactor(asset, fileName, outputAssetSubclip, outputAssetLiveRedactor,
                                                            priority, configurationSubclip, configurationRedactor);

                log.Info($"TriggerLiveStream request id: {requestID} filename: {fileName} job Submitted");
                lastTableId++;
                FaceHelper.UpdateLastEndTime(table, starttime + duration, programid, lastTableId, program.State);
            }
            catch (Exception ex)
            {
                log.Error($"Exception Message: {ex.Message}, requestId: {requestID}, ticks: {DateTime.Now.Ticks}", ex);
                return(req.CreateResponse(HttpStatusCode.BadRequest, "Completed with error sub cliping " + ex.Message));
            }
            return(req.CreateResponse(HttpStatusCode.OK, "Complete OK sub cliping"));
        }
        private async Task <FaceDetectResult[]> MakeFaceDetectRequest(byte[] imageBytes, string apiKey, Guid requestId, PolicyWrap <HttpResponseMessage> policy)
        {
            _log.Info($"Making detect request requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            string strResult = string.Empty;

            FaceDetectResult[] result = null;
            // Request parameters.
            const string requestParameters = "returnFaceId=true&returnFaceLandmarks=false";
            // Get the API URL and the API key from settings.
            var uriBase = ConfigurationManager.AppSettings["faceDetectApiUrl"];

            // Configure the HttpClient request headers.
            _client.DefaultRequestHeaders.Clear();
            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
            //_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            // Assemble the URI for the REST API Call.
            var uri = uriBase + "?" + requestParameters;

            try
            {
                // Execute the REST API call, implementing our resiliency strategy.
                HttpResponseMessage response = await policy.ExecuteAsync(() => _client.PostAsync(uri, FaceHelper.GetImageHttpContent(imageBytes)));

                // Get the JSON response.
                strResult = await response.Content.ReadAsStringAsync();

                result = await response.Content.ReadAsAsync <FaceDetectResult[]>();

                _log.Info($"detect completed: {strResult} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            }
            catch (BrokenCircuitException bce)
            {
                _log.Error($"Could not contact the Face API service due to the following error: {bce.Message} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}", bce);
            }
            catch (Exception e)
            {
                _log.Error($"Critical error-MakeFaceDetectRequest: {e.Message} requestId: {requestId} apiKey:{apiKey} string result:{strResult} ticks: {DateTime.Now.Ticks}", e);
            }

            return(result);
        }
Beispiel #14
0
        private async Task <FaceDetectResult[]> MakeFaceIdentifyRequest(FaceIdentifyRequest req, string apiKey, Guid requestId, PolicyWrap <HttpResponseMessage> policy)
        {
            string        strResult = string.Empty;
            StringBuilder faceids   = new StringBuilder();

            req.FaceIds.ToList().ForEach(s => faceids.Append(s + " "));
            _log.Info($"Making identify request faceids: {faceids} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            FaceDetectResult[] result = null;
            // Get the API URL and the API key from settings.
            var uri = ConfigurationManager.AppSettings["faceIdentifyApiUrl"];

            // Configure the HttpClient request headers.
            _client.DefaultRequestHeaders.Clear();
            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
            //_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            try
            {
                // Execute the REST API call, implementing our resiliency strategy.
                HttpResponseMessage response = await policy.ExecuteAsync(() => _client.PostAsync(uri, FaceHelper.GetIdentifyHttpContent(req)));

                // Get the JSON response.
                strResult = await response.Content.ReadAsStringAsync();

                result = await response.Content.ReadAsAsync <FaceDetectResult[]>();

                _log.Info($"identify completed: {strResult} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            }
            catch (BrokenCircuitException bce)
            {
                _log.Error($"Could not contact the Face API service due to the following error: {bce.Message} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}", bce);
            }
            catch (Exception e)
            {
                _log.Error($"Critical error-MakeFaceIdentifyRequest: {e.Message} requestId: {requestId} apiKey:{apiKey} string result:{strResult} ticks: {DateTime.Now.Ticks}", e);
            }

            return(result);
        }