Example #1
0
        public static string DownloadVideo(string videoUrl)
        {
            string path = GetLocalPath(videoUrl);

            if (File.Exists(path))
            {
                Logger.Log("File already exists.");
            }
            else
            {
                Logger.Log("Requesting video: " + videoUrl + " ...");

                string directory = Path.GetDirectoryName(path);
                if (directory != String.Empty && !Directory.Exists(directory))
                {
                    // Edge case! Ensure a file doesn't also exist already with that name.
                    if (File.Exists(directory))
                    {
                        const string prefix = "_tmp_";
                        directory = prefix + directory;
                        path      = prefix + path;
                    }
                    Directory.CreateDirectory(directory);
                }

                WebClient client = new WebClient();
                client.DownloadFile(videoUrl, path);
            }

            Logger.Log("File is here: " + path);
            return(path);
        }
Example #2
0
        public Guid?GetSkierTagId(SkiVideoEntity video)
        {
            try
            {
                if (string.IsNullOrEmpty(video.Skier))
                {
                    return(null);
                }

                string skier = video.Skier.Trim();

                var tag = m_tags.Where(t => t.Name == skier).FirstOrDefault();
                if (tag == null)
                {
                    if (HasEnoughOfSkier(skier))
                    {
                        tag = m_trainingApi.CreateTag(m_projectId, skier);
                        m_tags.Add(tag);
                    }
                }

                return(tag.Id);
            }
            catch (Exception e)
            {
                Logger.Log($"Unable to get SkierTag for {video.Skier}\n" + e);
                return(null);
            }
        }
Example #3
0
        private async Task GetCreationTimeAsync()
        {
            Logger.Log($"Getting creation time from video {_sourceVideoUrl}...");
            _creationTime = await _videoTasks.GetCreationTimeAsync();

            Logger.Log($"Creation time is {_creationTime}");
        }
Example #4
0
        private CoursePass CreatePass(List<Measurement> measurements)
        {
            if (this.m_course == null)
                FindCourse(measurements);
            
            if (this.m_course == null)
            {
                Logger.Log("Unable to find a course for this ski run.");       
                return null;
            }

            if (m_rope == null)
                m_rope = Rope.Default;

            CoursePass pass = new CoursePass(m_course, m_rope, CenterLineDegreeOffset);
            for (int i = 0; i < measurements.Count; i++)
            {
                Measurement current = measurements[i];
                current.BoatPosition = pass.CoursePositionFromGeo(current.BoatGeoCoordinate);               
                if (current.BoatPosition == CoursePosition.Empty)
                    continue;               
                
                CalculateInCourse(pass, measurements, i);
                CalculateCurrent(measurements, i);
                pass.Track(current);

                // If the handle has passed the 55s, we're done here.
                if (current.HandlePosition.Y > Course.LengthM)
                    break;
            }
            
            CalculateCoursePassSpeed(pass);
            return pass;
        }
Example #5
0
        /// <summary>
        /// Returns prediction or null if an error occurs.
        /// </summary>
        public virtual string Predict(string thumbnailUrl)
        {
            Logger.Log($"Making a prediction of {CustomVisionModelName} for: " + thumbnailUrl);

            predictionApi = new CustomVisionPredictionClient()
            {
                ApiKey   = CustomVisionKey,
                Endpoint = CustomVisionEndPoint
            };

            try
            {
                PredictionModels.ImageUrl thumbnail = new PredictionModels.ImageUrl(CropThumbnailUrl + thumbnailUrl);
                var result = predictionApi.ClassifyImageUrl(ProjectId, CustomVisionModelName, thumbnail);

                //LogPredicitions(result.Predictions);

                return(GetHighestRankedPrediction(result.Predictions));
            }
            catch (PredictionModels.CustomVisionErrorException e)
            {
                Logger.Log($"Error making prediction for {thumbnailUrl}\n\t" +
                           e.Response.Content, e);
                return(null);
            }
        }
