Beispiel #1
0
        private static async Task StoreFacesAsync(Face f, VideoBreakdown poco, VideoIndexerHelper videoIndexerHelper)
        {
            var faceStream = await DownloadWebResource(f.thumbnailFullUrl);

            var blob = await UploadFileToBlobStorage(faceStream, $"{poco.id}/faces/{f.shortId}.jpg", "image/jpg", videoIndexerHelper);

            f.thumbnailFullUrl = blob.Uri.ToString();
        }
Beispiel #2
0
        public static async Task RunAsync(
            [QueueTrigger("%EncodingCompleteQueue%", Connection = "AzureWebJobsStorage")] string myQueueItem, TraceWriter log)
        {
            var videoIndexerHelper = new VideoIndexerHelper(log);
            var cosmosHelper       = new CosmosHelper(log);
            var msg = JsonConvert.DeserializeObject <NotificationMessage>(myQueueItem);

            if (msg.EventType != NotificationEventType.TaskStateChange)
            {
                return; // ignore anything but job complete
            }
            var newJobStateStr = msg.Properties.FirstOrDefault(j => j.Key == Constants.NEWSTATE).Value;

            if (newJobStateStr == Enums.StateEnum.Finished.ToString())
            {
                var jobId  = msg.Properties["JobId"];
                var taskId = msg.Properties["TaskId"];

                _context = MediaServicesHelper.Context;

                var job = _context.Jobs.Where(j => j.Id == jobId).FirstOrDefault();
                if (job == null)
                {
                    videoIndexerHelper.LogMessage($"Job for JobId:{jobId} is null");
                    return;
                }
                var task = job.Tasks.Where(l => l.Id == taskId).FirstOrDefault();
                if (task == null)
                {
                    videoIndexerHelper.LogMessage($"Task for taskId:{taskId} is null");
                    return;
                }
                var outputAsset = task.OutputAssets[0];
                var inputAsset  = task.InputAssets[0];


                cosmosHelper.LogMessage("Read policy");
                var readPolicy =
                    _context.AccessPolicies.Create("readPolicy", TimeSpan.FromHours(4), AccessPermissions.Read);
                var outputLocator = _context.Locators.CreateLocator(LocatorType.Sas, outputAsset, readPolicy);
                cosmosHelper.LogMessage("Create cloud blob client");
                var destBlobStorage = BlobHelper.AmsStorageAccount.CreateCloudBlobClient();
                cosmosHelper.LogMessage("get asset container");
                // Get the asset container reference
                var outContainerName = new Uri(outputLocator.Path).Segments[1];
                var outContainer     = destBlobStorage.GetContainerReference(outContainerName);
                cosmosHelper.LogMessage("use largest single mp4 ");
                // use largest single mp4 output (highest bitrate) to send to Video Indexer
                var biggestblob = outContainer.ListBlobs().OfType <CloudBlockBlob>()
                                  .Where(b => b.Name.ToLower().EndsWith(".mp4"))
                                  .OrderBy(u => u.Properties.Length).Last();
                cosmosHelper.LogMessage("GetSasUrl");
                var sas = videoIndexerHelper.GetSasUrl(biggestblob);
                cosmosHelper.LogMessage(" submit to VI ");
                // Submit processing job to Video Indexer
                await videoIndexerHelper.SubmitToVideoIndexerAsync(biggestblob.Name, sas, inputAsset.AlternateId, log);
            }
        }
Beispiel #3
0
        private static async Task GetCaptionsVttAsync(string id, VideoBreakdown videoBreakdownPoco, string language, VideoIndexerHelper videoIndexerHelper)
        {
            var client      = videoIndexerHelper.GetVideoIndexerHttpClient();
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            // Request parameters
            queryString["language"] = language;
            var uri = $"https://videobreakdown.azure-api.net/Breakdowns/Api/Partner/Breakdowns/{id}/VttUrl?" +
                      queryString;

            // this returns a url to the captions file
            var response = await client.GetAsync(uri);

            var vttUrl =
                response.Content.ReadAsStringAsync().Result
                .Replace("\"", "");     // seems like the url is always wrapped in quotes

            // download actual vtt file and store in blob storage
            var vttStream = await DownloadWebResource(vttUrl);

            await UploadFileToBlobStorage(vttStream, $"{videoBreakdownPoco.id}/{language}.vtt", "text/plain", videoIndexerHelper);

            //TODO: put reference to vtt in breakdown?
        }
