/// <summary>
        /// Decrypts the signature in the <see cref="VideoInfo.DownloadUrl" /> property and sets it
        /// to the decrypted URL. Use this method, if you have decryptSignature in the <see
        /// cref="GetDownloadUrls" /> method set to false.
        /// </summary>
        /// <param name="videoInfo">The video info which's downlaod URL should be decrypted.</param>
        /// <exception cref="YoutubeParseException">
        /// There was an error while deciphering the signature.
        /// </exception>
        public static void DecryptDownloadUrl(VideoInfo videoInfo)
        {
            IDictionary <string, string> queries = HttpHelper.ParseQueryString(videoInfo.DownloadUrl);

            if (queries.ContainsKey(SignatureQuery))
            {
                string encryptedSignature = queries[SignatureQuery];

                string decrypted;

                try
                {
                    decrypted = GetDecipheredSignature(videoInfo.HtmlPlayerVersion, encryptedSignature);
                }

                catch (Exception ex)
                {
                    throw new YoutubeParseException("Could not decipher signature", ex);
                }

                videoInfo.DownloadUrl        = HttpHelper.ReplaceQueryStringParameter(videoInfo.DownloadUrl, SignatureQuery, decrypted);
                videoInfo.RequiresDecryption = false;
            }
        }
        private static IEnumerable <VideoInfo> GetVideoInfos(YoutubeModel model)
        {
            var streamingFormats = GetStreamMap(model);

            if (streamingFormats == null)
            {
                streamingFormats = new List <Format>();
            }

            var adaptiveStream = GetAdaptiveStreamMap(model);

            if (adaptiveStream != null)
            {
                streamingFormats.AddRange(adaptiveStream);
            }

            foreach (var fmt in streamingFormats)
            {
                if (!fmt.Itag.HasValue)
                {
                    continue;
                }

                var itag = (int)fmt.Itag.Value;

                VideoInfo videoInfo = VideoInfo.Defaults.SingleOrDefault(info => info.FormatCode == itag);

                videoInfo = videoInfo ?? new VideoInfo(itag);

                if (!string.IsNullOrEmpty(fmt.Url))
                {
                    videoInfo.DownloadUrl = HttpHelper.UrlDecode(HttpHelper.UrlDecode(fmt.Url));
                }
                else if (!string.IsNullOrEmpty(fmt.Cipher) || !string.IsNullOrEmpty(fmt.SignatureCipher))
                {
                    IDictionary <string, string> cipher = null;

                    if (!string.IsNullOrEmpty(fmt.Cipher))
                    {
                        cipher = HttpHelper.ParseQueryString(fmt.Cipher);
                    }
                    if (!string.IsNullOrEmpty(fmt.SignatureCipher))
                    {
                        cipher = HttpHelper.ParseQueryString(fmt.SignatureCipher);
                    }

                    if (!cipher.ContainsKey("url"))
                    {
                        continue;
                    }
                    if (!cipher.ContainsKey("s"))
                    {
                        continue;
                    }

                    var url = cipher["url"];
                    var sig = cipher["s"];

                    url = HttpHelper.UrlDecode(url);
                    url = HttpHelper.UrlDecode(url);

                    sig = HttpHelper.UrlDecode(sig);
                    sig = HttpHelper.UrlDecode(sig);

                    url = url.Replace("&s=", "&sig=");
                    videoInfo.DownloadUrl        = HttpHelper.ReplaceQueryStringParameter(url, SignatureQuery, sig);
                    videoInfo.RequiresDecryption = true;
                }
                else
                {
                    continue;
                }

                if (!HttpHelper.ParseQueryString(videoInfo.DownloadUrl).ContainsKey(RateBypassFlag))
                {
                    videoInfo.DownloadUrl = string.Concat(videoInfo.DownloadUrl, string.Format("&{0}={1}", "ratebypass", "yes"));
                }

                if (fmt.AudioSampleRate.HasValue)
                {
                    videoInfo.AudioBitrate = (int)fmt.AudioSampleRate.Value;
                }

                if (fmt.ContentLength.HasValue)
                {
                    videoInfo.FileSize = (int)fmt.ContentLength.Value;
                }

                if (!string.IsNullOrEmpty(fmt.QualityLabel))
                {
                    videoInfo.FormatNote = fmt.QualityLabel;
                }
                else
                {
                    videoInfo.FormatNote = fmt.Quality;
                }

                if (fmt.Fps.HasValue)
                {
                    videoInfo.FPS = (int)fmt.Fps.Value;
                }

                if (fmt.Height.HasValue)
                {
                    videoInfo.Height = (int)fmt.Height.Value;
                }

                if (fmt.Width.HasValue)
                {
                    videoInfo.Width = (int)fmt.Width.Value;
                }

                // bitrate for itag 43 is always 2147483647
                if (itag != 43)
                {
                    if (fmt.AverageBitrate.HasValue)
                    {
                        videoInfo.AverageBitrate = fmt.AverageBitrate.Value / 1000f;
                    }
                    else if (fmt.Bitrate.HasValue)
                    {
                        videoInfo.AverageBitrate = fmt.Bitrate.Value / 1000f;
                    }
                }

                if (fmt.Height.HasValue)
                {
                    videoInfo.Height = (int)fmt.Height.Value;
                }

                if (fmt.Width.HasValue)
                {
                    videoInfo.Width = (int)fmt.Width.Value;
                }

                yield return(videoInfo);
            }
        }