Example #6
0
        private Task <string> TrimAndSilenceAsync(CoursePass pass)
        {
            Logger.Log($"Trimming and silencing video {_sourceVideoUrl}...");

            double start = 0, duration = 0, total = 0;

            if (_timeOverrides != null)
            {
                start    = _timeOverrides.Start;
                duration = _timeOverrides.Duration;
                total    = start + duration;
            }
            else
            {
                if (pass == null)
                {
                    throw new ApplicationException(
                              "CoursePass was not found and no pass overrides were available for " +
                              $"{_sourceVideoUrl}");
                }

                start    = pass.GetSecondsAtEntry();
                duration = pass.GetDurationSeconds();
                total    = pass.GetTotalSeconds();
            }

            return(_videoTasks.TrimAndSilenceVideoAsync(start, duration, total));
        }
Example #7
0
        private static string CreateImage(string jsonPath, double clOffset, double rope,
                                          CourseCoordinates coords)
        {
            CoursePass        pass;
            CoursePassFactory factory = new CoursePassFactory();

            factory.CenterLineDegreeOffset = clOffset;
            factory.RopeLengthOff          = rope;
            factory.Course55Coordinates    = coords;

            if (jsonPath.StartsWith("http"))
            {
                pass = factory.FromUrl(jsonPath);
            }
            else
            {
                pass = factory.FromFile(jsonPath);
            }

            if (pass == null)
            {
                throw new ApplicationException($"Unable to create a pass for {jsonPath}");
            }

            string          imagePath = GetImagePath(jsonPath);
            CoursePassImage image     = new CoursePassImage(pass);
            Bitmap          bitmap    = image.Draw();

            bitmap.Save(imagePath, ImageFormat.Png);

            Logger.Log(string.Format("Gate precision == {0} for {1}", pass.GetGatePrecision(), jsonPath));
            Logger.Log("Wrote image to: " + imagePath);

            return(imagePath);
        }
Example #8
0
        /// <summary>
        /// Listens to service bus queue and processes videos as they arrive.
        /// </summary>
        private static void Listen(string queueName, bool openDeadLetter)
        {
            VideoUploadListener listener = new VideoUploadListener(queueName, openDeadLetter);
            EventWaitHandle     ewh      = new EventWaitHandle(false, EventResetMode.ManualReset);
            EventHandler        Reset    = (o, e) => {
                listener.Stop();
                ewh.Set();
            };

            AppDomain.CurrentDomain.ProcessExit += Reset;
            listener.Completed += Reset;  // Force to only listen for 1 message, then exit.
            listener.Start();

            if (Console.WindowHeight > 0)
            {
                Logger.Log("Press any key to cancel.");
                Console.ReadKey();
                ewh.Set();
            }
            else
            {
                Logger.Log("Waiting until signaled to close.");
            }

            // Wait until signalled.
            ewh.WaitOne();

            Logger.Log($"Done listening for events.");
            AppDomain.CurrentDomain.ProcessExit -= Reset;
        }
Example #9
0
 private void OnProgress(object sender, ConversionProgressEventArgs e)
 {
     // Grab every 10th progress update.
     if (e.Frame % 10 == 0)
     {
         Logger.Log($"{_localVideoPath} -- Processed frame {e.Frame} @{e.ProcessedDuration}");
     }
 }
Example #10
0
        public void AddMetadata(SkiVideoEntity entity, string json)
        {
            string blobName = GetBlobName(entity.Url, entity.RecordedTime);
            string jsonUrl  = UploadMeasurements(blobName, json);

            entity.JsonUrl = jsonUrl;
            AddTableEntity(entity);
            Logger.Log("Uploaded metadata for video:" + entity.Url);
        }
Example #11
0
        private async Task ExtractMetadataAsync()
        {
            Logger.Log($"Extracting metadata from video {_sourceVideoUrl}...");
            await Task.Run(() => {
                _json = MetadataExtractor.Extract.ExtractMetadata(_localVideoPath);
            });

            Logger.Log("Extracted metadata.");
        }
