Пример #1
0
        static void Main(string[] args)
        {
            // Here we setup the environment.
            // We step back from the project location until we reach the project's base folder and establish folder locations from there.

            // Getting the root path of the project.
            string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

            while (rootPath.Contains("TwitchBackend"))
            {
                rootPath = Directory.GetParent(rootPath).FullName;
            }

            string testPath = rootPath + "\\TestData\\";

            rootPath += "\\";
            ConfigurationManager.AppSettings["RootPath"] = rootPath;

            // Configuring Path locations.
            string scriptsPath         = rootPath + "Scripts\\";
            string broadcastsPath      = rootPath + "Broadcasts\\";
            string analyzedMatchesPath = rootPath + "AnalyzedBroadcasts\\";
            string tensorflowDataPath  = rootPath + "TensorflowData\\";
            string highlightVideosPath = rootPath + "HighlightVideos\\";
            string twitchVodsPath      = rootPath + "TwitchVods\\";

            ConfigurationManager.AppSettings["ScriptsPath"]         = scriptsPath;
            ConfigurationManager.AppSettings["BroadcastsPath"]      = broadcastsPath;
            ConfigurationManager.AppSettings["TwitchVodsPath"]      = twitchVodsPath;
            ConfigurationManager.AppSettings["AnalyzedMatchesPath"] = analyzedMatchesPath;
            ConfigurationManager.AppSettings["TensorflowDataPath"]  = tensorflowDataPath;
            ConfigurationManager.AppSettings["HighlightVideosPath"] = highlightVideosPath;
            ConfigurationManager.AppSettings["FilterTemplatePath"]  = scriptsPath + "broadcastFilterTemplate.png";
            ConfigurationManager.AppSettings["TestPath"]            = testPath;

            // Initialise existing broadcast data from previous sessions.
            FilteredMatchesManager.LoadFromJson();

            // Check for new videos to process.
            var           files           = Directory.GetFiles(twitchVodsPath);
            List <string> videosToProcess = new List <string>();

            // Filter out non video files.
            foreach (var file in files)
            {
                if (file.EndsWith(".mp4"))
                {
                    videosToProcess.Add(file);
                }
            }

            // Process videos, stripping out non-gameplay elements.
            var filteredMatches = new BroadcastFilter().FilterBroadcasts(videosToProcess);

            Console.WriteLine("");
            Console.WriteLine("Populating chat-logs for filtered matches");
            Console.WriteLine("");

            // Load in filtered chat-log info into each filtered match.
            foreach (var filteredMatch in filteredMatches)
            {
                if (!filteredMatch.IsPopulated)
                {
                    filteredMatch.PopulateMatchChatLogs();
                }
            }

            // Save the newly discovered filtered match info to our manager.
            FilteredMatchesManager.AddFilteredMatches(filteredMatches);

            var matchAnalyzer   = new MatchAnalyzer();
            var matchCollection = new List <List <MatchMetricGroup> >();

            Console.WriteLine("");
            Console.WriteLine("Analyzing matches.");
            Console.WriteLine("");

            // Go through each filtered match and analyze it for selected gameplay metrics (kills, ultimate usage, ect.).
            foreach (var filteredMatch in FilteredMatchesManager.FilteredMatches)
            {
                matchCollection.Add(matchAnalyzer.AnalyzeMatches(filteredMatch));
            }

            // Save the newly discovered analysis to our manager.
            foreach (var collection in matchCollection)
            {
                AnalyzedMatchesManager.AddAnalyzedMatches(collection);
            }

            Console.WriteLine("");
            Console.WriteLine("Match analysis complete.");
            Console.WriteLine("");

            // Ensuring a Json file is generated and in sync with the local files generated via analysis.
            AnalyzedMatchesManager.LoadFromFiles();
            AnalyzedMatchesManager.SaveToJson();

            Console.WriteLine("");
            Console.WriteLine("Loading analyzed match info into Deep Learning Predictor.");
            Console.WriteLine("");


            var deepLearner        = new NeuralNetController();
            var highlightGenerator = new HighlightMaker();

            // Finally we generate a highlight for each discovered match we find.
            foreach (var match in AnalyzedMatchesManager.AnalyzedMatches)
            {
                if (!match.Match.IsInstantReplay)
                {
                    var highlightInfo      = deepLearner.GetHighlightPeriod(match);
                    var highlightVideoPath = highlightGenerator.CreateHighlight(highlightInfo, match.Match);
                    Console.WriteLine($"Highlight video created at: {highlightVideoPath} for match: {match.Match.GetFileName(false)}");
                }
            }

            // Here all UnFiltered Broadcasts are Filtered, then all Analyzed Matches are Analyzed, then all untrained instant-replays are trained and all unpredicted matches are predicted.
            // All Analyzed matches then have their corresponding highlight video rendered, available to the user to view.
            Console.WriteLine($"Processing complete: Go to {highlightVideosPath} to see highlight videos.");
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
Пример #2
0
        /// <summary>
        /// Loads in the filteredMatch list file. If a local analysis file exists it will use this first to avoid unnecessary processing.
        /// </summary>
        public static void LoadFromFiles()
        {
            var filteredMatches = FilteredMatchesManager.FilteredMatches;

            AnalyzedMatches = new List <MatchMetricGroup>();
            var folders = Directory.GetDirectories(AnalyzedMatchesPath);

            // Go over each filtered match and look up their corresponding analysis files.
            foreach (var filteredMatch in filteredMatches)
            {
                foreach (var folder in folders)
                {
                    if (folder.Contains(filteredMatch.Broadcast.Id.ToString()))
                    {
                        // Analysis files found.
                        var files = Directory.GetFiles(folder);

                        // Go over each match and create a corresponding analysis object using the local analysis files.
                        // If no file found, perform analysis and create an object from scratch (and a corresponding analysis file group.).
                        foreach (var match in filteredMatch.Matches)
                        {
                            // Check everything requires exists.
                            MatchMetricGroup metrics;
                            bool             killsFound = false,
                                             turretsFound = false,
                                             ultimatesFound = false,
                                             baronFound = false,
                                             dragonFound = false,
                                             inhibitorFound = false;
                            string killPath = null, ultimatePath = null, turretsPath = null, baronPath = null, dragonPath = null, inhibitorPath = null;
                            foreach (var file in files)
                            {
                                if (file.Contains(match.GetFileName(false)))
                                {
                                    if (file.Contains("kills"))
                                    {
                                        killPath   = file;
                                        killsFound = true;
                                    }

                                    if (file.Contains("ultimates"))
                                    {
                                        ultimatePath   = file;
                                        ultimatesFound = true;
                                    }

                                    if (file.Contains("turrets"))
                                    {
                                        turretsPath  = file;
                                        turretsFound = true;
                                    }

                                    if (file.Contains("baron"))
                                    {
                                        baronPath  = file;
                                        baronFound = true;
                                    }

                                    if (file.Contains("dragon"))
                                    {
                                        dragonPath  = file;
                                        dragonFound = true;
                                    }

                                    if (file.Contains("inhibitor"))
                                    {
                                        inhibitorPath  = file;
                                        inhibitorFound = true;
                                    }
                                }
                            }
                            // If one or more metrics missing, (re)generate analysis info.
                            if (!(ultimatesFound && killsFound && turretsFound && baronFound && dragonFound && inhibitorFound))
                            {
                                metrics = new MatchAnalyzer().AnalyzeMatch(match, filteredMatch);
                            }
                            // Load analysis info from file.
                            else
                            {
                                metrics = new MatchAnalyzer().ParseMatch(killPath, ultimatePath, turretsPath, baronPath, dragonPath, inhibitorPath, match);
                            }
                            AnalyzedMatches.Add(metrics);
                        }
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Uses the Tensorflow model to predict the most exciting moment.
        /// Returns metadata about the highlight.
        /// </summary>
        /// <param name="matchMetricGroup"></param>
        /// <returns></returns>
        public HighlightInfo GetHighlightPeriod(MatchMetricGroup matchMetricGroup, bool testConfiguration = false)
        {
            if (testConfiguration)
            {
                _deepLearnerScriptPath = ConfigurationManager.AppSettings["AltScriptsPath"] + "DeepLearningModel.py";
            }

            // Packages matchMetricGroup info into a chunked up form that Tensorflow can understand and creates a csv file for the Tensorflow python script to reference.
            var(matchPath, predictedDataPath) = PrepareMatchForTensorFlow(matchMetricGroup, false);

            // Runs the python script that outputs a csv file for the predictions the Tensorflow model made about the excitement level at a particular time in the match.
            GetHighlightInfo(matchPath, predictedDataPath);

            // Load in the predictions made by the model.
            List <string> predictedDataRaw;

            try
            {
                predictedDataRaw = File.ReadAllLines(_tensorflowPath + "Predictions\\" + predictedDataPath).ToList();
            }
            catch (Exception)
            {
                // Very rare edge case when multiple parallel uses of the model can cause a failure to predict.
                GetHighlightInfo(matchPath, predictedDataPath);
                predictedDataRaw = File.ReadAllLines(_tensorflowPath + "Predictions\\" + predictedDataPath).ToList();
            }
            Console.WriteLine(predictedDataPath + " Complete.");

            List <double> predictedData = new List <double>();
            List <double> matchOffset   = new List <double>();

            var matchAnalyzer = new MatchAnalyzer();

            // Parse predicted data into relevant objects. reference is via an offset from the original raw Broadcast video start time.
            var counter = 0.0;

            foreach (var line in predictedDataRaw)
            {
                predictedData.Add(double.Parse(line));
                matchOffset.Add(matchAnalyzer.ConvertVideoTimeToMatchOffset(counter * 15, matchMetricGroup.Match));
                counter += 1;
            }

            // Find the most exciting period in the match and its score.
            var highestScore      = 0.0;
            var index             = 0;
            var highestScoreIndex = 0;

            foreach (var score in predictedData)
            {
                if (score > highestScore)
                {
                    highestScore      = score;
                    highestScoreIndex = index;
                }

                index += 1;
            }

            // We offset the start by an additional 90 seconds to account for time slippage.
            return(new HighlightInfo(matchOffset[highestScoreIndex] + 90, 40, highestScore));
        }