/// <summary> /// Generates And Submit Frames /// </summary> /// <param name="assetInfo">assetInfo</param> /// <returns>Retruns Review Id</returns> public List <ProcessedFrameDetails> CreateVideoFrames(UploadAssetResult uploadAssetResult) { List <ProcessedFrameDetails> frameEventsList = new List <ProcessedFrameDetails>(); PopulateFrameEvents(uploadAssetResult.ModeratedJson, frameEventsList, uploadAssetResult); return(frameEventsList); }
public async Task <string> CreateVideoReviewInContentModerator(UploadAssetResult uploadAssetResult) { string reviewId = string.Empty; List <ProcessedFrameDetails> frameEntityList = framegenerator.CreateVideoFrames(uploadAssetResult); string path = uploadAssetResult.GenerateVTT == true ? this._amsConfig.FfmpegFramesOutputPath + Path.GetFileNameWithoutExtension(uploadAssetResult.VideoName) + "_aud_SpReco.vtt" : ""; TranscriptScreenTextResult screenTextResult = new TranscriptScreenTextResult(); if (File.Exists(path)) { screenTextResult = await GenerateTextScreenProfanity(reviewId, path, frameEntityList); uploadAssetResult.Category1TextScore = screenTextResult.Category1Score; uploadAssetResult.Category2TextScore = screenTextResult.Category2Score; uploadAssetResult.Category3TextScore = screenTextResult.Category3Score; uploadAssetResult.Category1TextTag = screenTextResult.Category1Tag; uploadAssetResult.Category2TextTag = screenTextResult.Category2Tag; uploadAssetResult.Category3TextTag = screenTextResult.Category3Tag; } var reviewVideoRequestJson = CreateReviewRequestObject(uploadAssetResult, frameEntityList); if (string.IsNullOrWhiteSpace(reviewVideoRequestJson)) { throw new Exception("Video review process failed in CreateVideoReviewInContentModerator"); } var reviewIds = await ExecuteCreateReviewApi(reviewVideoRequestJson); reviewId = reviewIds.FirstOrDefault(); frameEntityList = framegenerator.GenerateFrameImages(frameEntityList, uploadAssetResult, reviewId); await CreateAndPublishReviewInContentModerator(uploadAssetResult, frameEntityList, reviewId, path, screenTextResult); return(reviewId); }
/// <summary> /// /// </summary> /// <param name="uploadVideoRequest"></param> /// <param name="uploadResult"></param> /// <returns></returns> /// public bool CreateAzureMediaServicesJobToModerateVideo(UploadVideoStreamRequest uploadVideoRequest, UploadAssetResult uploadResult) { asset = CreateAsset(uploadVideoRequest); uploadResult.VideoName = uploadVideoRequest.VideoName; // Encoding the asset , Moderating the asset, Generating transcript in parallel IAsset encodedAsset = null; //Creates the job for the tasks. IJob job = this._mediaContext.Jobs.Create("AMS Review Job"); //Adding encoding task to job. ConfigureEncodeAssetTask(uploadVideoRequest.EncodingRequest, job); ConfigureContentModerationTask(job); //adding transcript task to job. if (uploadResult.GenerateVTT) { ConfigureTranscriptTask(job); } var watch = System.Diagnostics.Stopwatch.StartNew(); //submit and execute job. job.Submit(); job.GetExecutionProgressTask(new CancellationTokenSource().Token).Wait(); watch.Stop(); Logger.Log($"AMS Job Elapsed Time: {watch.Elapsed}"); if (job.State == JobState.Error) { throw new Exception("Video moderation has failed due to AMS Job error."); } UploadAssetResult result = uploadResult; encodedAsset = job.OutputMediaAssets[0]; result.ModeratedJson = GetCmDetail(job.OutputMediaAssets[1]); // Check for valid Moderated JSON var jsonModerateObject = JsonConvert.DeserializeObject <VideoModerationResult>(result.ModeratedJson); if (jsonModerateObject == null) { return(false); } if (uploadResult.GenerateVTT) { GenerateTranscript(job.OutputMediaAssets.Last()); } uploadResult.StreamingUrlDetails = PublishAsset(encodedAsset); string downloadUrl = GenerateDownloadUrl(asset, uploadVideoRequest.VideoName); uploadResult.StreamingUrlDetails.DownloadUri = downloadUrl; uploadResult.VideoName = uploadVideoRequest.VideoName; uploadResult.VideoFilePath = uploadVideoRequest.VideoFilePath; return(true); }
public async Task <string> CreateAndPublishReviewInContentModerator(UploadAssetResult assetinfo, List <ProcessedFrameDetails> frameEntityList, string reviewId, string path, TranscriptScreenTextResult screenTextResult) { bool isSuccess = false; bool isTranscript = false; isSuccess = await SubmitAddFramesReview(frameEntityList, reviewId, assetinfo); if (!isSuccess) { Console.WriteLine("Add Frame API call failed."); throw new Exception(); } if (File.Exists(path)) { if (ValidateVtt(path)) { isTranscript = await SubmitTranscript(reviewId, path); } if (isTranscript) { isSuccess = await UploadScreenTextResult(reviewId, JsonConvert.SerializeObject(screenTextResult?.TranscriptProfanity)); if (!isSuccess) { Console.WriteLine("ScreenTextResult API call failed."); throw new Exception(); } } else { Console.WriteLine("Upload vtt failed."); throw new Exception(); } try { File.Delete(path); } catch (Exception e) { Console.WriteLine(e.Message); } } isSuccess = PublishReview(reviewId); if (!isSuccess) { throw new Exception("Publish review failed."); } else { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("\nReview Created Successfully and the review Id {0}", reviewId); } CleanUp(reviewId); return(reviewId); }
/// <summary> /// Populates a Video frame object /// </summary> /// <param name="frameEvent">FrameEventBlobEntity</param> /// <returns>Video Frame Object</returns> private VideoFrame PopulateVideoFrame(ProcessedFrameDetails frameEvent, UploadAssetResult uploadResult) { VideoFrame frameobj = new VideoFrame() { FrameImage = frameEvent.FrameName, Timestamp = Convert.ToString(frameEvent.TimeStamp), ReviewerResultTags = new List <ReviewResultTag>(), Metadata = new List <Metadata>() { new Metadata() { Key = "Review Recommended", Value = frameEvent.ReviewRecommended.ToString() }, new Metadata() { Key = "Adult Score", Value = frameEvent.AdultScore }, new Metadata() { Key = "a", Value = frameEvent.IsAdultContent.ToString() }, new Metadata() { Key = "Racy Score", Value = frameEvent.RacyScore }, new Metadata() { Key = "r", Value = frameEvent.IsRacyContent.ToString() }, new Metadata() { Key = "ExternalId", Value = frameEvent.FrameName }, new Metadata() { Key = "at", Value = frameEvent.IsAdultTextContent.ToString() }, new Metadata() { Key = "rt", Value = frameEvent.IsRacyTextContent.ToString() }, new Metadata() { Key = "ot", Value = frameEvent.IsOffensiveTextContent.ToString() } }, }; return(frameobj); }
private static async Task ProcessVideo(string videoPath) { var watch = System.Diagnostics.Stopwatch.StartNew(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("\nVideo compression process started..."); var compressedVideoPath = amsComponent.CompressVideo(videoPath); if (string.IsNullOrWhiteSpace(compressedVideoPath)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Video Compression failed."); } Console.WriteLine("\nVideo compression process completed..."); UploadVideoStreamRequest uploadVideoStreamRequest = CreateVideoStreamingRequest(compressedVideoPath); UploadAssetResult uploadResult = new UploadAssetResult(); if (generateVtt) { uploadResult.GenerateVTT = generateVtt; } Console.WriteLine("\nVideo moderation process started..."); if (!videoModerator.CreateAzureMediaServicesJobToModerateVideo(uploadVideoStreamRequest, uploadResult)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\nVideo moderation process failed."); } Console.WriteLine("\nVideo moderation process completed..."); Console.WriteLine("\nVideo review process started..."); string reviewId = await videoReviewApi.CreateVideoReviewInContentModerator(uploadResult); watch.Stop(); Console.WriteLine("\nVideo review successfully completed..."); Console.WriteLine("\nTotal Elapsed Time: {0}", watch.Elapsed); Logger.Log("Video File Name: " + Path.GetFileName(videoPath)); Logger.Log($"ReviewId: {reviewId}"); Logger.Log($"Total Elapsed Time: {watch.Elapsed}"); }
/// <summary> /// Creates a review video request object. /// </summary> /// <param name="assetInfo">UploadAssetResult</param> /// <param name="frameEvents">List of FrameEventBlobEntity</param> /// <returns>Reviewvideo</returns> public string CreateReviewRequestObject(UploadAssetResult assetInfo, List <ProcessedFrameDetails> frameEvents) { List <ReviewVideo> reviewList = new List <ReviewVideo>(); ReviewVideo reviewVideoObj = new ReviewVideo(); try { reviewVideoObj.Type = Constants.VideoEntityType; reviewVideoObj.Content = assetInfo.StreamingUrlDetails.SmoothUrl; reviewVideoObj.ContentId = assetInfo.VideoName; reviewVideoObj.CallbackEndpoint = this._amsConfig.ReviewCallBackUrl; reviewVideoObj.Metadata = frameEvents.Count != 0 ? GenerateMetadata(frameEvents, assetInfo) : null; reviewVideoObj.Status = Constants.PublishedStatus; reviewVideoObj.VideoFrames = null; reviewList.Add(reviewVideoObj); return(JsonConvert.SerializeObject(reviewList)); } catch (Exception e) { Console.WriteLine("An exception had occured at {0} ", MethodBase.GetCurrentMethod().Name); Console.WriteLine(e.Message); throw; } }
/// <summary> /// Forms the AddFrames request object. /// </summary> /// <param name="frameEvents">List of Frame events</param> /// <returns>Json representation of video frames collection.</returns> private string CreateAddFramesReviewRequestObject(List <ProcessedFrameDetails> frameEvents, UploadAssetResult uploadResult) { List <VideoFrame> videoFrames = GenerateVideoFrames(frameEvents, uploadResult); return(JsonConvert.SerializeObject(videoFrames)); }
/// <summary> /// Add frames and publishes it. /// </summary> /// <param name="frameEvents">List of Frame Events.</param> /// <param name="reviewId">Reviewid</param> /// <returns>Indicates Add frames operation success result.</returns> public async Task <bool> SubmitAddFramesReview(List <ProcessedFrameDetails> frameEvents, string reviewId, UploadAssetResult uploadResult) { bool isSuccess = true; int batchSize = _amsConfig.FrameBatchSize; var batchFrames = FetchFrameEvents(frameEvents, batchSize); List <string> frameRequest = new List <string>(); foreach (var batchFrame in batchFrames) { frameRequest.Add(CreateAddFramesReviewRequestObject(batchFrame, uploadResult)); } //string inputRequestObj = CreateAddFramesReviewRequestObject(frameEvents, uploadResult); string frameZipPath = $"{this._amsConfig.FfmpegFramesOutputPath}{reviewId}_zip"; DirectoryInfo di = new DirectoryInfo(frameZipPath); FileInfo[] zipFiles = di.GetFiles(); if (frameRequest.Count != zipFiles.Length) { Console.WriteLine("Something went wrong."); throw new Exception(); } for (int i = 0; i < frameRequest.Count; i++) { int retry = 3; bool isComplete = false; HttpResponseMessage response; while (!isComplete && retry > 0) { response = await ExecuteAddFramesReviewApi(reviewId, frameRequest[i], zipFiles[i].FullName); isComplete = response.IsSuccessStatusCode; retry--; if (retry == 0 && !isComplete) { isSuccess = false; } } } return(isSuccess); }
/// <summary> /// /// </summary> /// <param name="frameEvents"></param> /// <returns></returns> private List <Metadata> GenerateMetadata(List <ProcessedFrameDetails> frameEvents, UploadAssetResult uploadResult) { List <Metadata> metadata = new List <Metadata>(); var adultScore = frameEvents.OrderByDescending(a => Double.Parse(a.AdultScore)).FirstOrDefault().AdultScore; var racyScore = frameEvents.OrderByDescending(a => Double.Parse(a.RacyScore)).FirstOrDefault().RacyScore; var isAdult = double.Parse(adultScore) > _amsConfig.AdultFrameThreshold ? true : false; var isRacy = double.Parse(racyScore) > _amsConfig.RacyFrameThreshold ? true : false; var reviewRecommended = frameEvents.Any(frame => frame.ReviewRecommended); metadata = new List <Metadata>() { new Metadata() { Key = "ReviewRecommended", Value = reviewRecommended.ToString() }, new Metadata() { Key = "AdultScore", Value = adultScore }, new Metadata() { Key = "a", Value = isAdult.ToString() }, new Metadata() { Key = "RacyScore", Value = racyScore }, new Metadata() { Key = "r", Value = isRacy.ToString() } }; if (uploadResult.GenerateVTT) { metadata.AddRange(new List <Metadata>() { new Metadata() { Key = "Category1TextScore", Value = uploadResult.Category1TextScore.ToString() }, new Metadata() { Key = "at", Value = uploadResult.Category1TextTag.ToString() }, new Metadata() { Key = "Category2TextScore", Value = uploadResult.Category2TextScore.ToString() }, new Metadata() { Key = "rt", Value = uploadResult.Category2TextTag.ToString() }, new Metadata() { Key = "Category3TextScore", Value = uploadResult.Category3TextScore.ToString() }, new Metadata() { Key = "ot", Value = uploadResult.Category3TextTag.ToString() } }); } return(metadata); }
/// <summary> /// Geneartes Video Frames /// </summary> /// <param name="frameEvents">List of FrameEventBlobEntity</param> /// <returns>List of Video frames</returns> private List <VideoFrame> GenerateVideoFrames(List <ProcessedFrameDetails> frameEvents, UploadAssetResult uploadResult) { List <VideoFrame> videoFrames = new List <VideoFrame>(); foreach (ProcessedFrameDetails frameEvent in frameEvents) { VideoFrame videoFrameObj = PopulateVideoFrame(frameEvent, uploadResult); videoFrames.Add(videoFrameObj); } return(videoFrames); }
/// <summary> /// GetGeneratedFrameList method used for Generating Frames using Moderated Json /// </summary> /// <param name="eventsList">resultDownloaddetailsList</param> /// <param name="assetInfo"></param> public List <ProcessedFrameDetails> GenerateFrameImages(List <ProcessedFrameDetails> eventsList, UploadAssetResult assetInfo, string reviewId) { string frameStorageLocalPath = this._amsConfig.FfmpegFramesOutputPath + reviewId; Directory.CreateDirectory(frameStorageLocalPath); int batchSize = _amsConfig.FrameBatchSize; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("\nVideo Frames Creation inprogress..."); var watch = System.Diagnostics.Stopwatch.StartNew(); string ffmpegBlobUrl = string.Empty; if (File.Exists(_amsConfig.FfmpegExecutablePath)) { ffmpegBlobUrl = _amsConfig.FfmpegExecutablePath; } List <string> args = new List <string>(); StringBuilder sb = new StringBuilder(); int frameCounter = 0; int frameProcessedCount = 0; int segmentCount = 0; string dirPath = string.Empty; foreach (var frame in eventsList) { if (frameProcessedCount % batchSize == 0) { segmentCount = frameProcessedCount / batchSize; dirPath = $"{frameStorageLocalPath}\\{segmentCount}"; if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } } frameProcessedCount++; frame.FrameName = reviewId + frame.FrameName; TimeSpan ts = TimeSpan.FromMilliseconds(Convert.ToDouble(frame.TimeStamp)); var line = "-ss " + ts + " -i \"" + assetInfo.VideoFilePath + "\" -map " + frameCounter + ":v -frames:v 1 -vf scale=320:-1 \"" + dirPath + "\\" + frame.FrameName + "\" "; frameCounter++; sb.Append(line); if (sb.Length > 30000) { args.Add(sb.ToString()); sb.Clear(); frameCounter = 0; } } if (sb.Length != 0) { args.Add(sb.ToString()); } Parallel.ForEach(args, new ParallelOptions { MaxDegreeOfParallelism = 4 }, arg => CreateTaskProcess(arg, ffmpegBlobUrl)); watch.Stop(); Logger.Log($"Frame Creation Elapsed time: {watch.Elapsed}"); Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("Frames(" + eventsList.Count() + ") created successfully."); DirectoryInfo[] diArr = new DirectoryInfo(frameStorageLocalPath).GetDirectories(); Directory.CreateDirectory(frameStorageLocalPath + @"_zip"); foreach (var dir in diArr) { ZipFile.CreateFromDirectory(dir.FullName, frameStorageLocalPath + $"_zip\\{dir.Name}.zip"); } return(eventsList); }
/// <summary> /// Generates frames based on moderated json source. /// </summary> /// <param name="moderatedJsonstring">moderatedJsonstring</param> /// <param name="resultEventDetailsList">resultEventDetailsList</param> private void PopulateFrameEvents(string moderatedJsonstring, List <ProcessedFrameDetails> resultEventDetailsList, UploadAssetResult uploadResult) { var jsonModerateObject = JsonConvert.DeserializeObject <VideoModerationResult>(moderatedJsonstring); if (jsonModerateObject != null) { var timeScale = Convert.ToInt32(jsonModerateObject.TimeScale); int frameCount = 0; foreach (var item in jsonModerateObject.Fragments) { if (item.Events != null) { foreach (var frameEventDetailList in item.Events) { foreach (FrameEventDetails frameEventDetails in frameEventDetailList) { var eventDetailsObj = new ProcessedFrameDetails { ReviewRecommended = frameEventDetails.ReviewRecommended, TimeStamp = (frameEventDetails.TimeStamp * 1000 / timeScale), IsAdultContent = double.Parse(frameEventDetails.AdultScore) > _amsConfig.AdultFrameThreshold ? true : false, AdultScore = frameEventDetails.AdultScore, IsRacyContent = double.Parse(frameEventDetails.RacyScore) > _amsConfig.RacyFrameThreshold ? true : false, RacyScore = frameEventDetails.RacyScore, TimeScale = timeScale, }; frameCount++; eventDetailsObj.FrameName = "_" + frameCount + ".jpg"; resultEventDetailsList.Add(eventDetailsObj); } } } } } }