Example #12
0
        private static async Task DeleteGoogleVideoAsync(GoogleStorage gstore, Storage storage, SkiVideoEntity video)
        {
            Logger.Log($"Deleting {video.HotUrl} recorded @ {video.RecordedTime}.");
            await gstore.DeleteAsync(video.HotUrl);

            video.HotUrl = "";
            storage.UpdateMetadata(video);
            Logger.Log($"Metadata updated for video recorded @ {video.RecordedTime}.");
        }
Example #13
0
        public Task NotifyAsync(string skier, string video)
        {
            Logger.Log($"Notifying of {video}");
            string value = Newtonsoft.Json.JsonConvert.SerializeObject(
                new { Skier = skier, Video = video }
                );

            byte[] bytes = Encoding.ASCII.GetBytes(value);
            return(_queueClient.SendAsync(new Message(bytes)));
        }
Example #14
0
        private async Task <string> DownloadVideoAsync()
        {
            string localPath = null;
            await Task.Run(() => {
                Logger.Log($"Downloading video {_sourceVideoUrl}...");
                localPath = Cloud.Storage.DownloadVideo(_sourceVideoUrl);
            });

            return(localPath);
        }
Example #15
0
        private async Task <string> RemoveAudioAsync(string inputFile)
        {
            string outputFile = AppendToFileName(inputFile, "s");
            string parameters = $"-i {inputFile} -c copy -an {outputFile}";
            await _ffmpeg.ExecuteAsync(parameters);

            Logger.Log($"Removed Audio: {outputFile}");

            return(outputFile);
        }
Example #16
0
        async Task ProcessMessagesAsync(Message message, CancellationToken token)
        {
            if (_queueClient.IsClosedOrClosing)
            {
                Logger.Log("Queue is closing, abandoning message.");
                await _queueClient.AbandonAsync(message.SystemProperties.LockToken);

                return;
            }

            string videoUrl = "";

            try
            {
                // Process the message.
                Logger.Log($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");

                string json = Encoding.UTF8.GetString(message.Body);
                videoUrl = QueueMessageParser.GetUrl(json);
                Logger.Log($"Received this videoUrl: {videoUrl}");

                if (videoUrl.EndsWith("test.MP4"))
                {
                    throw new ApplicationException("Something broke, fail safe for testing exceptions!");
                }

                SkiVideoProcessor processor = new SkiVideoProcessor(videoUrl);
                await processor.ProcessAsync();

                await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
            }
            catch (Exception e)
            {
                if (message.SystemProperties.DeliveryCount <= 2)
                {
                    Logger.Log($"Abandoned message.", e);
                    // abandon and allow another to try in case of transient errors
                    await _queueClient.AbandonAsync(message.SystemProperties.LockToken);
                }
                else
                {
                    Logger.Log($"Dead lettering message.", e);
                    await _queueClient.DeadLetterAsync(message.SystemProperties.LockToken,
                                                       e.Message, e.InnerException?.Message);
                }
            }
            finally
            {
                Logger.Log($"Message handler completed for {videoUrl}.");
                if (Completed != null)
                {
                    Completed(this, null);
                }
            }
        }
Example #17
0
 /// <summary>
 /// This is just a way to review and drain the deadletter queue.
 /// </summary>
 void ReadDeadLetter()
 {
     _queueClient.RegisterMessageHandler((message, cancel) => {
         Logger.Log($"Dead letter message: {Encoding.UTF8.GetString(message.Body)}");
         Logger.Log($"Reason: {message.UserProperties["DeadLetterReason"]}");
         return(Task.CompletedTask);
     }, new MessageHandlerOptions(ExceptionReceivedHandler)
     {
         AutoComplete = true
     });
 }
Example #18
0
//TODO: Consolidate these two storage upload methods.
        private async Task <string> UploadVideoAsync(Task <string> trimAndSilence, Task getCreationTime)
        {
            await  getCreationTime; // Ensure creation time has been generated.
            string processedVideoPath = await trimAndSilence;

            Logger.Log($"Uploading video {processedVideoPath}...");
            string videoUrl = _storage.UploadVideo(processedVideoPath, _creationTime);

            Logger.Log($"Video uploaded to {videoUrl}");
            return(videoUrl);
        }
Example #19
0
        private async Task <string> UploadThumbnailAsync(Task <string> createThumbnail, Task getCreationTime)
        {
            await  getCreationTime; // Ensure creation time has been generated.
            string localThumbnailPath = await createThumbnail;

            Logger.Log($"Uploading thumbnail {localThumbnailPath}...");
            string thumbnailUrl = _storage.UploadThumbnail(localThumbnailPath, _creationTime);

            Logger.Log($"Uploaded thumbnail to {thumbnailUrl}");

            return(thumbnailUrl);
        }
Example #20
0
        public VideoProcessedNotifier(string queueName = DefaultQueueName)
        {
            string serviceBusConnectionString = Environment.GetEnvironmentVariable(ENV_SERVICEBUS);

            if (string.IsNullOrWhiteSpace(serviceBusConnectionString))
            {
                throw new ApplicationException($"Missing service bus connection string in env variable: {ENV_SERVICEBUS}");
            }

            _queueClient = new QueueClient(serviceBusConnectionString, queueName);
            Logger.Log($"Connected to queue {queueName}");
        }
Example #21
0
        private void LogPredicitions(IList <PredictionModels.PredictionModel> predictions)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.AppendLine();

            foreach (var c in predictions)
            {
                sb.Append($"\t{c.TagName}: {c.Probability:P1}\n");
            }

            Logger.Log(sb.ToString());
        }
