private static IEnumerable <Caption> SearchTrackForPhrases(CaptionTrack track, string[] phrases) { const string fullTextSeperator = " "; var startByCaption = new Dictionary <Caption, int>(); //aggregate captions into fullText to enable matching phrases across caption boundaries var fullText = track.Captions.OrderBy(c => c.At).Aggregate(string.Empty, (fullText, caption) => { //remember at what index in the fullText the caption starts startByCaption.Add(caption, fullText.Length == 0 ? 0 : fullText.Length + fullTextSeperator.Length); return(fullText.Length == 0 ? caption.Text : fullText + fullTextSeperator + caption.Text); }); return(fullText.GetMatches(phrases).Select(match => { //find first and last captions containing parts of the phrase var first = startByCaption.Last(x => x.Value <= match.Index); var last = startByCaption.Last(x => first.Value <= x.Value && x.Value < match.Index + match.Length); //return a single caption for all captions containing the phrase return new Caption { At = first.Key.At, Text = startByCaption .Where(x => first.Value <= x.Value && x.Value <= last.Value) .Select(x => x.Key.Text) .Join(fullTextSeperator) }; })); }
} //required by serializer /// <summary>Use this to clone a Captiontrack to include in a VideoSerachResult. /// Captions will be set to matchingCaptions instead of cloning track.Captions.</summary> /// <param name="track">The track to clone.</param> /// <param name="matchingCaptions">The matching captions.</param> internal CaptionTrack(CaptionTrack track, Caption[] matchingCaptions) { this.LanguageName = track.LanguageName; this.Captions = matchingCaptions; }