Beispiel #4
0
        public static async Task RunAsync(
            [QueueTrigger("%VIProcessingCompleteQueue%", Connection = "AzureWebJobsStorage")] CloudQueueMessage myQueueItem,
            TraceWriter log)
        {
            var videoIndexerHelper = new VideoIndexerHelper(log);
            var cosmosHelper       = new CosmosHelper(log);

            var queueContents = myQueueItem.AsString;

            // queue item should be id & state
            var completionData = JsonConvert.DeserializeObject <Dictionary <string, string> >(queueContents);

            // ignore if not proper state
            if (completionData["state"] != "Processed")
            {
                return;
            }

            var videoIndexerVideoId = completionData["id"];

            var apiUrl = videoIndexerHelper.VideoIndexerApiUrl;
            var client = videoIndexerHelper.GetVideoIndexerHttpClient();

            var uri = string.Format(apiUrl + "/{0}", videoIndexerVideoId);

            videoIndexerHelper.LogMessage($" call VI with uri{uri}");
            var response = await client.GetAsync(uri);

            var json = await response.Content.ReadAsStringAsync();

            videoIndexerHelper.LogMessage($"get state with id: {videoIndexerVideoId}");
            var state = cosmosHelper.GetManifestStateRecordByVideoId(videoIndexerVideoId, log);

            videoIndexerHelper.LogMessage("create poco from json ");
            var videoBreakdownPoco = JsonConvert.DeserializeObject <VideoBreakdown>(json);



            var taskList = new List <Task>();


            // these tasks are network io dependant and can happen in parallel
            //TODO:  setup default languages to be pulled from app settings, but
            //TODO: the languages set in config would override
            //TODO: validate languages
            videoIndexerHelper.LogMessage("Process transcripts");
            if (state.Transcripts != null)
            {
                taskList = state.Transcripts
                           .Select(language => GetCaptionsVttAsync(videoIndexerVideoId, videoBreakdownPoco, language, videoIndexerHelper))
                           .ToList();
            }
            videoIndexerHelper.LogMessage("start task extract images");
            taskList.Add(ExtractImages(videoBreakdownPoco, log, videoIndexerHelper));
            //var englishCaptionsTask = GetCaptionsVttAsync(videoIndexerVideoId, videoBreakdownPoco, "English");
            //var japaneseCaptionsTask = GetCaptionsVttAsync(videoIndexerVideoId, videoBreakdownPoco, "Japanese");
            //var imagesTask = ExtractImages(videoBreakdownPoco);
            videoIndexerHelper.LogMessage($"wait for tasks to finish");
            await Task.WhenAll(taskList.ToArray());

            videoIndexerHelper.LogMessage($"store in json breakdowns");
            // we wait to store breakdown json because it's modified in previous tasks
            var storeTask1 = StoreBreakdownJsonInCosmos(videoBreakdownPoco, log);

            videoIndexerHelper.LogMessage($"update processing ");
            var storeTask2 = cosmosHelper.UpdateProcessingStateAsync(completionData["id"]);

            videoIndexerHelper.LogMessage($"wait for  store tasks to finish");
            await Task.WhenAll(storeTask1, storeTask2);
        }
Beispiel #5
0
        private static async Task <CloudBlockBlob> UploadFileToBlobStorage(MemoryStream blobContents, string blobName,
                                                                           string contentType, VideoIndexerHelper videoIndexerHelper)
        {
            var resourcesContainer = videoIndexerHelper.VideoIndexerResourcesContainer;
            var newBlob            = resourcesContainer.GetBlockBlobReference(blobName);

            newBlob.Properties.ContentType = contentType;
            await newBlob.UploadFromStreamAsync(blobContents);

            return(newBlob);
        }
Beispiel #6
0
        /// <summary>
        ///     Store the images referenced in the breakdown and update their location in the JSON prior to
        ///     storing in the database.
        /// </summary>
        /// <param name="poco"></param>
        /// <param name="videoIndexerHelper"></param>
        /// <returns></returns>
        private static async Task ExtractImages(VideoBreakdown poco, TraceWriter log, VideoIndexerHelper videoIndexerHelper)
        {
            var baseHelper = new BaseHelper(log);

            baseHelper.LogMessage($"start task extract images");
            // download thumbnail and store in blob storage

            var memSreamOfResource = await DownloadWebResource(poco.summarizedInsights.thumbnailUrl);

            var newBlob = await UploadFileToBlobStorage(memSreamOfResource, $"{poco.id}/video-thumbnail.jpg",
                                                        "image/jpg", videoIndexerHelper);

            string newImageUrl = newBlob.Uri.AbsoluteUri;

            // replace urls in breakdown
            poco.summarizedInsights.thumbnailUrl = newImageUrl;
            poco.breakdowns[0].thumbnailUrl      = newImageUrl;
            baseHelper.LogMessage($"wait for task extract images to finish");
            await Task.WhenAll(poco.summarizedInsights.faces.Select(f => StoreFacesAsync(f, poco, videoIndexerHelper)));
        }