Example #22
0
 private void SendBatch()
 {
     try
     {
         Logger.Log($"Sending batch of {entries.Count} urls to train.");
         var batch = new TrainingModels.ImageUrlCreateBatch(entries);
         trainingApi.CreateImagesFromUrls(ProjectId, batch);
     }
     catch (Exception e)
     {
         Logger.Log("Error writing ML training batch.", e);
     }
 }
Example #23
0
 public void Start()
 {
     if (_deadLetterMode)
     {
         Logger.Log($"Reading dead letter messages...");
         ReadDeadLetter();
     }
     else
     {
         RegisterOnMessageHandlerAndReceiveMessages();
         Logger.Log($"Listening for messages...");
     }
 }
Example #24
0
        public void UpdateCourse(Course course)
        {
            const string coursePartitionKey = "cochituate";

            if (course == null)
            {
                throw new ApplicationException("You must pass a course object to update.");
            }

            CloudTableClient client = _account.CreateCloudTableClient();
            CloudTable       table  = client.GetTableReference(COURSETABLE);

            // Get existing entity, if one exists.
            TableQuery <CourseEntity> query = new TableQuery <CourseEntity>()
                                              .Where($"PartitionKey eq '{coursePartitionKey}' and RowKey eq '{course.Name}'");
            var result = table.ExecuteQuerySegmentedAsync(query, null);

            result.Wait();
            CourseEntity entity = result.Result.FirstOrDefault();

            if (entity != null)
            {
                entity.FriendlyName    = course.FriendlyName;
                entity.Course55EntryCL = course.Course55EntryCL;
                entity.Course55ExitCL  = course.Course55ExitCL;
            }
            else
            {
                entity = new CourseEntity();
                entity.FriendlyName    = course.FriendlyName;
                entity.PartitionKey    = coursePartitionKey;
                entity.RowKey          = course.Name;
                entity.Course55EntryCL = course.Course55EntryCL;
                entity.Course55ExitCL  = course.Course55ExitCL;
            }

            TableOperation insert     = TableOperation.InsertOrReplace(entity);
            Task           createTask = table.CreateIfNotExistsAsync();

            createTask.Wait();
            Task insertTask = table.ExecuteAsync(insert);

            insertTask.Wait();

            Logger.Log($"Inserted course: {entity.RowKey}");
        }
Example #25
0
        private static async Task UpdateThumbnailAsync(Storage storage, SkiVideoEntity video)
        {
            Logger.Log($"Updating thumbnail for {video.PartitionKey}, {video.RowKey}");
            double thumbnailAtSeconds = 0; // video.EntryTime;

            string     localVideoPath = Storage.DownloadVideo(video.HotUrl ?? video.Url);
            VideoTasks _videoTasks    = new VideoTasks(localVideoPath);

            string localThumbnailPath = await _videoTasks.GetThumbnailAsync(thumbnailAtSeconds);

            string modifiedThumbnailPath = localThumbnailPath.Replace("_ts.PNG", ".PNG");

            System.IO.File.Move(localThumbnailPath, modifiedThumbnailPath);
            string thumbnailUrl = storage.UploadThumbnail(modifiedThumbnailPath, video.RecordedTime);

            Logger.Log($"New thumbnail at {thumbnailUrl}");
        }
Example #26
0
        private static async Task UpdateThumbnailsAsync()
        {
            Storage storage = new Storage();
            List <SkiVideoEntity> videos = await storage.GetAllMetdataAsync();

            var selectedVideos = videos.OrderByDescending(v => v.RecordedTime).Take(5);

            foreach (var video in selectedVideos)
            {
                try
                {
                    await UpdateThumbnailAsync(storage, video);
                }
                catch (Exception e)
                {
                    Logger.Log($"Unable to update thumbnail for {video.PartitionKey}, {video.RowKey}", e);
                }
            }
        }
Example #27
0
        public bool LoadVideoJson()
        {
            try
            {
                string localJson = Storage.DownloadVideo(_videoJsonUrl);

                Logger.Log($"Found override json: {_videoJsonUrl}");
                VideoTime obj = FromJsonFile(localJson);
                this.Start    = obj.Start;
                this.Duration = obj.Duration;
            }
            catch (System.Net.WebException)
            {
                Logger.Log("No json override found for " + _videoJsonUrl);
                return(false);
            }

            return(true);
        }
Example #28
0
        private void DrawCoursePass()
        {
            int i    = 0;                            // FirstInCourse(_pass.Measurements);
            int last = _pass.Measurements.Count - 2; // LastInCourse(_pass.Measurements);
            HandleMeasurements handleMeasurements = new HandleMeasurements(this);

            for (; i < last; i++)
            {
                var m = _pass.Measurements[i];
                if (m.BoatPosition == CoursePosition.Empty)
                {
                    Logger.Log($"Out of course {i}");
                    continue;
                }

                DrawBoat(m, i);
                DrawHandle(m, i);
                handleMeasurements.Draw(m, i);
            }
        }
Example #29
0
        public void Stop()
        {
            lock (_queueClient)
            {
                if (!_queueClient.IsClosedOrClosing)
                {
                    var task = _queueClient.CloseAsync();

                    System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
                    long peakMemory = process.PeakWorkingSet64;
                    Logger.Log($"Stopping...  Peak memory was: {(peakMemory/1024/1024).ToString("F1")} mb");

                    task.Wait();
                }
                else
                {
                    Logger.Log("Queue already closing.");
                }
            }
        }
Example #30
0
        private void CalculateCoursePassSpeed(CoursePass pass)
        {
            if (pass.Exit == null || pass.Entry == null)
            {
                Logger.Log("Skiping course pass speed calculation since Entry or Exit are null.");
                return;
            }

            TimeSpan duration = pass.Exit.Timestamp.Subtract(pass.Entry.Timestamp);
            double distance = pass.Exit.BoatGeoCoordinate.GetDistanceTo(
                pass.Entry.BoatGeoCoordinate);
            
            if (duration == null || duration.Seconds <= 0 || distance <= 0)
            {
                throw new ApplicationException("Could not calculate time and distance for course entry/exit.");
            }

            double speedMps = distance / duration.TotalSeconds;
            pass.AverageBoatSpeed = Math.Round(speedMps * CoursePass.MPS_TO_MPH, 1);
        }