diff --git a/core/InnerTube/CacheItem.cs b/core/InnerTube/CacheItem.cs new file mode 100644 index 00000000..343c295c --- /dev/null +++ b/core/InnerTube/CacheItem.cs @@ -0,0 +1,16 @@ +using System; + +namespace InnerTube +{ + public class CacheItem + { + public T Item; + public DateTimeOffset ExpireTime; + + public CacheItem(T item, TimeSpan expiresIn) + { + Item = item; + ExpireTime = DateTimeOffset.Now.Add(expiresIn); + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Enums.cs b/core/InnerTube/Enums.cs new file mode 100644 index 00000000..8c506f92 --- /dev/null +++ b/core/InnerTube/Enums.cs @@ -0,0 +1,12 @@ +namespace InnerTube +{ + public enum ChannelTabs + { + Home, + Videos, + Playlists, + Community, + Channels, + About + } +} \ No newline at end of file diff --git a/core/InnerTube/InnerTube.csproj b/core/InnerTube/InnerTube.csproj new file mode 100644 index 00000000..7792fb99 --- /dev/null +++ b/core/InnerTube/InnerTube.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/core/InnerTube/Models/DynamicItem.cs b/core/InnerTube/Models/DynamicItem.cs new file mode 100644 index 00000000..5095955e --- /dev/null +++ b/core/InnerTube/Models/DynamicItem.cs @@ -0,0 +1,380 @@ +using System; +using System.Xml; +using System.Xml.Linq; + +namespace InnerTube.Models +{ + public class DynamicItem + { + public string Id; + public string Title; + public Thumbnail[] Thumbnails; + + public virtual XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("DynamicItem"); + item.SetAttribute("id", Id); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } + + public class VideoItem : DynamicItem + { + public string UploadedAt; + public long Views; + public Channel Channel; + public string Duration; + public string Description; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Video"); + item.SetAttribute("id", Id); + item.SetAttribute("duration", Duration); + item.SetAttribute("views", Views.ToString()); + item.SetAttribute("uploadedAt", UploadedAt); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + if (Channel is not null) + item.AppendChild(Channel.GetXmlElement(doc)); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + if (!string.IsNullOrWhiteSpace(Description)) + { + XmlElement description = doc.CreateElement("Description"); + description.InnerText = Description; + item.AppendChild(description); + } + + return item; + } + } + + public class PlaylistItem : DynamicItem + { + public int VideoCount; + public string FirstVideoId; + public Channel Channel; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Playlist"); + item.SetAttribute("id", Id); + item.SetAttribute("videoCount", VideoCount.ToString()); + item.SetAttribute("firstVideoId", FirstVideoId); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + item.AppendChild(Channel.GetXmlElement(doc)); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } + + public class RadioItem : DynamicItem + { + public string FirstVideoId; + public Channel Channel; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Radio"); + item.SetAttribute("id", Id); + item.SetAttribute("firstVideoId", FirstVideoId); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + item.AppendChild(Channel.GetXmlElement(doc)); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } + + public class ChannelItem : DynamicItem + { + public string Url; + public string Description; + public long VideoCount; + public string Subscribers; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Channel"); + item.SetAttribute("id", Id); + item.SetAttribute("videoCount", VideoCount.ToString()); + item.SetAttribute("subscribers", Subscribers); + if (!string.IsNullOrWhiteSpace(Url)) + item.SetAttribute("customUrl", Url); + + XmlElement title = doc.CreateElement("Name"); + title.InnerText = Title; + item.AppendChild(title); + + XmlElement description = doc.CreateElement("Description"); + description.InnerText = Description; + item.AppendChild(description); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Avatar"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } + + public class ContinuationItem : DynamicItem + { + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Continuation"); + item.SetAttribute("key", Id); + return item; + } + } + + public class ShelfItem : DynamicItem + { + public DynamicItem[] Items; + public int CollapsedItemCount; + public BadgeItem[] Badges; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Shelf"); + item.SetAttribute("title", Title); + item.SetAttribute("collapsedItemCount", CollapsedItemCount.ToString()); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + if (Badges.Length > 0) + { + XmlElement badges = doc.CreateElement("Badges"); + foreach (BadgeItem badge in Badges) badges.AppendChild(badge.GetXmlElement(doc)); + item.AppendChild(badges); + } + + XmlElement items = doc.CreateElement("Items"); + foreach (DynamicItem dynamicItem in Items) items.AppendChild(dynamicItem.GetXmlElement(doc)); + item.AppendChild(items); + + return item; + } + } + + public class HorizontalCardListItem : DynamicItem + { + public DynamicItem[] Items; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("CardList"); + item.SetAttribute("title", Title); + + foreach (DynamicItem dynamicItem in Items) item.AppendChild(dynamicItem.GetXmlElement(doc)); + + return item; + } + } + + public class CardItem : DynamicItem + { + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Card"); + item.SetAttribute("title", Title); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } + + public class PlaylistVideoItem : DynamicItem + { + public long Index; + public Channel Channel; + public string Duration; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Video"); + item.SetAttribute("id", Id); + item.SetAttribute("index", Index.ToString()); + item.SetAttribute("duration", Duration); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + item.AppendChild(Channel.GetXmlElement(doc)); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } + + public class ItemSectionItem : DynamicItem + { + public DynamicItem[] Contents; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement section = doc.CreateElement("ItemSection"); + foreach (DynamicItem item in Contents) section.AppendChild(item.GetXmlElement(doc)); + return section; + } + } + + public class MessageItem : DynamicItem + { + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement message = doc.CreateElement("Message"); + message.InnerText = Title; + return message; + } + } + + public class ChannelAboutItem : DynamicItem + { + public string Description; + public string Country; + public string Joined; + public string ViewCount; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement about = doc.CreateElement("About"); + XmlElement description = doc.CreateElement("Description"); + description.InnerText = Description; + about.AppendChild(description); + XmlElement country = doc.CreateElement("Location"); + country.InnerText = Country; + about.AppendChild(country); + XmlElement joined = doc.CreateElement("Joined"); + joined.InnerText = Joined; + about.AppendChild(joined); + XmlElement viewCount = doc.CreateElement("ViewCount"); + viewCount.InnerText = ViewCount; + about.AppendChild(viewCount); + return about; + } + } + + public class BadgeItem : DynamicItem + { + public string Style; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement badge = doc.CreateElement("Badge"); + badge.SetAttribute("style", Style); + badge.InnerText = Title; + return badge; + } + } + + public class StationItem : DynamicItem + { + public int VideoCount; + public string FirstVideoId; + public string Description; + + public override XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Station"); + item.SetAttribute("id", Id); + item.SetAttribute("videoCount", VideoCount.ToString()); + item.SetAttribute("firstVideoId", FirstVideoId); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + + XmlElement description = doc.CreateElement("Description"); + description.InnerText = Description; + item.AppendChild(description); + + foreach (Thumbnail t in Thumbnails ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/RequestContext.cs b/core/InnerTube/Models/RequestContext.cs new file mode 100644 index 00000000..fcdb983c --- /dev/null +++ b/core/InnerTube/Models/RequestContext.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace InnerTube.Models +{ + public class RequestContext + { + [JsonProperty("context")] public Context Context; + + public static string BuildRequestContextJson(Dictionary additionalFields, string language = "en", + string region = "US", string clientName = "WEB", string clientVersion = "2.20220224.07.00") + { + RequestContext ctx = new() + { + Context = new Context( + new RequestClient(language, region, clientName, clientVersion), + new RequestUser(false)) + }; + + string json1 = JsonConvert.SerializeObject(ctx); + Dictionary json2 = JsonConvert.DeserializeObject>(json1); + foreach (KeyValuePair pair in additionalFields) json2.Add(pair.Key, pair.Value); + + return JsonConvert.SerializeObject(json2); + } + } + + public class Context + { + [JsonProperty("client")] public RequestClient RequestClient { get; set; } + [JsonProperty("user")] public RequestUser RequestUser { get; set; } + + public Context(RequestClient requestClient, RequestUser requestUser) + { + RequestClient = requestClient; + RequestUser = requestUser; + } + } + + public class RequestClient + { + [JsonProperty("hl")] public string Language { get; set; } + [JsonProperty("gl")] public string Region { get; set; } + [JsonProperty("clientName")] public string ClientName { get; set; } + [JsonProperty("clientVersion")] public string ClientVersion { get; set; } + [JsonProperty("deviceModel")] public string DeviceModel { get; set; } + + public RequestClient(string language, string region, string clientName, string clientVersion) + { + Language = language; + Region = region; + ClientName = clientName; + ClientVersion = clientVersion; + if (clientName == "IOS") DeviceModel = "iPhone14,3"; + } + } + + public class RequestUser + { + [JsonProperty("lockedSafetyMode")] public bool LockedSafetyMode { get; set; } + + public RequestUser(bool lockedSafetyMode) + { + LockedSafetyMode = lockedSafetyMode; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubeChannel.cs b/core/InnerTube/Models/YoutubeChannel.cs new file mode 100644 index 00000000..3d497c6c --- /dev/null +++ b/core/InnerTube/Models/YoutubeChannel.cs @@ -0,0 +1,71 @@ +using System.Xml; + +namespace InnerTube.Models +{ + public class YoutubeChannel + { + public string Id; + public string Name; + public string Url; + public Thumbnail[] Avatars; + public Thumbnail[] Banners; + public string Description; + public DynamicItem[] Videos; + public string Subscribers; + + public string GetHtmlDescription() + { + return Utils.GetHtmlDescription(Description); + } + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement channel = doc.CreateElement("Channel"); + channel.SetAttribute("id", Id); + if (Id != Url) + channel.SetAttribute("customUrl", Url); + + XmlElement metadata = doc.CreateElement("Metadata"); + + XmlElement name = doc.CreateElement("Name"); + name.InnerText = Name; + metadata.AppendChild(name); + + XmlElement avatars = doc.CreateElement("Avatars"); + foreach (Thumbnail t in Avatars) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + avatars.AppendChild(thumbnail); + } + metadata.AppendChild(avatars); + + XmlElement banners = doc.CreateElement("Banners"); + foreach (Thumbnail t in Banners) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + banners.AppendChild(thumbnail); + } + metadata.AppendChild(banners); + + XmlElement subscriberCount = doc.CreateElement("Subscribers"); + subscriberCount.InnerText = Subscribers; + metadata.AppendChild(subscriberCount); + + channel.AppendChild(metadata); + + XmlElement contents = doc.CreateElement("Contents"); + foreach (DynamicItem item in Videos) contents.AppendChild(item.GetXmlElement(doc)); + channel.AppendChild(contents); + + doc.AppendChild(channel); + return doc; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubeLocals.cs b/core/InnerTube/Models/YoutubeLocals.cs new file mode 100644 index 00000000..58827509 --- /dev/null +++ b/core/InnerTube/Models/YoutubeLocals.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Xml; + +namespace InnerTube.Models +{ + public class YoutubeLocals + { + public Dictionary Languages { get; set; } + public Dictionary Regions { get; set; } + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement locals = doc.CreateElement("Locals"); + + XmlElement languages = doc.CreateElement("Languages"); + foreach (KeyValuePair l in Languages) + { + XmlElement language = doc.CreateElement("Language"); + language.SetAttribute("hl", l.Key); + language.InnerText = l.Value; + languages.AppendChild(language); + } + locals.AppendChild(languages); + + XmlElement regions = doc.CreateElement("Regions"); + foreach (KeyValuePair r in Regions) + { + XmlElement region = doc.CreateElement("Region"); + region.SetAttribute("gl", r.Key); + region.InnerText = r.Value; + regions.AppendChild(region); + } + locals.AppendChild(regions); + + doc.AppendChild(locals); + return doc; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubePlayer.cs b/core/InnerTube/Models/YoutubePlayer.cs new file mode 100644 index 00000000..8e1e03c1 --- /dev/null +++ b/core/InnerTube/Models/YoutubePlayer.cs @@ -0,0 +1,230 @@ +using System; +using System.Xml; +using Newtonsoft.Json; + +namespace InnerTube.Models +{ + public class YoutubePlayer + { + public string Id { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public string[] Tags { get; set; } + public Channel Channel { get; set; } + public long? Duration { get; set; } + public bool IsLive { get; set; } + public Chapter[] Chapters { get; set; } + public Thumbnail[] Thumbnails { get; set; } + public Format[] Formats { get; set; } + public Format[] AdaptiveFormats { get; set; } + public string HlsManifestUrl { get; set; } + public Subtitle[] Subtitles { get; set; } + public string[] Storyboards { get; set; } + public string ExpiresInSeconds { get; set; } + public string ErrorMessage { get; set; } + + public string GetHtmlDescription() + { + return Utils.GetHtmlDescription(Description); + } + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + if (!string.IsNullOrWhiteSpace(ErrorMessage)) + { + XmlElement error = doc.CreateElement("Error"); + error.InnerText = ErrorMessage; + doc.AppendChild(error); + } + else + { + XmlElement player = doc.CreateElement("Player"); + player.SetAttribute("id", Id); + player.SetAttribute("duration", Duration.ToString()); + player.SetAttribute("isLive", IsLive.ToString()); + player.SetAttribute("expiresInSeconds", ExpiresInSeconds); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + player.AppendChild(title); + + XmlElement description = doc.CreateElement("Description"); + description.InnerText = Description; + player.AppendChild(description); + + XmlElement tags = doc.CreateElement("Tags"); + foreach (string tag in Tags ?? Array.Empty()) + { + XmlElement tagElement = doc.CreateElement("Tag"); + tagElement.InnerText = tag; + tags.AppendChild(tagElement); + } + player.AppendChild(tags); + + player.AppendChild(Channel.GetXmlElement(doc)); + + XmlElement thumbnails = doc.CreateElement("Thumbnails"); + foreach (Thumbnail t in Thumbnails) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + thumbnails.AppendChild(thumbnail); + } + player.AppendChild(thumbnails); + + XmlElement formats = doc.CreateElement("Formats"); + foreach (Format f in Formats ?? Array.Empty()) formats.AppendChild(f.GetXmlElement(doc)); + player.AppendChild(formats); + + XmlElement adaptiveFormats = doc.CreateElement("AdaptiveFormats"); + foreach (Format f in AdaptiveFormats ?? Array.Empty()) adaptiveFormats.AppendChild(f.GetXmlElement(doc)); + player.AppendChild(adaptiveFormats); + + XmlElement storyboards = doc.CreateElement("Storyboards"); + foreach (string s in Storyboards) + { + XmlElement storyboard = doc.CreateElement("Storyboard"); + storyboard.InnerText = s; + storyboards.AppendChild(storyboard); + } + player.AppendChild(storyboards); + + XmlElement subtitles = doc.CreateElement("Subtitles"); + foreach (Subtitle s in Subtitles ?? Array.Empty()) subtitles.AppendChild(s.GetXmlElement(doc)); + player.AppendChild(subtitles); + + doc.AppendChild(player); + } + + return doc; + } + } + + public class Chapter + { + [JsonProperty("title")] public string Title { get; set; } + [JsonProperty("start_time")] public long StartTime { get; set; } + [JsonProperty("end_time")] public long EndTime { get; set; } + } + + public class Format + { + [JsonProperty("format")] public string FormatName { get; set; } + [JsonProperty("format_id")] public string FormatId { get; set; } + [JsonProperty("format_note")] public string FormatNote { get; set; } + [JsonProperty("filesize")] public long? Filesize { get; set; } + [JsonProperty("quality")] public long Quality { get; set; } + [JsonProperty("bitrate")] public double Bitrate { get; set; } + [JsonProperty("audio_codec")] public string AudioCodec { get; set; } + [JsonProperty("video_codec")] public string VideoCodec { get; set; } + [JsonProperty("audio_sample_rate")] public long? AudioSampleRate { get; set; } + [JsonProperty("resolution")] public string Resolution { get; set; } + [JsonProperty("url")] public string Url { get; set; } + [JsonProperty("init_range")] public Range InitRange { get; set; } + [JsonProperty("index_range")] public Range IndexRange { get; set; } + + public XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement format = doc.CreateElement("Format"); + + format.SetAttribute("id", FormatId); + format.SetAttribute("label", FormatName); + format.SetAttribute("filesize", Filesize.ToString()); + format.SetAttribute("quality", Bitrate.ToString()); + format.SetAttribute("audioCodec", AudioCodec); + format.SetAttribute("videoCodec", VideoCodec); + if (AudioSampleRate != null) + format.SetAttribute("audioSampleRate", AudioSampleRate.ToString()); + else + format.SetAttribute("resolution", Resolution); + + XmlElement url = doc.CreateElement("URL"); + url.InnerText = Url; + format.AppendChild(url); + + if (InitRange != null && IndexRange != null) + { + XmlElement initRange = doc.CreateElement("InitRange"); + initRange.SetAttribute("start", InitRange.Start); + initRange.SetAttribute("end", InitRange.End); + format.AppendChild(initRange); + + XmlElement indexRange = doc.CreateElement("IndexRange"); + indexRange.SetAttribute("start", IndexRange.Start); + indexRange.SetAttribute("end", IndexRange.End); + format.AppendChild(indexRange); + } + + return format; + } + } + + public class Range + { + [JsonProperty("start")] public string Start { get; set; } + [JsonProperty("end")] public string End { get; set; } + + public Range(string start, string end) + { + Start = start; + End = end; + } + } + + public class Channel + { + [JsonProperty("name")] public string Name { get; set; } + [JsonProperty("id")] public string Id { get; set; } + [JsonProperty("subscriberCount")] public string SubscriberCount { get; set; } + [JsonProperty("avatars")] public Thumbnail[] Avatars { get; set; } + + public XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement channel = doc.CreateElement("Channel"); + channel.SetAttribute("id", Id); + if (!string.IsNullOrWhiteSpace(SubscriberCount)) + channel.SetAttribute("subscriberCount", SubscriberCount); + + XmlElement name = doc.CreateElement("Name"); + name.InnerText = Name; + channel.AppendChild(name); + + foreach (Thumbnail avatarThumb in Avatars ?? Array.Empty()) + { + XmlElement avatar = doc.CreateElement("Avatar"); + avatar.SetAttribute("width", avatarThumb.Width.ToString()); + avatar.SetAttribute("height", avatarThumb.Height.ToString()); + avatar.InnerText = avatarThumb.Url; + channel.AppendChild(avatar); + } + + return channel; + } + } + + public class Subtitle + { + [JsonProperty("ext")] public string Ext { get; set; } + [JsonProperty("name")] public string Language { get; set; } + [JsonProperty("url")] public string Url { get; set; } + + public XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement subtitle = doc.CreateElement("Subtitle"); + subtitle.SetAttribute("ext", Ext); + subtitle.SetAttribute("language", Language); + subtitle.InnerText = Url; + return subtitle; + } + } + + public class Thumbnail + { + [JsonProperty("height")] public long Height { get; set; } + [JsonProperty("url")] public string Url { get; set; } + [JsonProperty("width")] public long Width { get; set; } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubePlaylist.cs b/core/InnerTube/Models/YoutubePlaylist.cs new file mode 100644 index 00000000..a9124958 --- /dev/null +++ b/core/InnerTube/Models/YoutubePlaylist.cs @@ -0,0 +1,68 @@ +using System.Xml; + +namespace InnerTube.Models +{ + public class YoutubePlaylist + { + public string Id; + public string Title; + public string Description; + public string VideoCount; + public string ViewCount; + public string LastUpdated; + public Thumbnail[] Thumbnail; + public Channel Channel; + public DynamicItem[] Videos; + public string ContinuationKey; + + public string GetHtmlDescription() => Utils.GetHtmlDescription(Description); + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement playlist = doc.CreateElement("Playlist"); + playlist.SetAttribute("id", Id); + playlist.SetAttribute("continuation", ContinuationKey); + + XmlElement metadata = doc.CreateElement("Metadata"); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + metadata.AppendChild(title); + + metadata.AppendChild(Channel.GetXmlElement(doc)); + + XmlElement thumbnails = doc.CreateElement("Thumbnails"); + foreach (Thumbnail t in Thumbnail) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + thumbnails.AppendChild(thumbnail); + } + metadata.AppendChild(thumbnails); + + XmlElement videoCount = doc.CreateElement("VideoCount"); + XmlElement viewCount = doc.CreateElement("ViewCount"); + XmlElement lastUpdated = doc.CreateElement("LastUpdated"); + + videoCount.InnerText = VideoCount; + viewCount.InnerText = ViewCount; + lastUpdated.InnerText = LastUpdated; + + metadata.AppendChild(videoCount); + metadata.AppendChild(viewCount); + metadata.AppendChild(lastUpdated); + + playlist.AppendChild(metadata); + + XmlElement results = doc.CreateElement("Videos"); + foreach (DynamicItem result in Videos) results.AppendChild(result.GetXmlElement(doc)); + playlist.AppendChild(results); + + doc.AppendChild(playlist); + return doc; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubeSearchResults.cs b/core/InnerTube/Models/YoutubeSearchResults.cs new file mode 100644 index 00000000..5feeecc3 --- /dev/null +++ b/core/InnerTube/Models/YoutubeSearchResults.cs @@ -0,0 +1,39 @@ +using System.Xml; + +namespace InnerTube.Models +{ + public class YoutubeSearchResults + { + public string[] Refinements; + public long EstimatedResults; + public DynamicItem[] Results; + public string ContinuationKey; + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement search = doc.CreateElement("Search"); + search.SetAttribute("estimatedResults", EstimatedResults.ToString()); + search.SetAttribute("continuation", ContinuationKey); + + if (Refinements.Length > 0) + { + XmlElement refinements = doc.CreateElement("Refinements"); + foreach (string refinementText in Refinements) + { + XmlElement refinement = doc.CreateElement("Refinement"); + refinement.InnerText = refinementText; + refinements.AppendChild(refinement); + } + search.AppendChild(refinements); + } + + XmlElement results = doc.CreateElement("Results"); + foreach (DynamicItem result in Results) results.AppendChild(result.GetXmlElement(doc)); + search.AppendChild(results); + + doc.AppendChild(search); + return doc; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubeStoryboardSpec.cs b/core/InnerTube/Models/YoutubeStoryboardSpec.cs new file mode 100644 index 00000000..dd133f66 --- /dev/null +++ b/core/InnerTube/Models/YoutubeStoryboardSpec.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace InnerTube.Models +{ + public class YoutubeStoryboardSpec + { + public Dictionary Urls = new(); + public YoutubeStoryboardSpec(string specStr, long duration) + { + if (specStr is null) return; + List spec = new(specStr.Split("|")); + string baseUrl = spec[0]; + spec.RemoveAt(0); + spec.Reverse(); + int L = spec.Count - 1; + for (int i = 0; i < spec.Count; i++) + { + string[] args = spec[i].Split("#"); + int width = int.Parse(args[0]); + int height = int.Parse(args[1]); + int frameCount = int.Parse(args[2]); + int cols = int.Parse(args[3]); + int rows = int.Parse(args[4]); + string N = args[6]; + string sigh = args[7]; + string url = baseUrl + .Replace("$L", (spec.Count - 1 - i).ToString()) + .Replace("$N", N) + "&sigh=" + sigh; + float fragmentCount = frameCount / (cols * rows); + float fragmentDuration = duration / fragmentCount; + + for (int j = 0; j < Math.Ceiling(fragmentCount); j++) + Urls.TryAdd($"L{spec.Count - 1 - i}", url.Replace("$M", j.ToString())); + } + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubeTrends.cs b/core/InnerTube/Models/YoutubeTrends.cs new file mode 100644 index 00000000..8ecacf27 --- /dev/null +++ b/core/InnerTube/Models/YoutubeTrends.cs @@ -0,0 +1,70 @@ +using System; +using System.Xml; + +namespace InnerTube.Models +{ + public class YoutubeTrends + { + public TrendCategory[] Categories; + public DynamicItem[] Videos; + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement explore = doc.CreateElement("Explore"); + + XmlElement categories = doc.CreateElement("Categories"); + foreach (TrendCategory category in Categories ?? Array.Empty()) categories.AppendChild(category.GetXmlElement(doc)); + explore.AppendChild(categories); + + XmlElement contents = doc.CreateElement("Videos"); + foreach (DynamicItem item in Videos ?? Array.Empty()) contents.AppendChild(item.GetXmlElement(doc)); + explore.AppendChild(contents); + + doc.AppendChild(explore); + return doc; + } + } + + public class TrendCategory + { + public string Label; + public Thumbnail[] BackgroundImage; + public Thumbnail[] Icon; + public string Id; + + public XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement category = doc.CreateElement("Category"); + category.SetAttribute("id", Id); + + XmlElement title = doc.CreateElement("Name"); + title.InnerText = Label; + category.AppendChild(title); + + XmlElement backgroundImages = doc.CreateElement("BackgroundImage"); + foreach (Thumbnail t in BackgroundImage ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + backgroundImages.AppendChild(thumbnail); + } + category.AppendChild(backgroundImages); + + XmlElement icons = doc.CreateElement("Icon"); + foreach (Thumbnail t in Icon ?? Array.Empty()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + icons.AppendChild(thumbnail); + } + category.AppendChild(icons); + + return category; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Models/YoutubeVideo.cs b/core/InnerTube/Models/YoutubeVideo.cs new file mode 100644 index 00000000..598b1cd4 --- /dev/null +++ b/core/InnerTube/Models/YoutubeVideo.cs @@ -0,0 +1,45 @@ +using System; +using System.Xml; + +namespace InnerTube.Models +{ + public class YoutubeVideo + { + public string Id; + public string Title; + public string Description; + public Channel Channel; + public string UploadDate; + public DynamicItem[] Recommended; + public string Views; + + public string GetHtmlDescription() => InnerTube.Utils.GetHtmlDescription(Description); + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement item = doc.CreateElement("Video"); + + item.SetAttribute("id", Id); + item.SetAttribute("views", Views); + item.SetAttribute("uploadDate", UploadDate); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + + XmlElement description = doc.CreateElement("Description"); + description.InnerText = Description; + item.AppendChild(description); + + item.AppendChild(Channel.GetXmlElement(doc)); + + XmlElement recommendations = doc.CreateElement("Recommendations"); + foreach (DynamicItem f in Recommended ?? Array.Empty()) recommendations.AppendChild(f.GetXmlElement(doc)); + item.AppendChild(recommendations); + + doc.AppendChild(item); + return doc; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/ReturnYouTubeDislike.cs b/core/InnerTube/ReturnYouTubeDislike.cs new file mode 100644 index 00000000..83ea3c34 --- /dev/null +++ b/core/InnerTube/ReturnYouTubeDislike.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace InnerTube +{ + public static class ReturnYouTubeDislike + { + private static HttpClient _client = new(); + private static Dictionary DislikesCache = new(); + + // TODO: better cache + public static async Task GetDislikes(string videoId) + { + if (DislikesCache.ContainsKey(videoId)) + return DislikesCache[videoId]; + + HttpResponseMessage response = await _client.GetAsync("https://returnyoutubedislikeapi.com/votes?videoId=" + videoId); + string json = await response.Content.ReadAsStringAsync(); + YoutubeDislikes dislikes = JsonConvert.DeserializeObject(json); + if (dislikes is not null) + DislikesCache.Add(videoId, dislikes); + return dislikes ?? new YoutubeDislikes(); + } + } + + public class YoutubeDislikes + { + [JsonProperty("id")] public string Id { get; set; } + [JsonProperty("dateCreated")] public string DateCreated { get; set; } + [JsonProperty("likes")] public long Likes { get; set; } + [JsonProperty("dislikes")] public long Dislikes { get; set; } + [JsonProperty("rating")] public double Rating { get; set; } + [JsonProperty("viewCount")] public long Views { get; set; } + [JsonProperty("deleted")] public bool Deleted { get; set; } + + public float GetLikePercentage() + { + return Likes / (float)(Likes + Dislikes) * 100; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Utils.cs b/core/InnerTube/Utils.cs new file mode 100644 index 00000000..38a3f668 --- /dev/null +++ b/core/InnerTube/Utils.cs @@ -0,0 +1,457 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web; +using System.Xml; +using InnerTube.Models; +using Newtonsoft.Json.Linq; + +namespace InnerTube +{ + public static class Utils + { + private static string Sapisid; + private static string Psid; + private static bool UseAuthorization; + + public static string GetHtmlDescription(string description) => description?.Replace("\n", "
") ?? ""; + + public static string GetMpdManifest(this YoutubePlayer player, string proxyUrl, string videoCodec = null, string audioCodec = null) + { + XmlDocument doc = new(); + + XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null); + XmlElement root = doc.DocumentElement; + doc.InsertBefore(xmlDeclaration, root); + + XmlElement mpdRoot = doc.CreateElement(string.Empty, "MPD", string.Empty); + mpdRoot.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + mpdRoot.SetAttribute("xmlns", "urn:mpeg:dash:schema:mpd:2011"); + mpdRoot.SetAttribute("xsi:schemaLocation", "urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd"); + //mpdRoot.SetAttribute("profiles", "urn:mpeg:dash:profile:isoff-on-demand:2011"); + mpdRoot.SetAttribute("profiles", "urn:mpeg:dash:profile:isoff-main:2011"); + mpdRoot.SetAttribute("type", "static"); + mpdRoot.SetAttribute("minBufferTime", "PT1.500S"); + TimeSpan durationTs = TimeSpan.FromMilliseconds(double.Parse(HttpUtility + .ParseQueryString(player.Formats.First().Url.Split("?")[1]) + .Get("dur")?.Replace(".", "") ?? "0")); + StringBuilder duration = new("PT"); + if (durationTs.TotalHours > 0) + duration.Append($"{durationTs.Hours}H"); + if (durationTs.Minutes > 0) + duration.Append($"{durationTs.Minutes}M"); + if (durationTs.Seconds > 0) + duration.Append(durationTs.Seconds); + mpdRoot.SetAttribute("mediaPresentationDuration", $"{duration}.{durationTs.Milliseconds}S"); + doc.AppendChild(mpdRoot); + + XmlElement period = doc.CreateElement("Period"); + + period.AppendChild(doc.CreateComment("Audio Adaptation Set")); + XmlElement audioAdaptationSet = doc.CreateElement("AdaptationSet"); + List audios; + if (audioCodec != "all") + audios = player.AdaptiveFormats + .Where(x => x.AudioSampleRate.HasValue && x.FormatId != "17" && + (audioCodec == null || x.AudioCodec.ToLower().Contains(audioCodec.ToLower()))) + .GroupBy(x => x.FormatNote) + .Select(x => x.Last()) + .ToList(); + else + audios = player.AdaptiveFormats + .Where(x => x.AudioSampleRate.HasValue && x.FormatId != "17") + .ToList(); + + audioAdaptationSet.SetAttribute("mimeType", + HttpUtility.ParseQueryString(audios.First().Url.Split("?")[1]).Get("mime")); + audioAdaptationSet.SetAttribute("subsegmentAlignment", "true"); + audioAdaptationSet.SetAttribute("contentType", "audio"); + foreach (Format format in audios) + { + XmlElement representation = doc.CreateElement("Representation"); + representation.SetAttribute("id", format.FormatId); + representation.SetAttribute("codecs", format.AudioCodec); + representation.SetAttribute("startWithSAP", "1"); + representation.SetAttribute("bandwidth", + Math.Floor((format.Filesize ?? 1) / (double)player.Duration).ToString()); + + XmlElement audioChannelConfiguration = doc.CreateElement("AudioChannelConfiguration"); + audioChannelConfiguration.SetAttribute("schemeIdUri", + "urn:mpeg:dash:23003:3:audio_channel_configuration:2011"); + audioChannelConfiguration.SetAttribute("value", "2"); + representation.AppendChild(audioChannelConfiguration); + + XmlElement baseUrl = doc.CreateElement("BaseURL"); + baseUrl.InnerText = string.IsNullOrWhiteSpace(proxyUrl) ? format.Url : $"{proxyUrl}media/{player.Id}/{format.FormatId}"; + representation.AppendChild(baseUrl); + + if (format.IndexRange != null && format.InitRange != null) + { + XmlElement segmentBase = doc.CreateElement("SegmentBase"); + segmentBase.SetAttribute("indexRange", $"{format.IndexRange.Start}-{format.IndexRange.End}"); + segmentBase.SetAttribute("indexRangeExact", "true"); + + XmlElement initialization = doc.CreateElement("Initialization"); + initialization.SetAttribute("range", $"{format.InitRange.Start}-{format.InitRange.End}"); + + segmentBase.AppendChild(initialization); + representation.AppendChild(segmentBase); + } + + audioAdaptationSet.AppendChild(representation); + } + + period.AppendChild(audioAdaptationSet); + + period.AppendChild(doc.CreateComment("Video Adaptation Set")); + + List videos; + if (videoCodec != "all") + videos = player.AdaptiveFormats.Where(x => !x.AudioSampleRate.HasValue && x.FormatId != "17" && + (videoCodec == null || x.VideoCodec.ToLower() + .Contains(videoCodec.ToLower()))) + .GroupBy(x => x.FormatNote) + .Select(x => x.Last()) + .ToList(); + else + videos = player.AdaptiveFormats.Where(x => x.Resolution != "audio only" && x.FormatId != "17").ToList(); + + + XmlElement videoAdaptationSet = doc.CreateElement("AdaptationSet"); + videoAdaptationSet.SetAttribute("mimeType", + HttpUtility.ParseQueryString(videos.FirstOrDefault()?.Url?.Split("?")[1] ?? "mime=video/mp4") + .Get("mime")); + videoAdaptationSet.SetAttribute("subsegmentAlignment", "true"); + videoAdaptationSet.SetAttribute("contentType", "video"); + + foreach (Format format in videos) + { + XmlElement representation = doc.CreateElement("Representation"); + representation.SetAttribute("id", format.FormatId); + representation.SetAttribute("codecs", format.VideoCodec); + representation.SetAttribute("startWithSAP", "1"); + string[] widthAndHeight = format.Resolution.Split("x"); + representation.SetAttribute("width", widthAndHeight[0]); + representation.SetAttribute("height", widthAndHeight[1]); + representation.SetAttribute("bandwidth", + Math.Floor((format.Filesize ?? 1) / (double)player.Duration).ToString()); + + XmlElement baseUrl = doc.CreateElement("BaseURL"); + baseUrl.InnerText = string.IsNullOrWhiteSpace(proxyUrl) ? format.Url : $"{proxyUrl}media/{player.Id}/{format.FormatId}"; + representation.AppendChild(baseUrl); + + if (format.IndexRange != null && format.InitRange != null) + { + XmlElement segmentBase = doc.CreateElement("SegmentBase"); + segmentBase.SetAttribute("indexRange", $"{format.IndexRange.Start}-{format.IndexRange.End}"); + segmentBase.SetAttribute("indexRangeExact", "true"); + + XmlElement initialization = doc.CreateElement("Initialization"); + initialization.SetAttribute("range", $"{format.InitRange.Start}-{format.InitRange.End}"); + + segmentBase.AppendChild(initialization); + representation.AppendChild(segmentBase); + } + + videoAdaptationSet.AppendChild(representation); + } + + period.AppendChild(videoAdaptationSet); + + period.AppendChild(doc.CreateComment("Subtitle Adaptation Sets")); + foreach (Subtitle subtitle in player.Subtitles ?? Array.Empty()) + { + period.AppendChild(doc.CreateComment(subtitle.Language)); + XmlElement adaptationSet = doc.CreateElement("AdaptationSet"); + adaptationSet.SetAttribute("mimeType", "text/vtt"); + adaptationSet.SetAttribute("lang", subtitle.Language); + + XmlElement representation = doc.CreateElement("Representation"); + representation.SetAttribute("id", $"caption_{subtitle.Language.ToLower()}"); + representation.SetAttribute("bandwidth", "256"); // ...why do we need this for a plaintext file + + XmlElement baseUrl = doc.CreateElement("BaseURL"); + string url = subtitle.Url; + url = url.Replace("fmt=srv3", "fmt=vtt"); + baseUrl.InnerText = string.IsNullOrWhiteSpace(proxyUrl) ? url : $"{proxyUrl}caption/{player.Id}/{subtitle.Language}"; + + representation.AppendChild(baseUrl); + adaptationSet.AppendChild(representation); + period.AppendChild(adaptationSet); + } + + mpdRoot.AppendChild(period); + return doc.OuterXml.Replace(" schemaLocation=\"", " xsi:schemaLocation=\""); + } + + public static async Task GetHlsManifest(this YoutubePlayer player, string proxyUrl) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("#EXTM3U"); + sb.AppendLine("##Generated by LightTube"); + sb.AppendLine("##Video ID: " + player.Id); + + sb.AppendLine("#EXT-X-VERSION:7"); + sb.AppendLine("#EXT-X-INDEPENDENT-SEGMENTS"); + + string hls = await new HttpClient().GetStringAsync(player.HlsManifestUrl); + string[] hlsLines = hls.Split("\n"); + foreach (string line in hlsLines) + { + if (line.StartsWith("#EXT-X-STREAM-INF:")) + sb.AppendLine(line); + if (line.StartsWith("http")) + { + Uri u = new(line); + sb.AppendLine($"{proxyUrl}/ytmanifest?path={HttpUtility.UrlEncode(u.PathAndQuery)}"); + } + } + + return sb.ToString(); + } + + public static string ReadRuns(JArray runs) + { + string str = ""; + foreach (JToken runToken in runs ?? new JArray()) + { + JObject run = runToken as JObject; + if (run is null) continue; + + if (run.ContainsKey("bold")) + { + str += "" + run["text"] + ""; + } + else if (run.ContainsKey("navigationEndpoint")) + { + if (run?["navigationEndpoint"]?["urlEndpoint"] is not null) + { + string url = run["navigationEndpoint"]?["urlEndpoint"]?["url"]?.ToString() ?? ""; + if (url.StartsWith("https://www.youtube.com/redirect")) + { + NameValueCollection qsl = HttpUtility.ParseQueryString(url.Split("?")[1]); + url = qsl["url"] ?? qsl["q"]; + } + + str += $"{run["text"]}"; + } + else if (run?["navigationEndpoint"]?["commandMetadata"] is not null) + { + string url = run["navigationEndpoint"]?["commandMetadata"]?["webCommandMetadata"]?["url"] + ?.ToString() ?? ""; + if (url.StartsWith("/")) + url = "https://youtube.com" + url; + str += $"{run["text"]}"; + } + } + else + { + str += run["text"]; + } + } + + return str; + } + + public static Thumbnail ParseThumbnails(JToken arg) => new() + { + Height = arg["height"]?.ToObject() ?? -1, + Url = arg["url"]?.ToString() ?? string.Empty, + Width = arg["width"]?.ToObject() ?? -1 + }; + + public static async Task GetAuthorizedPlayer(string id, HttpClient client) + { + HttpRequestMessage hrm = new(HttpMethod.Post, + "https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"); + + byte[] buffer = Encoding.UTF8.GetBytes( + RequestContext.BuildRequestContextJson(new Dictionary + { + ["videoId"] = id + })); + ByteArrayContent byteContent = new(buffer); + byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + hrm.Content = byteContent; + + if (UseAuthorization) + { + hrm.Headers.Add("Cookie", GenerateAuthCookie()); + hrm.Headers.Add("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0"); + hrm.Headers.Add("Authorization", GenerateAuthHeader()); + hrm.Headers.Add("X-Origin", "https://www.youtube.com"); + hrm.Headers.Add("X-Youtube-Client-Name", "1"); + hrm.Headers.Add("X-Youtube-Client-Version", "2.20210721.00.00"); + hrm.Headers.Add("Accept-Language", "en-US;q=0.8,en;q=0.7"); + hrm.Headers.Add("Origin", "https://www.youtube.com"); + hrm.Headers.Add("Referer", "https://www.youtube.com/watch?v=" + id); + } + + HttpResponseMessage ytPlayerRequest = await client.SendAsync(hrm); + return JObject.Parse(await ytPlayerRequest.Content.ReadAsStringAsync()); + } + + internal static string GenerateAuthHeader() + { + if (!UseAuthorization) return "None none"; + long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + string hashInput = timestamp + " " + Sapisid + " https://www.youtube.com"; + string hashDigest = GenerateSha1Hash(hashInput); + return $"SAPISIDHASH {timestamp}_{hashDigest}"; + } + + internal static string GenerateAuthCookie() => UseAuthorization ? $"SAPISID={Sapisid}; __Secure-3PAPISID={Sapisid}; __Secure-3PSID={Psid};" : ";"; + + private static string GenerateSha1Hash(string input) + { + using SHA1Managed sha1 = new(); + byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input)); + StringBuilder sb = new(hash.Length * 2); + foreach (byte b in hash) sb.Append(b.ToString("X2")); + return sb.ToString(); + } + + public static string GetExtension(this Format format) + { + if (format.VideoCodec != "none") return "mp4"; + else + switch (format.FormatId) + { + case "139": + case "140": + case "141": + case "256": + case "258": + case "327": + return "mp3"; + case "249": + case "250": + case "251": + case "338": + return "opus"; + } + + return "mp4"; + } + + public static void SetAuthorization(bool canUseAuthorizedEndpoints, string sapisid, string psid) + { + UseAuthorization = canUseAuthorizedEndpoints; + Sapisid = sapisid; + Psid = psid; + } + + internal static string GetCodec(string mimetypeString, bool audioCodec) + { + string acodec = ""; + string vcodec = ""; + + Match match = Regex.Match(mimetypeString, "codecs=\"([\\s\\S]+?)\""); + + string[] g = match.Groups[1].ToString().Split(","); + foreach (string codec in g) + { + switch (codec.Split(".")[0].Trim()) + { + case "avc1": + case "av01": + case "vp9": + case "mp4v": + vcodec = codec; + break; + case "mp4a": + case "opus": + acodec = codec; + break; + default: + Console.WriteLine("Unknown codec type: " + codec.Split(".")[0].Trim()); + break; + } + } + + return (audioCodec ? acodec : vcodec).Trim(); + } + + public static string GetFormatName(JToken formatToken) + { + string format = formatToken["itag"]?.ToString() switch + { + "160" => "144p", + "278" => "144p", + "330" => "144p", + "394" => "144p", + "694" => "144p", + + "133" => "240p", + "242" => "240p", + "331" => "240p", + "395" => "240p", + "695" => "240p", + + "134" => "360p", + "243" => "360p", + "332" => "360p", + "396" => "360p", + "696" => "360p", + + "135" => "480p", + "244" => "480p", + "333" => "480p", + "397" => "480p", + "697" => "480p", + + "136" => "720p", + "247" => "720p", + "298" => "720p", + "302" => "720p", + "334" => "720p", + "398" => "720p", + "698" => "720p", + + "137" => "1080p", + "299" => "1080p", + "248" => "1080p", + "303" => "1080p", + "335" => "1080p", + "399" => "1080p", + "699" => "1080p", + + "264" => "1440p", + "271" => "1440p", + "304" => "1440p", + "308" => "1440p", + "336" => "1440p", + "400" => "1440p", + "700" => "1440p", + + "266" => "2160p", + "305" => "2160p", + "313" => "2160p", + "315" => "2160p", + "337" => "2160p", + "401" => "2160p", + "701" => "2160p", + + "138" => "4320p", + "272" => "4320p", + "402" => "4320p", + "571" => "4320p", + + var _ => $"{formatToken["height"]}p", + }; + + return format == "p" + ? formatToken["audioQuality"]?.ToString().ToLowerInvariant() + : (formatToken["fps"]?.ToObject() ?? 0) > 30 + ? $"{format}{formatToken["fps"]}" + : format; + } + } +} \ No newline at end of file diff --git a/core/InnerTube/Youtube.cs b/core/InnerTube/Youtube.cs new file mode 100644 index 00000000..3465a68e --- /dev/null +++ b/core/InnerTube/Youtube.cs @@ -0,0 +1,790 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using InnerTube.Models; +using Newtonsoft.Json.Linq; + +namespace InnerTube +{ + public class Youtube + { + internal readonly HttpClient Client = new(); + + public readonly Dictionary> PlayerCache = new(); + + private readonly Dictionary ChannelTabParams = new() + { + [ChannelTabs.Home] = @"EghmZWF0dXJlZA%3D%3D", + [ChannelTabs.Videos] = @"EgZ2aWRlb3M%3D", + [ChannelTabs.Playlists] = @"EglwbGF5bGlzdHM%3D", + [ChannelTabs.Community] = @"Egljb21tdW5pdHk%3D", + [ChannelTabs.Channels] = @"EghjaGFubmVscw%3D%3D", + [ChannelTabs.About] = @"EgVhYm91dA%3D%3D" + }; + + private async Task MakeRequest(string endpoint, Dictionary postData, string language, + string region, string clientName = "WEB", string clientId = "1", string clientVersion = "2.20220405", bool authorized = false) + { + HttpRequestMessage hrm = new(HttpMethod.Post, + @$"https://www.youtube.com/youtubei/v1/{endpoint}?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"); + + byte[] buffer = Encoding.UTF8.GetBytes(RequestContext.BuildRequestContextJson(postData, language, region, clientName, clientVersion)); + ByteArrayContent byteContent = new(buffer); + if (authorized) + { + hrm.Headers.Add("Cookie", Utils.GenerateAuthCookie()); + hrm.Headers.Add("Authorization", Utils.GenerateAuthHeader()); + hrm.Headers.Add("X-Youtube-Client-Name", clientId); + hrm.Headers.Add("X-Youtube-Client-Version", clientVersion); + hrm.Headers.Add("Origin", "https://www.youtube.com"); + } + byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + hrm.Content = byteContent; + HttpResponseMessage ytPlayerRequest = await Client.SendAsync(hrm); + + return JObject.Parse(await ytPlayerRequest.Content.ReadAsStringAsync()); + } + + public async Task GetPlayerAsync(string videoId, string language = "en", string region = "US", bool iOS = false) + { + if (PlayerCache.Any(x => x.Key == videoId && x.Value.ExpireTime > DateTimeOffset.Now)) + { + CacheItem item = PlayerCache[videoId]; + item.Item.ExpiresInSeconds = ((int)(item.ExpireTime - DateTimeOffset.Now).TotalSeconds).ToString(); + return item.Item; + } + + JObject player = await MakeRequest("player", new Dictionary + { + ["videoId"] = videoId, + ["contentCheckOk"] = true, + ["racyCheckOk"] = true + }, language, region, iOS ? "IOS" : "ANDROID", iOS ? "5" : "3", "17.13.3", true); + + switch (player["playabilityStatus"]?["status"]?.ToString()) + { + case "OK": + YoutubeStoryboardSpec storyboardSpec = + new(player["storyboards"]?["playerStoryboardSpecRenderer"]?["spec"]?.ToString(), player["videoDetails"]?["lengthSeconds"]?.ToObject() ?? 0); + YoutubePlayer video = new() + { + Id = player["videoDetails"]?["videoId"]?.ToString(), + Title = player["videoDetails"]?["title"]?.ToString(), + Description = player["videoDetails"]?["shortDescription"]?.ToString(), + Tags = player["videoDetails"]?["keywords"]?.ToObject(), + Channel = new Channel + { + Name = player["videoDetails"]?["author"]?.ToString(), + Id = player["videoDetails"]?["channelId"]?.ToString(), + Avatars = Array.Empty() + }, + Duration = player["videoDetails"]?["lengthSeconds"]?.ToObject(), + IsLive = player["videoDetails"]?["isLiveContent"]?.ToObject() ?? false, + Chapters = Array.Empty(), + Thumbnails = player["videoDetails"]?["thumbnail"]?["thumbnails"]?.Select(x => new Thumbnail + { + Height = x["height"]?.ToObject() ?? -1, + Url = x["url"]?.ToString(), + Width = x["width"]?.ToObject() ?? -1 + }).ToArray(), + Formats = player["streamingData"]?["formats"]?.Select(x => new Format + { + FormatName = Utils.GetFormatName(x), + FormatId = x["itag"]?.ToString(), + FormatNote = x["quality"]?.ToString(), + Filesize = x["contentLength"]?.ToObject(), + Bitrate = x["bitrate"]?.ToObject() ?? 0, + AudioCodec = Utils.GetCodec(x["mimeType"]?.ToString(), true), + VideoCodec = Utils.GetCodec(x["mimeType"]?.ToString(), false), + AudioSampleRate = x["audioSampleRate"]?.ToObject(), + Resolution = $"{x["width"] ?? "0"}x{x["height"] ?? "0"}", + Url = x["url"]?.ToString() + }).ToArray() ?? Array.Empty(), + AdaptiveFormats = player["streamingData"]?["adaptiveFormats"]?.Select(x => new Format + { + FormatName = Utils.GetFormatName(x), + FormatId = x["itag"]?.ToString(), + FormatNote = x["quality"]?.ToString(), + Filesize = x["contentLength"]?.ToObject(), + Bitrate = x["bitrate"]?.ToObject() ?? 0, + AudioCodec = Utils.GetCodec(x["mimeType"].ToString(), true), + VideoCodec = Utils.GetCodec(x["mimeType"].ToString(), false), + AudioSampleRate = x["audioSampleRate"]?.ToObject(), + Resolution = $"{x["width"] ?? "0"}x{x["height"] ?? "0"}", + Url = x["url"]?.ToString(), + InitRange = x["initRange"]?.ToObject(), + IndexRange = x["indexRange"]?.ToObject() + }).ToArray() ?? Array.Empty(), + HlsManifestUrl = player["streamingData"]?["hlsManifestUrl"]?.ToString(), + Subtitles = player["captions"]?["playerCaptionsTracklistRenderer"]?["captionTracks"]?.Select( + x => new Subtitle + { + Ext = HttpUtility.ParseQueryString(x["baseUrl"].ToString()).Get("fmt"), + Language = Utils.ReadRuns(x["name"]?["runs"]?.ToObject()), + Url = x["baseUrl"].ToString() + }).ToArray(), + Storyboards = storyboardSpec.Urls.TryGetValue("L0", out string sb) ? new[] { sb } : Array.Empty(), + ExpiresInSeconds = player["streamingData"]?["expiresInSeconds"]?.ToString(), + ErrorMessage = null + }; + PlayerCache.Remove(videoId); + PlayerCache.Add(videoId, + new CacheItem(video, + TimeSpan.FromSeconds(int.Parse(video.ExpiresInSeconds ?? "21600")) + .Subtract(TimeSpan.FromHours(1)))); + return video; + case "LOGIN_REQUIRED": + return new YoutubePlayer + { + Id = "", + Title = "", + Description = "", + Tags = Array.Empty(), + Channel = new Channel + { + Name = "", + Id = "", + SubscriberCount = "", + Avatars = Array.Empty() + }, + Duration = 0, + IsLive = false, + Chapters = Array.Empty(), + Thumbnails = Array.Empty(), + Formats = Array.Empty(), + AdaptiveFormats = Array.Empty(), + Subtitles = Array.Empty(), + Storyboards = Array.Empty(), + ExpiresInSeconds = "0", + ErrorMessage = + "This video is age-restricted. Please contact this instances authors to update their configuration" + }; + default: + return new YoutubePlayer + { + Id = "", + Title = "", + Description = "", + Tags = Array.Empty(), + Channel = new Channel + { + Name = "", + Id = "", + SubscriberCount = "", + Avatars = Array.Empty() + }, + Duration = 0, + IsLive = false, + Chapters = Array.Empty(), + Thumbnails = Array.Empty(), + Formats = Array.Empty(), + AdaptiveFormats = Array.Empty(), + Subtitles = Array.Empty(), + Storyboards = Array.Empty(), + ExpiresInSeconds = "0", + ErrorMessage = player["playabilityStatus"]?["reason"]?.ToString() ?? "Something has gone *really* wrong" + }; + } + } + + public async Task GetVideoAsync(string videoId, string language = "en", string region = "US") + { + JObject player = await MakeRequest("next", new Dictionary + { + ["videoId"] = videoId + }, language, region); + + JToken[] contents = + (player?["contents"]?["twoColumnWatchNextResults"]?["results"]?["results"]?["contents"] + ?.ToObject() ?? new JArray()) + .SkipWhile(x => !x.First.Path.EndsWith("videoPrimaryInfoRenderer")).ToArray(); + + YoutubeVideo video = new(); + video.Id = player["currentVideoEndpoint"]?["watchEndpoint"]?["videoId"]?.ToString(); + try + { + + video.Title = Utils.ReadRuns( + contents[0] + ["videoPrimaryInfoRenderer"]?["title"]?["runs"]?.ToObject()); + video.Description = Utils.ReadRuns( + contents[1] + ["videoSecondaryInfoRenderer"]?["description"]?["runs"]?.ToObject()); + video.Views = contents[0] + ["videoPrimaryInfoRenderer"]?["viewCount"]?["videoViewCountRenderer"]?["viewCount"]?["simpleText"]?.ToString(); + video.Channel = new Channel + { + Name = + contents[1] + ["videoSecondaryInfoRenderer"]?["owner"]?["videoOwnerRenderer"]?["title"]?["runs"]?[0]?[ + "text"]?.ToString(), + Id = contents[1] + ["videoSecondaryInfoRenderer"]?["owner"]?["videoOwnerRenderer"]?["title"]?["runs"]?[0]? + ["navigationEndpoint"]?["browseEndpoint"]?["browseId"]?.ToString(), + SubscriberCount = + contents[1] + ["videoSecondaryInfoRenderer"]?["owner"]?["videoOwnerRenderer"]?["subscriberCountText"]?[ + "simpleText"]?.ToString(), + Avatars = + (contents[1][ + "videoSecondaryInfoRenderer"]?["owner"]?["videoOwnerRenderer"]?["thumbnail"]?[ + "thumbnails"] + ?.ToObject() ?? new JArray()).Select(Utils.ParseThumbnails).ToArray() + }; + video.UploadDate = contents[0][ + "videoPrimaryInfoRenderer"]?["dateText"]?["simpleText"]?.ToString(); + } + catch + { + video.Title ??= ""; + video.Description ??= ""; + video.Channel ??= new Channel + { + Name = "", + Id = "", + SubscriberCount = "", + Avatars = Array.Empty() + }; + video.UploadDate ??= ""; + } + video.Recommended = ParseRenderers( + player?["contents"]?["twoColumnWatchNextResults"]?["secondaryResults"]?["secondaryResults"]? + ["results"]?.ToObject() ?? new JArray()); + + return video; + } + + public async Task SearchAsync(string query, string continuation = null, + string language = "en", string region = "US") + { + Dictionary data = new(); + if (string.IsNullOrWhiteSpace(continuation)) + data.Add("query", query); + else + data.Add("continuation", continuation); + JObject search = await MakeRequest("search", data, language, region); + + return new YoutubeSearchResults + { + Refinements = search?["refinements"]?.ToObject() ?? Array.Empty(), + EstimatedResults = search?["estimatedResults"]?.ToObject() ?? 0, + Results = ParseRenderers( + search?["contents"]?["twoColumnSearchResultsRenderer"]?["primaryContents"]?["sectionListRenderer"]? + ["contents"]?[0]?["itemSectionRenderer"]?["contents"]?.ToObject() ?? + search?["onResponseReceivedCommands"]?[0]?["appendContinuationItemsAction"]?["continuationItems"]? + [0]?["itemSectionRenderer"]?["contents"]?.ToObject() ?? new JArray()), + ContinuationKey = + search?["contents"]?["twoColumnSearchResultsRenderer"]?["primaryContents"]?["sectionListRenderer"]? + ["contents"]?[1]?["continuationItemRenderer"]?["continuationEndpoint"]?["continuationCommand"]? + ["token"]?.ToString() ?? + search?["onResponseReceivedCommands"]?[0]?["appendContinuationItemsAction"]?["continuationItems"]? + [1]?["continuationItemRenderer"]?["continuationEndpoint"]?["continuationCommand"]?["token"] + ?.ToString() ?? "" + }; + } + + public async Task GetPlaylistAsync(string id, string continuation = null, + string language = "en", string region = "US") + { + Dictionary data = new(); + if (string.IsNullOrWhiteSpace(continuation)) + data.Add("browseId", "VL" + id); + else + data.Add("continuation", continuation); + JObject playlist = await MakeRequest("browse", data, language, region); + DynamicItem[] renderers = ParseRenderers( + playlist?["contents"]?["twoColumnBrowseResultsRenderer"]?["tabs"]?[0]?["tabRenderer"]?["content"]? + ["sectionListRenderer"]?["contents"]?[0]?["itemSectionRenderer"]?["contents"]?[0]? + ["playlistVideoListRenderer"]?["contents"]?.ToObject() ?? + playlist?["onResponseReceivedActions"]?[0]?["appendContinuationItemsAction"]?["continuationItems"] + ?.ToObject() ?? new JArray()); + + return new YoutubePlaylist + { + Id = id, + Title = playlist?["metadata"]?["playlistMetadataRenderer"]?["title"]?.ToString(), + Description = playlist?["metadata"]?["playlistMetadataRenderer"]?["description"]?.ToString(), + VideoCount = playlist?["sidebar"]?["playlistSidebarRenderer"]?["items"]?[0]?[ + "playlistSidebarPrimaryInfoRenderer"]?["stats"]?[0]?["runs"]?[0]?["text"]?.ToString(), + ViewCount = playlist?["sidebar"]?["playlistSidebarRenderer"]?["items"]?[0]?[ + "playlistSidebarPrimaryInfoRenderer"]?["stats"]?[1]?["simpleText"]?.ToString(), + LastUpdated = Utils.ReadRuns(playlist?["sidebar"]?["playlistSidebarRenderer"]?["items"]?[0]?[ + "playlistSidebarPrimaryInfoRenderer"]?["stats"]?[2]?["runs"]?.ToObject() ?? new JArray()), + Thumbnail = (playlist?["microformat"]?["microformatDataRenderer"]?["thumbnail"]?["thumbnails"] ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + Channel = new Channel + { + Name = + playlist?["sidebar"]?["playlistSidebarRenderer"]?["items"]?[1]? + ["playlistSidebarSecondaryInfoRenderer"]?["videoOwner"]?["videoOwnerRenderer"]?["title"]? + ["runs"]?[0]?["text"]?.ToString(), + Id = playlist?["sidebar"]?["playlistSidebarRenderer"]?["items"]?[1]? + ["playlistSidebarSecondaryInfoRenderer"]?["videoOwner"]?["videoOwnerRenderer"]? + ["navigationEndpoint"]?["browseEndpoint"]?["browseId"]?.ToString(), + SubscriberCount = "", + Avatars = + (playlist?["sidebar"]?["playlistSidebarRenderer"]?["items"]?[1]? + ["playlistSidebarSecondaryInfoRenderer"]?["videoOwner"]?["videoOwnerRenderer"]?["thumbnail"] + ?["thumbnails"] ?? new JArray()).Select(Utils.ParseThumbnails).ToArray() + }, + Videos = renderers.Where(x => x is not ContinuationItem).ToArray(), + ContinuationKey = renderers.FirstOrDefault(x => x is ContinuationItem)?.Id + }; + } + + public async Task GetChannelAsync(string id, ChannelTabs tab = ChannelTabs.Home, + string continuation = null, string language = "en", string region = "US") + { + Dictionary data = new(); + if (string.IsNullOrWhiteSpace(continuation)) + { + data.Add("browseId", id); + if (string.IsNullOrWhiteSpace(continuation)) + data.Add("params", ChannelTabParams[tab]); + } + else + { + data.Add("continuation", continuation); + } + + JObject channel = await MakeRequest("browse", data, language, region); + JArray mainArray = + (channel?["contents"]?["twoColumnBrowseResultsRenderer"]?["tabs"]?.ToObject() ?? new JArray()) + .FirstOrDefault(x => x?["tabRenderer"]?["selected"]?.ToObject() ?? false)?["tabRenderer"]?[ + "content"]? + ["sectionListRenderer"]?["contents"]?.ToObject(); + + return new YoutubeChannel + { + Id = channel?["metadata"]?["channelMetadataRenderer"]?["externalId"]?.ToString(), + Name = channel?["metadata"]?["channelMetadataRenderer"]?["title"]?.ToString(), + Url = channel?["metadata"]?["channelMetadataRenderer"]?["externalId"]?.ToString(), + Avatars = (channel?["metadata"]?["channelMetadataRenderer"]?["avatar"]?["thumbnails"] ?? new JArray()) + .Select(Utils.ParseThumbnails).ToArray(), + Banners = (channel?["header"]?["c4TabbedHeaderRenderer"]?["banner"]?["thumbnails"] ?? new JArray()) + .Select(Utils.ParseThumbnails).ToArray(), + Description = channel?["metadata"]?["channelMetadataRenderer"]?["description"]?.ToString(), + Videos = ParseRenderers(mainArray ?? + channel?["onResponseReceivedActions"]?[0]?["appendContinuationItemsAction"]? + ["continuationItems"]?.ToObject() ?? new JArray()), + Subscribers = channel?["header"]?["c4TabbedHeaderRenderer"]?["subscriberCountText"]?["simpleText"] + ?.ToString() + }; + } + + public async Task GetExploreAsync(string browseId = null, string continuation = null, string language = "en", string region = "US") + { + Dictionary data = new(); + if (string.IsNullOrWhiteSpace(continuation)) + { + data.Add("browseId", browseId ?? "FEexplore"); + } + else + { + data.Add("continuation", continuation); + } + + JObject explore = await MakeRequest("browse", data, language, region); + JToken[] token = + (explore?["contents"]?["twoColumnBrowseResultsRenderer"]?["tabs"]?[0]?["tabRenderer"]?["content"]? + ["sectionListRenderer"]?["contents"]?.ToObject() ?? new JArray()).Skip(1).ToArray(); + + JArray mainArray = new(token.Select(x => x is JObject obj ? obj : null).Where(x => x is not null)); + + return new YoutubeTrends + { + Categories = explore?["contents"]?["twoColumnBrowseResultsRenderer"]?["tabs"]?[0]?["tabRenderer"]?["content"]?["sectionListRenderer"]?["contents"]?[0]?["itemSectionRenderer"]?["contents"]?[0]?["destinationShelfRenderer"]?["destinationButtons"]?.Select( + x => + { + JToken rendererObject = x?["destinationButtonRenderer"]; + TrendCategory category = new() + { + Label = rendererObject?["label"]?["simpleText"]?.ToString(), + BackgroundImage = (rendererObject?["backgroundImage"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + Icon = (rendererObject?["iconImage"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + Id = $"{rendererObject?["onTap"]?["browseEndpoint"]?["browseId"]}" + }; + return category; + }).ToArray(), + Videos = ParseRenderers(mainArray) + }; + } + + public async Task GetLocalsAsync(string language = "en", string region = "US") + { + JObject locals = await MakeRequest("account/account_menu", new Dictionary(), language, + region); + + return new YoutubeLocals + { + Languages = + locals["actions"]?[0]?["openPopupAction"]?["popup"]?["multiPageMenuRenderer"]?["sections"]?[0]? + ["multiPageMenuSectionRenderer"]?["items"]?[1]?["compactLinkRenderer"]?["serviceEndpoint"]? + ["signalServiceEndpoint"]?["actions"]?[0]?["getMultiPageMenuAction"]?["menu"]? + ["multiPageMenuRenderer"]?["sections"]?[0]?["multiPageMenuSectionRenderer"]?["items"]? + .ToObject()?.ToDictionary( + x => x?["compactLinkRenderer"]?["serviceEndpoint"]?["signalServiceEndpoint"]? + ["actions"]?[0]?["selectLanguageCommand"]?["hl"]?.ToString(), + x => x?["compactLinkRenderer"]?["title"]?["simpleText"]?.ToString()), + Regions = + locals["actions"]?[0]?["openPopupAction"]?["popup"]?["multiPageMenuRenderer"]?["sections"]?[0]? + ["multiPageMenuSectionRenderer"]?["items"]?[2]?["compactLinkRenderer"]?["serviceEndpoint"]? + ["signalServiceEndpoint"]?["actions"]?[0]?["getMultiPageMenuAction"]?["menu"]? + ["multiPageMenuRenderer"]?["sections"]?[0]?["multiPageMenuSectionRenderer"]?["items"]? + .ToObject()?.ToDictionary( + x => x?["compactLinkRenderer"]?["serviceEndpoint"]?["signalServiceEndpoint"]? + ["actions"]?[0]?["selectCountryCommand"]?["gl"]?.ToString(), + x => x?["compactLinkRenderer"]?["title"]?["simpleText"]?.ToString()) + }; + } + + private DynamicItem[] ParseRenderers(JArray renderersArray) + { + List items = new(); + + foreach (JToken jToken in renderersArray) + { + JObject recommendationContainer = jToken as JObject; + string rendererName = recommendationContainer?.First?.Path.Split(".").Last() ?? ""; + JObject rendererItem = recommendationContainer?[rendererName]?.ToObject(); + switch (rendererName) + { + case "videoRenderer": + items.Add(new VideoItem + { + Id = rendererItem?["videoId"]?.ToString(), + Title = Utils.ReadRuns(rendererItem?["title"]?["runs"]?.ToObject() ?? + new JArray()), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + UploadedAt = rendererItem?["publishedTimeText"]?["simpleText"]?.ToString(), + Views = long.TryParse( + rendererItem?["viewCountText"]?["simpleText"]?.ToString().Split(" ")[0] + .Replace(",", "").Replace(".", "") ?? "0", out long vV) ? vV : 0, + Channel = new Channel + { + Name = rendererItem?["longBylineText"]?["runs"]?[0]?["text"]?.ToString(), + Id = rendererItem?["longBylineText"]?["runs"]?[0]?["navigationEndpoint"]?[ + "browseEndpoint"]?["browseId"]?.ToString(), + SubscriberCount = null, + Avatars = + (rendererItem?["channelThumbnailSupportedRenderers"]?[ + "channelThumbnailWithLinkRenderer"]?["thumbnail"]?["thumbnails"] + ?.ToObject() ?? new JArray()).Select(Utils.ParseThumbnails) + .ToArray() + }, + Duration = rendererItem?["thumbnailOverlays"]?[0]?[ + "thumbnailOverlayTimeStatusRenderer"]?["text"]?["simpleText"]?.ToString(), + Description = Utils.ReadRuns(rendererItem?["detailedMetadataSnippets"]?[0]?[ + "snippetText"]?["runs"]?.ToObject() ?? new JArray()) + }); + break; + case "gridVideoRenderer": + items.Add(new VideoItem + { + Id = rendererItem?["videoId"]?.ToString(), + Title = rendererItem?["title"]?["simpleText"]?.ToString() ?? Utils.ReadRuns( + rendererItem?["title"]?["runs"]?.ToObject() ?? new JArray()), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + UploadedAt = rendererItem?["publishedTimeText"]?["simpleText"]?.ToString(), + Views = long.TryParse( + rendererItem?["viewCountText"]?["simpleText"]?.ToString().Split(" ")[0] + .Replace(",", "").Replace(".", "") ?? "0", out long gVV) ? gVV : 0, + Channel = null, + Duration = rendererItem?["thumbnailOverlays"]?[0]?[ + "thumbnailOverlayTimeStatusRenderer"]?["text"]?["simpleText"]?.ToString() + }); + break; + case "playlistRenderer": + items.Add(new PlaylistItem + { + Id = rendererItem?["playlistId"] + ?.ToString(), + Title = rendererItem?["title"]?["simpleText"] + ?.ToString(), + Thumbnails = + (rendererItem?["thumbnails"]?[0]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + VideoCount = int.TryParse( + rendererItem?["videoCountText"]?["runs"]?[0]?["text"]?.ToString().Replace(",", "") + .Replace(".", "") ?? "0", out int pVC) ? pVC : 0, + FirstVideoId = rendererItem?["navigationEndpoint"]?["watchEndpoint"]?["videoId"] + ?.ToString(), + Channel = new Channel + { + Name = rendererItem?["longBylineText"]?["runs"]?[0]?["text"] + ?.ToString(), + Id = rendererItem?["longBylineText"]?["runs"]?[0]?["navigationEndpoint"]?[ + "browseEndpoint"]?["browseId"] + ?.ToString(), + SubscriberCount = null, + Avatars = null + } + }); + break; + case "channelRenderer": + items.Add(new ChannelItem + { + Id = rendererItem?["channelId"]?.ToString(), + Title = rendererItem?["title"]?["simpleText"]?.ToString(), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"] + ?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails) + .ToArray(), // + Url = rendererItem?["navigationEndpoint"]?["commandMetadata"]?["webCommandMetadata"]?["url"] + ?.ToString(), + Description = + Utils.ReadRuns(rendererItem?["descriptionSnippet"]?["runs"]?.ToObject() ?? + new JArray()), + VideoCount = long.TryParse( + rendererItem?["videoCountText"]?["runs"]?[0]?["text"] + ?.ToString() + .Replace(",", + "") + .Replace(".", + "") ?? + "0", out long cVC) ? cVC : 0, + Subscribers = rendererItem?["subscriberCountText"]?["simpleText"]?.ToString() + }); + break; + case "radioRenderer": + items.Add(new RadioItem + { + Id = rendererItem?["playlistId"] + ?.ToString(), + Title = rendererItem?["title"]?["simpleText"] + ?.ToString(), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + FirstVideoId = rendererItem?["navigationEndpoint"]?["watchEndpoint"]?["videoId"] + ?.ToString(), + Channel = new Channel + { + Name = rendererItem?["longBylineText"]?["simpleText"]?.ToString(), + Id = "", + SubscriberCount = null, + Avatars = null + } + }); + break; + case "shelfRenderer": + items.Add(new ShelfItem + { + Title = rendererItem?["title"]?["simpleText"] + ?.ToString() ?? + rendererItem?["title"]?["runs"]?[0]?["text"] + ?.ToString(), + Thumbnails = (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + Items = ParseRenderers( + rendererItem?["content"]?["verticalListRenderer"]?["items"] + ?.ToObject() ?? + rendererItem?["content"]?["horizontalListRenderer"]?["items"] + ?.ToObject() ?? + rendererItem?["content"]?["expandedShelfContentsRenderer"]?["items"] + ?.ToObject() ?? + new JArray()), + CollapsedItemCount = + rendererItem?["content"]?["verticalListRenderer"]?["collapsedItemCount"] + ?.ToObject() ?? 0, + Badges = ParseRenderers(rendererItem?["badges"]?.ToObject() ?? new JArray()) + .Where(x => x is BadgeItem).Cast().ToArray(), + }); + break; + case "horizontalCardListRenderer": + items.Add(new HorizontalCardListItem + { + Title = rendererItem?["header"]?["richListHeaderRenderer"]?["title"]?["simpleText"] + ?.ToString(), + Items = ParseRenderers(rendererItem?["cards"]?.ToObject() ?? new JArray()) + }); + break; + case "searchRefinementCardRenderer": + items.Add(new CardItem + { + Title = Utils.ReadRuns(rendererItem?["query"]?["runs"]?.ToObject() ?? + new JArray()), + Thumbnails = (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray() + }); + break; + case "compactVideoRenderer": + items.Add(new VideoItem + { + Id = rendererItem?["videoId"]?.ToString(), + Title = rendererItem?["title"]?["simpleText"]?.ToString(), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + UploadedAt = rendererItem?["publishedTimeText"]?["simpleText"]?.ToString(), + Views = long.TryParse( + rendererItem?["viewCountText"]?["simpleText"]?.ToString().Split(" ")[0] + .Replace(",", "").Replace(".", "") ?? "0", out long cVV) ? cVV : 0, + Channel = new Channel + { + Name = rendererItem?["longBylineText"]?["runs"]?[0]?["text"]?.ToString(), + Id = rendererItem?["longBylineText"]?["runs"]?[0]?["navigationEndpoint"]?[ + "browseEndpoint"]?["browseId"]?.ToString(), + SubscriberCount = null, + Avatars = null + }, + Duration = rendererItem?["thumbnailOverlays"]?[0]?[ + "thumbnailOverlayTimeStatusRenderer"]?["text"]?["simpleText"]?.ToString() + }); + break; + case "compactPlaylistRenderer": + items.Add(new PlaylistItem + { + Id = rendererItem?["playlistId"] + ?.ToString(), + Title = rendererItem?["title"]?["simpleText"] + ?.ToString(), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"] + ?.ToObject() ?? new JArray()).Select(Utils.ParseThumbnails) + .ToArray(), + VideoCount = int.TryParse( + rendererItem?["videoCountText"]?["runs"]?[0]?["text"]?.ToString().Replace(",", "") + .Replace(".", "") ?? "0", out int cPVC) ? cPVC : 0, + FirstVideoId = rendererItem?["navigationEndpoint"]?["watchEndpoint"]?["videoId"] + ?.ToString(), + Channel = new Channel + { + Name = rendererItem?["longBylineText"]?["runs"]?[0]?["text"] + ?.ToString(), + Id = rendererItem?["longBylineText"]?["runs"]?[0]?["navigationEndpoint"]?[ + "browseEndpoint"]?["browseId"] + ?.ToString(), + SubscriberCount = null, + Avatars = null + } + }); + break; + case "compactRadioRenderer": + items.Add(new RadioItem + { + Id = rendererItem?["playlistId"] + ?.ToString(), + Title = rendererItem?["title"]?["simpleText"] + ?.ToString(), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"] + ?.ToObject() ?? new JArray()).Select(Utils.ParseThumbnails) + .ToArray(), + FirstVideoId = rendererItem?["navigationEndpoint"]?["watchEndpoint"]?["videoId"] + ?.ToString(), + Channel = new Channel + { + Name = rendererItem?["longBylineText"]?["simpleText"]?.ToString(), + Id = "", + SubscriberCount = null, + Avatars = null + } + }); + break; + case "continuationItemRenderer": + items.Add(new ContinuationItem + { + Id = rendererItem?["continuationEndpoint"]?["continuationCommand"]?["token"]?.ToString() + }); + break; + case "playlistVideoRenderer": + items.Add(new PlaylistVideoItem + { + Id = rendererItem?["videoId"]?.ToString(), + Index = rendererItem?["index"]?["simpleText"]?.ToObject() ?? 0, + Title = Utils.ReadRuns(rendererItem?["title"]?["runs"]?.ToObject() ?? + new JArray()), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + Channel = new Channel + { + Name = rendererItem?["shortBylineText"]?["runs"]?[0]?["text"]?.ToString(), + Id = rendererItem?["shortBylineText"]?["runs"]?[0]?["navigationEndpoint"]?[ + "browseEndpoint"]?["browseId"]?.ToString(), + SubscriberCount = null, + Avatars = null + }, + Duration = rendererItem?["lengthText"]?["simpleText"]?.ToString() + }); + break; + case "itemSectionRenderer": + items.Add(new ItemSectionItem + { + Contents = ParseRenderers(rendererItem?["contents"]?.ToObject() ?? new JArray()) + }); + break; + case "gridRenderer": + items.Add(new ItemSectionItem + { + Contents = ParseRenderers(rendererItem?["items"]?.ToObject() ?? new JArray()) + }); + break; + case "messageRenderer": + items.Add(new MessageItem + { + Title = rendererItem?["text"]?["simpleText"]?.ToString() + }); + break; + case "channelAboutFullMetadataRenderer": + items.Add(new ChannelAboutItem + { + Description = rendererItem?["description"]?["simpleText"]?.ToString(), + Country = rendererItem?["country"]?["simpleText"]?.ToString(), + Joined = Utils.ReadRuns(rendererItem?["joinedDateText"]?["runs"]?.ToObject() ?? + new JArray()), + ViewCount = rendererItem?["viewCountText"]?["simpleText"]?.ToString() + }); + break; + case "compactStationRenderer": + items.Add(new StationItem + { + Id = rendererItem?["navigationEndpoint"]?["watchEndpoint"]?["playlistId"]?.ToString(), + Title = rendererItem?["title"]?["simpleText"]?.ToString(), + Thumbnails = + (rendererItem?["thumbnail"]?["thumbnails"]?.ToObject() ?? + new JArray()).Select(Utils.ParseThumbnails).ToArray(), + VideoCount = rendererItem?["videoCountText"]?["runs"]?[0]?["text"].ToObject() ?? 0, + FirstVideoId = rendererItem?["navigationEndpoint"]?["watchEndpoint"]?["videoId"]?.ToString(), + Description = rendererItem?["description"]?["simpleText"]?.ToString() + }); + break; + case "metadataBadgeRenderer": + items.Add(new BadgeItem + { + Title = rendererItem?["label"]?.ToString(), + Style = rendererItem?["style"]?.ToString() + }); + break; + case "promotedSparklesWebRenderer": + // this is an ad + // no one likes ads + break; + default: + items.Add(new DynamicItem + { + Id = rendererName, + Title = rendererItem?.ToString() + }); + break; + } + } + + return items.ToArray(); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Contexts/BaseContext.cs b/core/LightTube/Contexts/BaseContext.cs new file mode 100644 index 00000000..a0c251e7 --- /dev/null +++ b/core/LightTube/Contexts/BaseContext.cs @@ -0,0 +1,7 @@ +namespace LightTube.Contexts +{ + public class BaseContext + { + public bool MobileLayout; + } +} \ No newline at end of file diff --git a/core/LightTube/Contexts/ErrorContext.cs b/core/LightTube/Contexts/ErrorContext.cs new file mode 100644 index 00000000..bb0b43ab --- /dev/null +++ b/core/LightTube/Contexts/ErrorContext.cs @@ -0,0 +1,7 @@ +namespace LightTube.Contexts +{ + public class ErrorContext : BaseContext + { + public string Path; + } +} \ No newline at end of file diff --git a/core/LightTube/Contexts/FeedContext.cs b/core/LightTube/Contexts/FeedContext.cs new file mode 100644 index 00000000..d3fbb19d --- /dev/null +++ b/core/LightTube/Contexts/FeedContext.cs @@ -0,0 +1,11 @@ +using LightTube.Database; + +namespace LightTube.Contexts +{ + public class FeedContext : BaseContext + { + public LTChannel[] Channels; + public FeedVideo[] Videos; + public string RssToken; + } +} \ No newline at end of file diff --git a/core/LightTube/Contexts/LocalsContext.cs b/core/LightTube/Contexts/LocalsContext.cs new file mode 100644 index 00000000..ef078459 --- /dev/null +++ b/core/LightTube/Contexts/LocalsContext.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using InnerTube.Models; + +namespace LightTube.Contexts +{ + public class LocalsContext : BaseContext + { + public Dictionary Languages; + public Dictionary Regions; + public string CurrentLanguage; + public string CurrentRegion; + } +} \ No newline at end of file diff --git a/core/LightTube/Contexts/PlaylistsContext.cs b/core/LightTube/Contexts/PlaylistsContext.cs new file mode 100644 index 00000000..3c34227c --- /dev/null +++ b/core/LightTube/Contexts/PlaylistsContext.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using InnerTube.Models; +using LightTube.Database; + +namespace LightTube.Contexts +{ + public class PlaylistsContext : BaseContext + { + public IEnumerable Playlists; + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/AccountController.cs b/core/LightTube/Controllers/AccountController.cs new file mode 100644 index 00000000..b0f49e81 --- /dev/null +++ b/core/LightTube/Controllers/AccountController.cs @@ -0,0 +1,351 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using System.Web; +using InnerTube; +using InnerTube.Models; +using LightTube.Contexts; +using LightTube.Database; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Primitives; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace LightTube.Controllers +{ + public class AccountController : Controller + { + private readonly Youtube _youtube; + + public AccountController(Youtube youtube) + { + _youtube = youtube; + } + + [Route("/Account")] + public IActionResult Account() + { + return View(new BaseContext + { + MobileLayout = Utils.IsClientMobile(Request) + }); + } + + [HttpGet] + public IActionResult Login(string err = null) + { + if (HttpContext.TryGetUser(out LTUser _, "web")) + return Redirect("/"); + + return View(new MessageContext + { + Message = err, + MobileLayout = Utils.IsClientMobile(Request) + }); + } + + [HttpPost] + public async Task Login(string userid, string password) + { + if (HttpContext.TryGetUser(out LTUser _, "web")) + return Redirect("/"); + + try + { + LTLogin login = await DatabaseManager.Logins.CreateToken(userid, password, Request.Headers["user-agent"], new []{"web"}); + Response.Cookies.Append("token", login.Token, new CookieOptions + { + Expires = DateTimeOffset.MaxValue + }); + + return Redirect("/"); + } + catch (KeyNotFoundException e) + { + return Redirect("/Account/Login?err=" + HttpUtility.UrlEncode(e.Message)); + } + catch (UnauthorizedAccessException e) + { + return Redirect("/Account/Login?err=" + HttpUtility.UrlEncode(e.Message)); + } + } + + public async Task Logout() + { + if (HttpContext.Request.Cookies.TryGetValue("token", out string token)) + { + await DatabaseManager.Logins.RemoveToken(token); + } + + HttpContext.Response.Cookies.Delete("token"); + HttpContext.Response.Cookies.Delete("account_data"); + return Redirect("/"); + } + + [HttpGet] + public IActionResult Register(string err = null) + { + if (HttpContext.TryGetUser(out LTUser _, "web")) + return Redirect("/"); + + return View(new MessageContext + { + Message = err, + MobileLayout = Utils.IsClientMobile(Request) + }); + } + + [HttpPost] + public async Task Register(string userid, string password) + { + if (HttpContext.TryGetUser(out LTUser _, "web")) + return Redirect("/"); + + try + { + await DatabaseManager.Logins.CreateUser(userid, password); + LTLogin login = await DatabaseManager.Logins.CreateToken(userid, password, Request.Headers["user-agent"], new []{"web"}); + Response.Cookies.Append("token", login.Token, new CookieOptions + { + Expires = DateTimeOffset.MaxValue + }); + + return Redirect("/"); + } + catch (DuplicateNameException e) + { + return Redirect("/Account/Register?err=" + HttpUtility.UrlEncode(e.Message)); + } + } + + public IActionResult RegisterLocal() + { + if (!HttpContext.TryGetUser(out LTUser _, "web")) + HttpContext.CreateLocalAccount(); + + return Redirect("/"); + } + + [HttpGet] + public IActionResult Delete(string err = null) + { + if (!HttpContext.TryGetUser(out LTUser _, "web")) + return Redirect("/"); + + return View(new MessageContext + { + Message = err, + MobileLayout = Utils.IsClientMobile(Request) + }); + } + + [HttpPost] + public async Task Delete(string userid, string password) + { + try + { + if (userid == "Local Account" && password == "local_account") + Response.Cookies.Delete("account_data"); + else + await DatabaseManager.Logins.DeleteUser(userid, password); + return Redirect("/Account/Register?err=Account+deleted"); + } + catch (KeyNotFoundException e) + { + return Redirect("/Account/Delete?err=" + HttpUtility.UrlEncode(e.Message)); + } + catch (UnauthorizedAccessException e) + { + return Redirect("/Account/Delete?err=" + HttpUtility.UrlEncode(e.Message)); + } + } + + public async Task Logins() + { + if (!HttpContext.TryGetUser(out LTUser _, "web") || !HttpContext.Request.Cookies.TryGetValue("token", out string token)) + return Redirect("/Account/Login"); + + return View(new LoginsContext + { + CurrentLogin = await DatabaseManager.Logins.GetCurrentLoginId(token), + Logins = await DatabaseManager.Logins.GetAllUserTokens(token), + MobileLayout = Utils.IsClientMobile(Request) + }); + } + + public async Task DisableLogin(string id) + { + if (!HttpContext.Request.Cookies.TryGetValue("token", out string token)) + return Redirect("/Account/Login"); + + try + { + await DatabaseManager.Logins.RemoveTokenFromId(token, id); + } catch { } + return Redirect("/Account/Logins"); + } + + public async Task Subscribe(string channel) + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + return Unauthorized(); + + try + { + YoutubeChannel youtubeChannel = await _youtube.GetChannelAsync(channel, ChannelTabs.About); + + (LTChannel channel, bool subscribed) result; + result.channel = await DatabaseManager.Channels.UpdateChannel(youtubeChannel.Id, youtubeChannel.Name, youtubeChannel.Subscribers, + youtubeChannel.Avatars.First().Url); + + if (user.PasswordHash == "local_account") + { + LTChannel ltChannel = await DatabaseManager.Channels.UpdateChannel(youtubeChannel.Id, youtubeChannel.Name, youtubeChannel.Subscribers, + youtubeChannel.Avatars.First().Url); + if (user.SubscribedChannels.Contains(ltChannel.ChannelId)) + user.SubscribedChannels.Remove(ltChannel.ChannelId); + else + user.SubscribedChannels.Add(ltChannel.ChannelId); + + HttpContext.Response.Cookies.Append("account_data", JsonConvert.SerializeObject(user), + new CookieOptions + { + Expires = DateTimeOffset.MaxValue + }); + + result.subscribed = user.SubscribedChannels.Contains(ltChannel.ChannelId); + } + else + { + result = + await DatabaseManager.Logins.SubscribeToChannel(user, youtubeChannel); + } + + return Ok(result.subscribed ? "true" : "false"); + } + catch + { + return Unauthorized(); + } + } + + public IActionResult SubscriptionsJson() + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + return Json(Array.Empty()); + try + { + return Json(user.SubscribedChannels); + } + catch + { + return Json(Array.Empty()); + } + } + + public async Task Settings() + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + Redirect("/Account/Login"); + + if (Request.Method == "POST") + { + CookieOptions opts = new() + { + Expires = DateTimeOffset.MaxValue + }; + foreach ((string key, StringValues value) in Request.Form) + { + switch (key) + { + case "theme": + Response.Cookies.Append("theme", value, opts); + break; + case "hl": + Response.Cookies.Append("hl", value, opts); + break; + case "gl": + Response.Cookies.Append("gl", value, opts); + break; + case "compatibility": + Response.Cookies.Append("compatibility", value, opts); + break; + case "api-access": + await DatabaseManager.Logins.SetApiAccess(user, bool.Parse(value)); + break; + } + } + return Redirect("/Account"); + } + + YoutubeLocals locals = await _youtube.GetLocalsAsync(); + + Request.Cookies.TryGetValue("theme", out string theme); + + bool compatibility = false; + if (Request.Cookies.TryGetValue("compatibility", out string compatibilityString)) + bool.TryParse(compatibilityString, out compatibility); + + return View(new SettingsContext + { + Languages = locals.Languages, + Regions = locals.Regions, + CurrentLanguage = HttpContext.GetLanguage(), + CurrentRegion = HttpContext.GetRegion(), + MobileLayout = Utils.IsClientMobile(Request), + Theme = theme ?? "light", + CompatibilityMode = compatibility, + ApiAccess = user.ApiAccess + }); + } + + public async Task AddVideoToPlaylist(string v) + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + Redirect("/Account/Login"); + + JObject ytPlayer = await InnerTube.Utils.GetAuthorizedPlayer(v, new HttpClient()); + return View(new AddToPlaylistContext + { + Id = v, + Video = await _youtube.GetVideoAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()), + Playlists = await DatabaseManager.Playlists.GetUserPlaylists(user.UserID), + Thumbnail = ytPlayer?["videoDetails"]?["thumbnail"]?["thumbnails"]?[0]?["url"]?.ToString() ?? $"https://i.ytimg.com/vi_webp/{v}/maxresdefault.webp", + MobileLayout = Utils.IsClientMobile(Request), + }); + } + + [HttpGet] + public IActionResult CreatePlaylist(string returnUrl = null) + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + Redirect("/Account/Login"); + + return View(new BaseContext + { + MobileLayout = Utils.IsClientMobile(Request), + }); + } + + [HttpPost] + public async Task CreatePlaylist() + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + Redirect("/Account/Login"); + + if (!Request.Form.ContainsKey("name") || string.IsNullOrWhiteSpace(Request.Form["name"])) return BadRequest(); + + LTPlaylist pl = await DatabaseManager.Playlists.CreatePlaylist( + user, + Request.Form["name"], + string.IsNullOrWhiteSpace(Request.Form["description"]) ? "" : Request.Form["description"], + Enum.Parse(string.IsNullOrWhiteSpace(Request.Form["visibility"]) ? "UNLISTED" : Request.Form["visibility"])); + + return Redirect($"/playlist?list={pl.Id}"); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/ApiController.cs b/core/LightTube/Controllers/ApiController.cs new file mode 100644 index 00000000..bcd7c8d6 --- /dev/null +++ b/core/LightTube/Controllers/ApiController.cs @@ -0,0 +1,187 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Xml; +using InnerTube; +using InnerTube.Models; +using Microsoft.AspNetCore.Mvc; + +namespace LightTube.Controllers +{ + [Route("/api")] + public class ApiController : Controller + { + private const string VideoIdRegex = @"[a-zA-Z0-9_-]{11}"; + private const string ChannelIdRegex = @"[a-zA-Z0-9_-]{24}"; + private const string PlaylistIdRegex = @"[a-zA-Z0-9_-]{34}"; + private readonly Youtube _youtube; + + public ApiController(Youtube youtube) + { + _youtube = youtube; + } + + private IActionResult Xml(XmlNode xmlDocument) + { + MemoryStream ms = new(); + ms.Write(Encoding.UTF8.GetBytes(xmlDocument.OuterXml)); + ms.Position = 0; + HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*"); + return File(ms, "application/xml"); + } + + [Route("player")] + public async Task GetPlayerInfo(string v) + { + if (v is null) + return GetErrorVideoPlayer("", "Missing YouTube ID (query parameter `v`)"); + + Regex regex = new(VideoIdRegex); + if (!regex.IsMatch(v) || v.Length != 11) + return GetErrorVideoPlayer(v, "Invalid YouTube ID " + v); + + try + { + YoutubePlayer player = + await _youtube.GetPlayerAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()); + XmlDocument xml = player.GetXmlDocument(); + return Xml(xml); + } + catch (Exception e) + { + return GetErrorVideoPlayer(v, e.Message); + } + } + + private IActionResult GetErrorVideoPlayer(string videoId, string message) + { + YoutubePlayer player = new() + { + Id = videoId, + Title = "", + Description = "", + Tags = Array.Empty(), + Channel = new Channel + { + Name = "", + Id = "", + Avatars = Array.Empty() + }, + Duration = 0, + Chapters = Array.Empty(), + Thumbnails = Array.Empty(), + Formats = Array.Empty(), + AdaptiveFormats = Array.Empty(), + Subtitles = Array.Empty(), + Storyboards = Array.Empty(), + ExpiresInSeconds = "0", + ErrorMessage = message + }; + return Xml(player.GetXmlDocument()); + } + + [Route("video")] + public async Task GetVideoInfo(string v) + { + if (v is null) + return GetErrorVideoPlayer("", "Missing YouTube ID (query parameter `v`)"); + + Regex regex = new(VideoIdRegex); + if (!regex.IsMatch(v) || v.Length != 11) + { + XmlDocument doc = new(); + XmlElement item = doc.CreateElement("Error"); + + item.InnerText = "Invalid YouTube ID " + v; + + doc.AppendChild(item); + return Xml(doc); + } + + YoutubeVideo player = await _youtube.GetVideoAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()); + XmlDocument xml = player.GetXmlDocument(); + return Xml(xml); + } + + [Route("search")] + public async Task Search(string query, string continuation = null) + { + if (string.IsNullOrWhiteSpace(query) && string.IsNullOrWhiteSpace(continuation)) + { + XmlDocument doc = new(); + XmlElement item = doc.CreateElement("Error"); + + item.InnerText = "Invalid query " + query; + + doc.AppendChild(item); + return Xml(doc); + } + + YoutubeSearchResults player = await _youtube.SearchAsync(query, continuation, HttpContext.GetLanguage(), + HttpContext.GetRegion()); + XmlDocument xml = player.GetXmlDocument(); + return Xml(xml); + } + + [Route("playlist")] + public async Task Playlist(string id, string continuation = null) + { + Regex regex = new(PlaylistIdRegex); + if (!regex.IsMatch(id) || id.Length != 34) return GetErrorVideoPlayer(id, "Invalid playlist ID " + id); + + + if (string.IsNullOrWhiteSpace(id) && string.IsNullOrWhiteSpace(continuation)) + { + XmlDocument doc = new(); + XmlElement item = doc.CreateElement("Error"); + + item.InnerText = "Invalid ID " + id; + + doc.AppendChild(item); + return Xml(doc); + } + + YoutubePlaylist player = await _youtube.GetPlaylistAsync(id, continuation, HttpContext.GetLanguage(), + HttpContext.GetRegion()); + XmlDocument xml = player.GetXmlDocument(); + return Xml(xml); + } + + [Route("channel")] + public async Task Channel(string id, ChannelTabs tab = ChannelTabs.Home, + string continuation = null) + { + Regex regex = new(ChannelIdRegex); + if (!regex.IsMatch(id) || id.Length != 24) return GetErrorVideoPlayer(id, "Invalid channel ID " + id); + + if (string.IsNullOrWhiteSpace(id) && string.IsNullOrWhiteSpace(continuation)) + { + XmlDocument doc = new(); + XmlElement item = doc.CreateElement("Error"); + + item.InnerText = "Invalid ID " + id; + + doc.AppendChild(item); + return Xml(doc); + } + + YoutubeChannel player = await _youtube.GetChannelAsync(id, tab, continuation, HttpContext.GetLanguage(), + HttpContext.GetRegion()); + XmlDocument xml = player.GetXmlDocument(); + return Xml(xml); + } + + [Route("trending")] + public async Task Trending(string id, string continuation = null) + { + YoutubeTrends player = await _youtube.GetExploreAsync(id, continuation, + HttpContext.GetLanguage(), + HttpContext.GetRegion()); + XmlDocument xml = player.GetXmlDocument(); + return Xml(xml); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/AuthorizedApiController.cs b/core/LightTube/Controllers/AuthorizedApiController.cs new file mode 100644 index 00000000..72a1e061 --- /dev/null +++ b/core/LightTube/Controllers/AuthorizedApiController.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Xml; +using InnerTube; +using InnerTube.Models; +using LightTube.Database; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Primitives; + +namespace LightTube.Controllers +{ + [Route("/api/auth")] + public class AuthorizedApiController : Controller + { + private readonly Youtube _youtube; + + private IReadOnlyList _scopes = new[] + { + "api.subscriptions.read", + "api.subscriptions.write" + }; + + public AuthorizedApiController(Youtube youtube) + { + _youtube = youtube; + } + + private IActionResult Xml(XmlNode xmlDocument, HttpStatusCode statusCode) + { + MemoryStream ms = new(); + ms.Write(Encoding.UTF8.GetBytes(xmlDocument.OuterXml)); + ms.Position = 0; + HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*"); + Response.StatusCode = (int)statusCode; + return File(ms, "application/xml"); + } + + private XmlNode BuildErrorXml(string message) + { + XmlDocument doc = new(); + XmlElement error = doc.CreateElement("Error"); + error.InnerText = message; + doc.AppendChild(error); + return doc; + } + + [HttpPost] + [Route("getToken")] + public async Task GetToken() + { + if (!Request.Headers.TryGetValue("User-Agent", out StringValues userAgent)) + return Xml(BuildErrorXml("Missing User-Agent header"), HttpStatusCode.BadRequest); + + Match match = Regex.Match(userAgent.ToString(), DatabaseManager.ApiUaRegex); + if (!match.Success) + return Xml(BuildErrorXml("Bad User-Agent header. Please see 'Documentation/API requests'"), HttpStatusCode.BadRequest); + if (match.Groups[1].ToString() != "1.0") + return Xml(BuildErrorXml($"Unknown API version {match.Groups[1]}"), HttpStatusCode.BadRequest); + + if (!Request.Form.TryGetValue("user", out StringValues user)) + return Xml(BuildErrorXml("Missing request value: 'user'"), HttpStatusCode.BadRequest); + if (!Request.Form.TryGetValue("password", out StringValues password)) + return Xml(BuildErrorXml("Missing request value: 'password'"), HttpStatusCode.BadRequest); + if (!Request.Form.TryGetValue("scopes", out StringValues scopes)) + return Xml(BuildErrorXml("Missing request value: 'scopes'"), HttpStatusCode.BadRequest); + + string[] newScopes = scopes.First().Split(","); + foreach (string s in newScopes) + if (!_scopes.Contains(s)) + return Xml(BuildErrorXml($"Unknown scope '{s}'"), HttpStatusCode.BadRequest); + + try + { + LTLogin ltLogin = + await DatabaseManager.Logins.CreateToken(user, password, userAgent.ToString(), + scopes.First().Split(",")); + return Xml(ltLogin.GetXmlElement(), HttpStatusCode.Created); + } + catch (UnauthorizedAccessException) + { + return Xml(BuildErrorXml("Invalid credentials"), HttpStatusCode.Unauthorized); + } + catch (InvalidOperationException) + { + return Xml(BuildErrorXml("User has API access disabled"), HttpStatusCode.Forbidden); + } + } + + [Route("subscriptions/feed")] + public async Task SubscriptionsFeed() + { + if (!HttpContext.TryGetUser(out LTUser user, "api.subscriptions.read")) + return Xml(BuildErrorXml("Unauthorized"), HttpStatusCode.Unauthorized); + + SubscriptionFeed feed = new() + { + videos = await YoutubeRSS.GetMultipleFeeds(user.SubscribedChannels) + }; + + return Xml(feed.GetXmlDocument(), HttpStatusCode.OK); + } + + [HttpGet] + [Route("subscriptions/channels")] + public IActionResult SubscriptionsChannels() + { + if (!HttpContext.TryGetUser(out LTUser user, "api.subscriptions.read")) + return Xml(BuildErrorXml("Unauthorized"), HttpStatusCode.Unauthorized); + + SubscriptionChannels feed = new() + { + Channels = user.SubscribedChannels.Select(DatabaseManager.Channels.GetChannel).ToArray() + }; + Array.Sort(feed.Channels, (p, q) => string.Compare(p.Name, q.Name, StringComparison.OrdinalIgnoreCase)); + + return Xml(feed.GetXmlDocument(), HttpStatusCode.OK); + } + + [HttpPut] + [Route("subscriptions/channels")] + public async Task Subscribe() + { + if (!HttpContext.TryGetUser(out LTUser user, "api.subscriptions.write")) + return Xml(BuildErrorXml("Unauthorized"), HttpStatusCode.Unauthorized); + + Request.Form.TryGetValue("id", out StringValues ids); + string id = ids.ToString(); + + if (user.SubscribedChannels.Contains(id)) + return StatusCode((int)HttpStatusCode.NotModified); + + try + { + YoutubeChannel channel = await _youtube.GetChannelAsync(id); + + if (channel.Id is null) + return StatusCode((int)HttpStatusCode.NotFound); + + (LTChannel ltChannel, bool _) = await DatabaseManager.Logins.SubscribeToChannel(user, channel); + + XmlDocument doc = new(); + doc.AppendChild(ltChannel.GetXmlElement(doc)); + return Xml(doc, HttpStatusCode.OK); + } + catch (Exception e) + { + return Xml(BuildErrorXml(e.Message), HttpStatusCode.InternalServerError); + } + } + + [HttpDelete] + [Route("subscriptions/channels")] + public async Task Unsubscribe() + { + if (!HttpContext.TryGetUser(out LTUser user, "api.subscriptions.write")) + return Xml(BuildErrorXml("Unauthorized"), HttpStatusCode.Unauthorized); + + Request.Form.TryGetValue("id", out StringValues ids); + string id = ids.ToString(); + + if (!user.SubscribedChannels.Contains(id)) + return StatusCode((int)HttpStatusCode.NotModified); + + try + { + YoutubeChannel channel = await _youtube.GetChannelAsync(id); + + if (channel.Id is null) + return StatusCode((int)HttpStatusCode.NotFound); + + (LTChannel ltChannel, bool _) = await DatabaseManager.Logins.SubscribeToChannel(user, channel); + + XmlDocument doc = new(); + doc.AppendChild(ltChannel.GetXmlElement(doc)); + return Xml(doc, HttpStatusCode.OK); + } + catch (Exception e) + { + return Xml(BuildErrorXml(e.Message), HttpStatusCode.InternalServerError); + } + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/FeedController.cs b/core/LightTube/Controllers/FeedController.cs new file mode 100644 index 00000000..a5227533 --- /dev/null +++ b/core/LightTube/Controllers/FeedController.cs @@ -0,0 +1,104 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using LightTube.Contexts; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using InnerTube; +using LightTube.Database; + +namespace LightTube.Controllers +{ + [Route("/feed")] + public class FeedController : Controller + { + private readonly ILogger _logger; + private readonly Youtube _youtube; + + public FeedController(ILogger logger, Youtube youtube) + { + _logger = logger; + _youtube = youtube; + } + + [Route("subscriptions")] + public async Task Subscriptions() + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + return Redirect("/Account/Login"); + + try + { + FeedContext context = new() + { + Channels = user.SubscribedChannels.Select(DatabaseManager.Channels.GetChannel).ToArray(), + Videos = await YoutubeRSS.GetMultipleFeeds(user.SubscribedChannels), + RssToken = user.RssToken, + MobileLayout = Utils.IsClientMobile(Request) + }; + Array.Sort(context.Channels, (p, q) => string.Compare(p.Name, q.Name, StringComparison.OrdinalIgnoreCase)); + return View(context); + } + catch + { + HttpContext.Response.Cookies.Delete("token"); + return Redirect("/Account/Login"); + } + } + + [Route("channels")] + public IActionResult Channels() + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + return Redirect("/Account/Login"); + + try + { + FeedContext context = new() + { + Channels = user.SubscribedChannels.Select(DatabaseManager.Channels.GetChannel).ToArray(), + Videos = null, + MobileLayout = Utils.IsClientMobile(Request) + }; + Array.Sort(context.Channels, (p, q) => string.Compare(p.Name, q.Name, StringComparison.OrdinalIgnoreCase)); + return View(context); + } + catch + { + HttpContext.Response.Cookies.Delete("token"); + return Redirect("/Account/Login"); + } + } + + [Route("explore")] + public IActionResult Explore() + { + return View(new BaseContext + { + MobileLayout = Utils.IsClientMobile(Request) + }); + } + + [Route("/feed/library")] + public async Task Playlists() + { + if (!HttpContext.TryGetUser(out LTUser user, "web")) + Redirect("/Account/Login"); + + return View(new PlaylistsContext + { + MobileLayout = Utils.IsClientMobile(Request), + Playlists = await DatabaseManager.Playlists.GetUserPlaylists(user.UserID) + }); + } + + [Route("/rss")] + public async Task Playlists(string token, int limit = 15) + { + if (!DatabaseManager.TryGetRssUser(token, out LTUser user)) + return Unauthorized(); + return File(Encoding.UTF8.GetBytes(await user.GenerateRssFeed(Request.Host.ToString(), Math.Clamp(limit, 0, 50))), "application/xml"); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/HomeController.cs b/core/LightTube/Controllers/HomeController.cs new file mode 100644 index 00000000..e6cda1e8 --- /dev/null +++ b/core/LightTube/Controllers/HomeController.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using LightTube.Contexts; +using LightTube.Models; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; +using InnerTube; +using InnerTube.Models; +using ErrorContext = LightTube.Contexts.ErrorContext; + +namespace LightTube.Controllers +{ + public class HomeController : Controller + { + private readonly ILogger _logger; + private readonly Youtube _youtube; + + public HomeController(ILogger logger, Youtube youtube) + { + _logger = logger; + _youtube = youtube; + } + + public IActionResult Index() + { + return View(new BaseContext + { + MobileLayout = Utils.IsClientMobile(Request) + }); + } + + [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] + public IActionResult Error() + { + return View(new ErrorContext + { + Path = HttpContext.Features.Get().Path, + MobileLayout = Utils.IsClientMobile(Request) + }); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/ManifestController.cs b/core/LightTube/Controllers/ManifestController.cs new file mode 100644 index 00000000..c3892753 --- /dev/null +++ b/core/LightTube/Controllers/ManifestController.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using InnerTube; +using InnerTube.Models; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json.Linq; + +namespace LightTube.Controllers +{ + [Route("/manifest")] + public class ManifestController : Controller + { + private readonly Youtube _youtube; + private readonly HttpClient _client = new(); + + public ManifestController(Youtube youtube) + { + _youtube = youtube; + } + + [Route("{v}")] + public async Task DefaultManifest(string v) + { + YoutubePlayer player = await _youtube.GetPlayerAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()); + if (!string.IsNullOrWhiteSpace(player.ErrorMessage)) + return StatusCode(500, player.ErrorMessage); + return Redirect(player.IsLive ? $"/manifest/{v}.m3u8" : $"/manifest/{v}.mpd" + Request.QueryString); + } + + [Route("{v}.mpd")] + public async Task DashManifest(string v, string videoCodec = null, string audioCodec = null, bool useProxy = true) + { + YoutubePlayer player = await _youtube.GetPlayerAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()); + string manifest = player.GetMpdManifest(useProxy ? $"https://{Request.Host}/proxy/" : null, videoCodec, audioCodec); + return File(Encoding.UTF8.GetBytes(manifest), "application/dash+xml"); + } + + [Route("{v}.m3u8")] + public async Task HlsManifest(string v, bool useProxy = true) + { + YoutubePlayer player = await _youtube.GetPlayerAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion(), true); + if (!string.IsNullOrWhiteSpace(player.ErrorMessage)) + return StatusCode(403, player.ErrorMessage); + + if (player.IsLive) + { + string manifest = await player.GetHlsManifest(useProxy ? $"https://{Request.Host}/proxy" : null); + return File(Encoding.UTF8.GetBytes(manifest), "application/vnd.apple.mpegurl"); + } + + if (useProxy) + return StatusCode(400, "HLS proxy for non-live videos are not supported at the moment."); + return Redirect(player.HlsManifestUrl); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/ProxyController.cs b/core/LightTube/Controllers/ProxyController.cs new file mode 100644 index 00000000..d1baedb1 --- /dev/null +++ b/core/LightTube/Controllers/ProxyController.cs @@ -0,0 +1,517 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web; +using InnerTube; +using InnerTube.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; + +namespace LightTube.Controllers +{ + [Route("/proxy")] + public class ProxyController : Controller + { + private readonly ILogger _logger; + private readonly Youtube _youtube; + private string[] BlockedHeaders = + { + "host", + "cookies" + }; + + public ProxyController(ILogger logger, Youtube youtube) + { + _logger = logger; + _youtube = youtube; + } + + [Route("media/{videoId}/{formatId}")] + public async Task Media(string videoId, string formatId) + { + try + { + YoutubePlayer player = await _youtube.GetPlayerAsync(videoId); + if (!string.IsNullOrWhiteSpace(player.ErrorMessage)) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(player.ErrorMessage)); + await Response.StartAsync(); + return; + } + + List formats = new(); + + formats.AddRange(player.Formats); + formats.AddRange(player.AdaptiveFormats); + + if (!formats.Any(x => x.FormatId == formatId)) + { + Response.StatusCode = (int) HttpStatusCode.NotFound; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes( + $"Format with ID {formatId} not found.\nAvailable IDs are: {string.Join(", ", formats.Select(x => x.FormatId.ToString()))}")); + await Response.StartAsync(); + return; + } + + string url = formats.First(x => x.FormatId == formatId).Url; + + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + request.Method = Request.Method; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + HttpWebResponse response; + + try + { + response = (HttpWebResponse) request.GetResponse(); + } + catch (WebException e) + { + response = e.Response as HttpWebResponse; + } + + if (response == null) + await Response.StartAsync(); + + foreach (string header in response.Headers.AllKeys) + if (Response.Headers.ContainsKey(header)) + Response.Headers[header] = response.Headers.Get(header); + else + Response.Headers.Add(header, response.Headers.Get(header)); + Response.StatusCode = (int) response.StatusCode; + + await using Stream stream = response.GetResponseStream(); + try + { + await stream.CopyToAsync(Response.Body, HttpContext.RequestAborted); + } + catch (Exception) + { + // an exception is thrown if the client suddenly stops streaming + } + + await Response.StartAsync(); + } + catch (Exception e) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(e.ToString())); + await Response.StartAsync(); + } + } + + [Route("download/{videoId}/{formatId}/{filename}")] + public async Task Download(string videoId, string formatId, string filename) + { + try + { + YoutubePlayer player = await _youtube.GetPlayerAsync(videoId); + if (!string.IsNullOrWhiteSpace(player.ErrorMessage)) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(player.ErrorMessage)); + await Response.StartAsync(); + return; + } + + List formats = new(); + + formats.AddRange(player.Formats); + formats.AddRange(player.AdaptiveFormats); + + if (!formats.Any(x => x.FormatId == formatId)) + { + Response.StatusCode = (int) HttpStatusCode.NotFound; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes( + $"Format with ID {formatId} not found.\nAvailable IDs are: {string.Join(", ", formats.Select(x => x.FormatId.ToString()))}")); + await Response.StartAsync(); + return; + } + + string url = formats.First(x => x.FormatId == formatId).Url; + + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + request.Method = Request.Method; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + HttpWebResponse response; + + try + { + response = (HttpWebResponse) request.GetResponse(); + } + catch (WebException e) + { + response = e.Response as HttpWebResponse; + } + + if (response == null) + await Response.StartAsync(); + + foreach (string header in response.Headers.AllKeys) + if (Response.Headers.ContainsKey(header)) + Response.Headers[header] = response.Headers.Get(header); + else + Response.Headers.Add(header, response.Headers.Get(header)); + Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{Regex.Replace(filename, @"[^\u0000-\u007F]+", string.Empty)}\""); + Response.StatusCode = (int) response.StatusCode; + + await using Stream stream = response.GetResponseStream(); + try + { + await stream.CopyToAsync(Response.Body, HttpContext.RequestAborted); + } + catch (Exception) + { + // an exception is thrown if the client suddenly stops streaming + } + + await Response.StartAsync(); + } + catch (Exception e) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(e.ToString())); + await Response.StartAsync(); + } + } + + [Route("caption/{videoId}/{language}")] + public async Task SubtitleProxy(string videoId, string language) + { + YoutubePlayer player = await _youtube.GetPlayerAsync(videoId); + if (!string.IsNullOrWhiteSpace(player.ErrorMessage)) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + return File(new MemoryStream(Encoding.UTF8.GetBytes(player.ErrorMessage)), + "text/plain"); + } + + string url = null; + Subtitle? subtitle = player.Subtitles.FirstOrDefault(x => string.Equals(x.Language, language, StringComparison.InvariantCultureIgnoreCase)); + if (subtitle is null) + { + Response.StatusCode = (int) HttpStatusCode.NotFound; + return File( + new MemoryStream(Encoding.UTF8.GetBytes( + $"There are no available subtitles for {language}. Available language codes are: {string.Join(", ", player.Subtitles.Select(x => $"\"{x.Language}\""))}")), + "text/plain"); + } + url = subtitle.Url.Replace("fmt=srv3", "fmt=vtt"); + + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + await using Stream stream = response.GetResponseStream(); + using StreamReader reader = new(stream); + + return File(new MemoryStream(Encoding.UTF8.GetBytes(await reader.ReadToEndAsync())), + "text/vtt"); + } + + [Route("image")] + [Obsolete("Use /proxy/thumbnail instead")] + public async Task ImageProxy(string url) + { + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + foreach (string header in response.Headers.AllKeys) + if (Response.Headers.ContainsKey(header)) + Response.Headers[header] = response.Headers.Get(header); + else + Response.Headers.Add(header, response.Headers.Get(header)); + Response.StatusCode = (int)response.StatusCode; + + await using Stream stream = response.GetResponseStream(); + await stream.CopyToAsync(Response.Body); + await Response.StartAsync(); + } + + [Route("thumbnail/{videoId}/{index:int}")] + public async Task ThumbnailProxy(string videoId, int index = 0) + { + YoutubePlayer player = await _youtube.GetPlayerAsync(videoId); + if (index == -1) index = player.Thumbnails.Length - 1; + if (index >= player.Thumbnails.Length) + { + Response.StatusCode = 404; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes( + $"Cannot find thumbnail #{index} for {videoId}. The maximum quality is {player.Thumbnails.Length - 1}")); + await Response.StartAsync(); + return; + } + + string url = player.Thumbnails.FirstOrDefault()?.Url; + + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + foreach (string header in response.Headers.AllKeys) + if (Response.Headers.ContainsKey(header)) + Response.Headers[header] = response.Headers.Get(header); + else + Response.Headers.Add(header, response.Headers.Get(header)); + Response.StatusCode = (int)response.StatusCode; + + await using Stream stream = response.GetResponseStream(); + await stream.CopyToAsync(Response.Body); + await Response.StartAsync(); + } + + [Route("storyboard/{videoId}")] + public async Task StoryboardProxy(string videoId) + { + try + { + YoutubePlayer player = await _youtube.GetPlayerAsync(videoId); + if (!string.IsNullOrWhiteSpace(player.ErrorMessage)) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(player.ErrorMessage)); + await Response.StartAsync(); + return; + } + + if (!player.Storyboards.Any()) + { + Response.StatusCode = (int) HttpStatusCode.NotFound; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes("No usable storyboard found.")); + await Response.StartAsync(); + return; + } + + string url = player.Storyboards.First(); + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + foreach (string header in response.Headers.AllKeys) + if (Response.Headers.ContainsKey(header)) + Response.Headers[header] = response.Headers.Get(header); + else + Response.Headers.Add(header, response.Headers.Get(header)); + Response.StatusCode = (int)response.StatusCode; + + await using Stream stream = response.GetResponseStream(); + await stream.CopyToAsync(Response.Body); + await Response.StartAsync(); + } + catch (Exception e) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(e.ToString())); + await Response.StartAsync(); + } + } + + [Route("hls")] + public async Task HlsProxy(string url) + { + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + await using Stream stream = response.GetResponseStream(); + using StreamReader reader = new(stream); + string manifest = await reader.ReadToEndAsync(); + StringBuilder proxyManifest = new (); + + foreach (string s in manifest.Split("\n")) + { + // also check if proxy enabled + proxyManifest.AppendLine(!s.StartsWith("http") + ? s + : $"https://{Request.Host}/proxy/video?url={HttpUtility.UrlEncode(s)}"); + } + + return File(new MemoryStream(Encoding.UTF8.GetBytes(proxyManifest.ToString())), + "application/vnd.apple.mpegurl"); + } + + [Route("manifest/{videoId}")] + public async Task ManifestProxy(string videoId, string formatId, bool useProxy = true) + { + YoutubePlayer player = await _youtube.GetPlayerAsync(videoId, iOS: true); + if (!string.IsNullOrWhiteSpace(player.ErrorMessage)) + { + Response.StatusCode = (int) HttpStatusCode.InternalServerError; + return File(new MemoryStream(Encoding.UTF8.GetBytes(player.ErrorMessage)), + "text/plain"); + } + + if (player.HlsManifestUrl == null) + { + Response.StatusCode = (int) HttpStatusCode.NotFound; + return File(new MemoryStream(Encoding.UTF8.GetBytes("This video does not have an HLS manifest URL")), + "text/plain"); + } + + string url = player.HlsManifestUrl; + + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + await using Stream stream = response.GetResponseStream(); + using StreamReader reader = new(stream); + string manifest = await reader.ReadToEndAsync(); + StringBuilder proxyManifest = new (); + + if (useProxy) + foreach (string s in manifest.Split("\n")) + { + // also check if proxy enabled + proxyManifest.AppendLine(!s.StartsWith("http") + ? s + : $"https://{Request.Host}/proxy/ytmanifest?path=" + HttpUtility.UrlEncode(s[46..])); + } + else + proxyManifest.Append(manifest); + + return File(new MemoryStream(Encoding.UTF8.GetBytes(proxyManifest.ToString())), + "application/vnd.apple.mpegurl"); + } + + [Route("ytmanifest")] + public async Task YoutubeManifestProxy(string path) + { + string url = "https://manifest.googlevideo.com" + path; + StringBuilder sb = new(); + + if (!url.StartsWith("http://") && !url.StartsWith("https://")) + url = "https://" + url; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + await using Stream stream = response.GetResponseStream(); + using StreamReader reader = new(stream); + string manifest = await reader.ReadToEndAsync(); + + foreach (string line in manifest.Split("\n")) + { + if (string.IsNullOrWhiteSpace(line)) + sb.AppendLine(); + else if (line.StartsWith("#")) + sb.AppendLine(line); + else + { + Uri u = new(line); + sb.AppendLine($"https://{Request.Host}/proxy/videoplayback?host={u.Host}&path={HttpUtility.UrlEncode(u.PathAndQuery)}"); + } + } + + return File(new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString())), + "application/vnd.apple.mpegurl"); + } + + [Route("videoplayback")] + public async Task VideoPlaybackProxy(string path, string host) + { + // make sure this is only used in livestreams + + string url = $"https://{host}{path}"; + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + foreach ((string header, StringValues values) in HttpContext.Request.Headers.Where(header => + !header.Key.StartsWith(":") && !BlockedHeaders.Contains(header.Key.ToLower()))) + foreach (string value in values) + request.Headers.Add(header, value); + + using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + await using Stream stream = response.GetResponseStream(); + + Response.ContentType = "application/octet-stream"; + await Response.StartAsync(); + await stream.CopyToAsync(Response.Body, HttpContext.RequestAborted); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/TogglesController.cs b/core/LightTube/Controllers/TogglesController.cs new file mode 100644 index 00000000..2ae78f43 --- /dev/null +++ b/core/LightTube/Controllers/TogglesController.cs @@ -0,0 +1,67 @@ +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace LightTube.Controllers +{ + [Route("/toggles")] + public class TogglesController : Controller + { + [Route("theme")] + public IActionResult ToggleTheme(string redirectUrl) + { + if (Request.Cookies.TryGetValue("theme", out string theme)) + Response.Cookies.Append("theme", theme switch + { + "light" => "dark", + "dark" => "light", + var _ => "dark" + }, new CookieOptions + { + Expires = DateTimeOffset.MaxValue + }); + else + Response.Cookies.Append("theme", "light"); + + return Redirect(redirectUrl); + } + + [Route("compatibility")] + public IActionResult ToggleCompatibility(string redirectUrl) + { + if (Request.Cookies.TryGetValue("compatibility", out string compatibility)) + Response.Cookies.Append("compatibility", compatibility switch + { + "true" => "false", + "false" => "true", + var _ => "true" + }, new CookieOptions + { + Expires = DateTimeOffset.MaxValue + }); + else + Response.Cookies.Append("compatibility", "true"); + + return Redirect(redirectUrl); + } + + [Route("collapse_guide")] + public IActionResult ToggleCollapseGuide(string redirectUrl) + { + if (Request.Cookies.TryGetValue("minmode", out string minmode)) + Response.Cookies.Append("minmode", minmode switch + { + "true" => "false", + "false" => "true", + var _ => "true" + }, new CookieOptions + { + Expires = DateTimeOffset.MaxValue + }); + else + Response.Cookies.Append("minmode", "true"); + + return Redirect(redirectUrl); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Controllers/YoutubeController.cs b/core/LightTube/Controllers/YoutubeController.cs new file mode 100644 index 00000000..596df1c5 --- /dev/null +++ b/core/LightTube/Controllers/YoutubeController.cs @@ -0,0 +1,226 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using LightTube.Contexts; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using InnerTube; +using InnerTube.Models; +using LightTube.Database; + +namespace LightTube.Controllers +{ + public class YoutubeController : Controller + { + private readonly ILogger _logger; + private readonly Youtube _youtube; + + public YoutubeController(ILogger logger, Youtube youtube) + { + _logger = logger; + _youtube = youtube; + } + + [Route("/watch")] + public async Task Watch(string v, string quality = null) + { + Task[] tasks = { + _youtube.GetPlayerAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()), + _youtube.GetVideoAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()), + ReturnYouTubeDislike.GetDislikes(v) + }; + await Task.WhenAll(tasks); + + bool cookieCompatibility = false; + if (Request.Cookies.TryGetValue("compatibility", out string compatibilityString)) + bool.TryParse(compatibilityString, out cookieCompatibility); + + PlayerContext context = new() + { + Player = (tasks[0] as Task)?.Result, + Video = (tasks[1] as Task)?.Result, + Engagement = (tasks[2] as Task)?.Result, + Resolution = quality ?? (tasks[0] as Task)?.Result.Formats.FirstOrDefault(x => x.FormatId != "17")?.FormatNote, + MobileLayout = Utils.IsClientMobile(Request), + CompatibilityMode = cookieCompatibility + }; + return View(context); + } + + [Route("/download")] + public async Task Download(string v) + { + Task[] tasks = { + _youtube.GetPlayerAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()), + _youtube.GetVideoAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()), + ReturnYouTubeDislike.GetDislikes(v) + }; + await Task.WhenAll(tasks); + + bool cookieCompatibility = false; + if (Request.Cookies.TryGetValue("compatibility", out string compatibilityString)) + bool.TryParse(compatibilityString, out cookieCompatibility); + + PlayerContext context = new() + { + Player = (tasks[0] as Task)?.Result, + Video = (tasks[1] as Task)?.Result, + Engagement = null, + MobileLayout = Utils.IsClientMobile(Request), + CompatibilityMode = cookieCompatibility + }; + return View(context); + } + + [Route("/embed/{v}")] + public async Task Embed(string v, string quality = null, bool compatibility = false) + { + Task[] tasks = { + _youtube.GetPlayerAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()), + _youtube.GetVideoAsync(v, HttpContext.GetLanguage(), HttpContext.GetRegion()), + ReturnYouTubeDislike.GetDislikes(v) + }; + try + { + await Task.WhenAll(tasks); + } + catch { } + + + bool cookieCompatibility = false; + if (Request.Cookies.TryGetValue("compatibility", out string compatibilityString)) + bool.TryParse(compatibilityString, out cookieCompatibility); + + PlayerContext context = new() + { + Player = (tasks[0] as Task)?.Result, + Video = (tasks[1] as Task)?.Result, + Engagement = (tasks[2] as Task)?.Result, + Resolution = quality ?? (tasks[0] as Task)?.Result.Formats.FirstOrDefault(x => x.FormatId != "17")?.FormatNote, + CompatibilityMode = compatibility || cookieCompatibility, + MobileLayout = Utils.IsClientMobile(Request) + }; + return View(context); + } + + [Route("/results")] + public async Task Search(string search_query, string continuation = null) + { + SearchContext context = new() + { + Query = search_query, + ContinuationKey = continuation, + MobileLayout = Utils.IsClientMobile(Request) + }; + if (!string.IsNullOrWhiteSpace(search_query)) + { + context.Results = await _youtube.SearchAsync(search_query, continuation, HttpContext.GetLanguage(), + HttpContext.GetRegion()); + Response.Cookies.Append("search_query", search_query); + } + else + { + context.Results = + new YoutubeSearchResults + { + Refinements = Array.Empty(), + EstimatedResults = 0, + Results = Array.Empty(), + ContinuationKey = null + }; + } + return View(context); + } + + [Route("/playlist")] + public async Task Playlist(string list, string continuation = null, int? delete = null, string add = null, string remove = null) + { + HttpContext.TryGetUser(out LTUser user, "web"); + + YoutubePlaylist pl = list.StartsWith("LT-PL") + ? await (await DatabaseManager.Playlists.GetPlaylist(list)).ToYoutubePlaylist() + : await _youtube.GetPlaylistAsync(list, continuation, HttpContext.GetLanguage(), HttpContext.GetRegion()); + + string message = ""; + + if (list.StartsWith("LT-PL") && (await DatabaseManager.Playlists.GetPlaylist(list)).Visibility == PlaylistVisibility.PRIVATE && pl.Channel.Name != user?.UserID) + pl = new YoutubePlaylist + { + Id = null, + Title = "", + Description = "", + VideoCount = "", + ViewCount = "", + LastUpdated = "", + Thumbnail = Array.Empty(), + Channel = new Channel + { + Name = "", + Id = "", + SubscriberCount = "", + Avatars = Array.Empty() + }, + Videos = Array.Empty(), + ContinuationKey = null + }; + + if (string.IsNullOrWhiteSpace(pl.Title)) message = "Playlist unavailable"; + + if (list.StartsWith("LT-PL") && pl.Channel.Name == user?.UserID) + { + if (delete != null) + { + LTVideo removed = await DatabaseManager.Playlists.RemoveVideoFromPlaylist(list, delete.Value); + message += $"Removed video '{removed.Title}'"; + } + + if (add != null) + { + LTVideo added = await DatabaseManager.Playlists.AddVideoToPlaylist(list, add); + message += $"Added video '{added.Title}'"; + } + + if (!string.IsNullOrWhiteSpace(remove)) + { + await DatabaseManager.Playlists.DeletePlaylist(list); + message = "Playlist deleted"; + } + + pl = await (await DatabaseManager.Playlists.GetPlaylist(list)).ToYoutubePlaylist(); + } + + PlaylistContext context = new() + { + Playlist = pl, + Id = list, + ContinuationToken = continuation, + MobileLayout = Utils.IsClientMobile(Request), + Message = message, + Editable = list.StartsWith("LT-PL") && pl.Channel.Name == user?.UserID + }; + return View(context); + } + + [Route("/channel/{id}")] + public async Task Channel(string id, string continuation = null) + { + ChannelContext context = new() + { + Channel = await _youtube.GetChannelAsync(id, ChannelTabs.Videos, continuation, HttpContext.GetLanguage(), HttpContext.GetRegion()), + Id = id, + ContinuationToken = continuation, + MobileLayout = Utils.IsClientMobile(Request) + }; + await DatabaseManager.Channels.UpdateChannel(context.Channel.Id, context.Channel.Name, context.Channel.Subscribers, + context.Channel.Avatars.First().Url.ToString()); + return View(context); + } + + [Route("/shorts/{id}")] + public IActionResult Shorts(string id) + { + // yea no fuck shorts + return Redirect("/watch?v=" + id); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/ChannelManager.cs b/core/LightTube/Database/ChannelManager.cs new file mode 100644 index 00000000..45a3d472 --- /dev/null +++ b/core/LightTube/Database/ChannelManager.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using MongoDB.Driver; + +namespace LightTube.Database +{ + public class ChannelManager + { + private static IMongoCollection _channelCacheCollection; + + public ChannelManager(IMongoCollection channelCacheCollection) + { + _channelCacheCollection = channelCacheCollection; + } + + public LTChannel GetChannel(string id) + { + LTChannel res = _channelCacheCollection.FindSync(x => x.ChannelId == id).FirstOrDefault(); + return res ?? new LTChannel + { + Name = "Unknown Channel", + ChannelId = id, + IconUrl = "", + Subscribers = "" + }; + } + + public async Task UpdateChannel(string id, string name, string subscribers, string iconUrl) + { + LTChannel channel = new() + { + ChannelId = id, + Name = name, + Subscribers = subscribers, + IconUrl = iconUrl + }; + if (channel.IconUrl is null && !string.IsNullOrWhiteSpace(GetChannel(id).IconUrl)) + channel.IconUrl = GetChannel(id).IconUrl; + if (await _channelCacheCollection.CountDocumentsAsync(x => x.ChannelId == id) > 0) + await _channelCacheCollection.ReplaceOneAsync(x => x.ChannelId == id, channel); + else + await _channelCacheCollection.InsertOneAsync(channel); + + return channel; + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/DatabaseManager.cs b/core/LightTube/Database/DatabaseManager.cs new file mode 100644 index 00000000..e742fb15 --- /dev/null +++ b/core/LightTube/Database/DatabaseManager.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using InnerTube; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using MongoDB.Driver; +using Newtonsoft.Json; + +namespace LightTube.Database +{ + public static class DatabaseManager + { + public static readonly string ApiUaRegex = "LightTubeApiClient\\/([0-9.]*) ([\\S]+?)\\/([0-9.]*) \\(([\\s\\S]+?)\\)"; + + private static IMongoCollection _userCollection; + private static IMongoCollection _tokenCollection; + private static IMongoCollection _channelCacheCollection; + private static IMongoCollection _playlistCollection; + private static IMongoCollection _videoCacheCollection; + public static LoginManager Logins { get; private set; } + public static ChannelManager Channels { get; private set; } + public static PlaylistManager Playlists { get; private set; } + + public static void Init(string connstr, Youtube youtube) + { + MongoClient client = new(connstr); + IMongoDatabase database = client.GetDatabase("lighttube"); + _userCollection = database.GetCollection("users"); + _tokenCollection = database.GetCollection("tokens"); + _playlistCollection = database.GetCollection("playlists"); + _channelCacheCollection = database.GetCollection("channelCache"); + _videoCacheCollection = database.GetCollection("videoCache"); + Logins = new LoginManager(_userCollection, _tokenCollection); + Channels = new ChannelManager(_channelCacheCollection); + Playlists = new PlaylistManager(_userCollection, _playlistCollection, _videoCacheCollection, youtube); + } + + public static void CreateLocalAccount(this HttpContext context) + { + bool accountExists = false; + + // Check local account + if (context.Request.Cookies.TryGetValue("account_data", out string accountJson)) + { + try + { + if (accountJson != null) + { + LTUser tempUser = JsonConvert.DeserializeObject(accountJson) ?? new LTUser(); + if (tempUser.UserID == "Local Account" && tempUser.PasswordHash == "local_account") + accountExists = true; + } + } + catch { } + } + + // Account already exists, just leave it there + if (accountExists) return; + + LTUser user = new() + { + UserID = "Local Account", + PasswordHash = "local_account", + SubscribedChannels = new List() + }; + + context.Response.Cookies.Append("account_data", JsonConvert.SerializeObject(user), new CookieOptions + { + Expires = DateTimeOffset.MaxValue + }); + } + + public static bool TryGetUser(this HttpContext context, out LTUser user, string requiredScope) + { + // Check local account + if (context.Request.Cookies.TryGetValue("account_data", out string accountJson)) + { + try + { + if (accountJson != null) + { + LTUser tempUser = JsonConvert.DeserializeObject(accountJson) ?? new LTUser(); + if (tempUser.UserID == "Local Account" && tempUser.PasswordHash == "local_account") + { + user = tempUser; + return true; + } + } + } + catch + { + user = null; + return false; + } + } + + // Check cloud account + if (!context.Request.Cookies.TryGetValue("token", out string token)) + if (context.Request.Headers.TryGetValue("Authorization", out StringValues tokens)) + token = tokens.ToString(); + else + { + user = null; + return false; + } + + try + { + if (token != null) + { + user = Logins.GetUserFromToken(token).Result; + LTLogin login = Logins.GetLoginFromToken(token).Result; + if (login.Scopes.Contains(requiredScope)) + { +#pragma warning disable 4014 + login.UpdateLastAccess(DateTimeOffset.Now); +#pragma warning restore 4014 + return true; + } + return false; + } + } + catch + { + user = null; + return false; + } + + user = null; + return false; + } + + public static bool TryGetRssUser(string token, out LTUser user) + { + if (token is null) + { + user = null; + return false; + } + + try + { + user = Logins.GetUserFromRssToken(token).Result; + return true; + } + catch + { + user = null; + return false; + } + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/LTChannel.cs b/core/LightTube/Database/LTChannel.cs new file mode 100644 index 00000000..86879d87 --- /dev/null +++ b/core/LightTube/Database/LTChannel.cs @@ -0,0 +1,31 @@ +using System.Xml; +using MongoDB.Bson.Serialization.Attributes; + +namespace LightTube.Database +{ + [BsonIgnoreExtraElements] + public class LTChannel + { + public string ChannelId; + public string Name; + public string Subscribers; + public string IconUrl; + + public XmlNode GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Channel"); + item.SetAttribute("id", ChannelId); + item.SetAttribute("subscribers", Subscribers); + + XmlElement title = doc.CreateElement("Name"); + title.InnerText = Name; + item.AppendChild(title); + + XmlElement thumbnail = doc.CreateElement("Avatar"); + thumbnail.InnerText = IconUrl; + item.AppendChild(thumbnail); + + return item; + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/LTLogin.cs b/core/LightTube/Database/LTLogin.cs new file mode 100644 index 00000000..b4ca748b --- /dev/null +++ b/core/LightTube/Database/LTLogin.cs @@ -0,0 +1,84 @@ +using System; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web; +using System.Xml; +using Humanizer; +using MongoDB.Bson.Serialization.Attributes; +using MyCSharp.HttpUserAgentParser; + +namespace LightTube.Database +{ + [BsonIgnoreExtraElements] + public class LTLogin + { + public string Identifier; + public string Email; + public string Token; + public string UserAgent; + public string[] Scopes; + public DateTimeOffset Created = DateTimeOffset.MinValue; + public DateTimeOffset LastSeen = DateTimeOffset.MinValue; + + public XmlDocument GetXmlElement() + { + XmlDocument doc = new(); + XmlElement login = doc.CreateElement("Login"); + login.SetAttribute("id", Identifier); + login.SetAttribute("user", Email); + + XmlElement token = doc.CreateElement("Token"); + token.InnerText = Token; + login.AppendChild(token); + + XmlElement scopes = doc.CreateElement("Scopes"); + foreach (string scope in Scopes) + { + XmlElement scopeElement = doc.CreateElement("Scope"); + scopeElement.InnerText = scope; + login.AppendChild(scopeElement); + } + login.AppendChild(scopes); + + doc.AppendChild(login); + return doc; + } + + public string GetTitle() + { + Match match = Regex.Match(UserAgent, DatabaseManager.ApiUaRegex); + if (match.Success) + return $"API App: {match.Groups[2]} {match.Groups[3]}"; + + HttpUserAgentInformation client = HttpUserAgentParser.Parse(UserAgent); + StringBuilder sb = new($"{client.Name} {client.Version}"); + if (client.Platform.HasValue) + sb.Append($" on {client.Platform.Value.PlatformType.ToString()}"); + return sb.ToString(); + } + + public string GetDescription() + { + StringBuilder sb = new(); + sb.AppendLine($"Created: {Created.Humanize(DateTimeOffset.Now)}"); + sb.AppendLine($"Last seen: {LastSeen.Humanize(DateTimeOffset.Now)}"); + + Match match = Regex.Match(UserAgent, DatabaseManager.ApiUaRegex); + if (match.Success) + { + sb.AppendLine($"API version: {HttpUtility.HtmlEncode(match.Groups[1])}"); + sb.AppendLine($"App info: {HttpUtility.HtmlEncode(match.Groups[4])}"); + sb.AppendLine("Allowed scopes:"); + foreach (string scope in Scopes) sb.AppendLine($"- {scope}"); + } + + return sb.ToString(); + } + + public async Task UpdateLastAccess(DateTimeOffset newTime) + { + await DatabaseManager.Logins.UpdateLastAccess(Identifier, newTime); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/LTPlaylist.cs b/core/LightTube/Database/LTPlaylist.cs new file mode 100644 index 00000000..48c8ec47 --- /dev/null +++ b/core/LightTube/Database/LTPlaylist.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using InnerTube.Models; + +namespace LightTube.Database +{ + public class LTPlaylist + { + public string Id; + public string Name; + public string Description; + public PlaylistVisibility Visibility; + public List VideoIds; + public string Author; + public DateTimeOffset LastUpdated; + + public async Task ToYoutubePlaylist() + { + List t = new(); + if (VideoIds.Count > 0) + t.Add(new Thumbnail { Url = $"https://i.ytimg.com/vi_webp/{VideoIds.First()}/maxresdefault.webp" }); + YoutubePlaylist playlist = new() + { + Id = Id, + Title = Name, + Description = Description, + VideoCount = VideoIds.Count.ToString(), + ViewCount = "0", + LastUpdated = "Last updated " + LastUpdated.ToString("MMMM dd, yyyy"), + Thumbnail = t.ToArray(), + Channel = new Channel + { + Name = Author, + Id = GenerateChannelId(), + SubscriberCount = "0 subscribers", + Avatars = Array.Empty() + }, + Videos = (await DatabaseManager.Playlists.GetPlaylistVideos(Id)).Select(x => + { + x.Index = VideoIds.IndexOf(x.Id) + 1; + return x; + }).Cast().ToArray(), + ContinuationKey = null + }; + return playlist; + } + + private string GenerateChannelId() + { + StringBuilder sb = new("LTU-" + Author.Trim() + "_"); + + string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + Random rng = new(Author.GetHashCode()); + while (sb.Length < 32) sb.Append(alphabet[rng.Next(0, alphabet.Length)]); + return sb.ToString(); + } + } + + public enum PlaylistVisibility + { + PRIVATE, + UNLISTED, + VISIBLE + } +} \ No newline at end of file diff --git a/core/LightTube/Database/LTUser.cs b/core/LightTube/Database/LTUser.cs new file mode 100644 index 00000000..54999f2f --- /dev/null +++ b/core/LightTube/Database/LTUser.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using System.Xml; +using MongoDB.Bson.Serialization.Attributes; + +namespace LightTube.Database +{ + [BsonIgnoreExtraElements] + public class LTUser + { + public string UserID; + public string PasswordHash; + public List SubscribedChannels; + public bool ApiAccess; + public string RssToken; + + public async Task GenerateRssFeed(string hostUrl, int limit) + { + XmlDocument document = new(); + XmlElement rss = document.CreateElement("rss"); + rss.SetAttribute("version", "2.0"); + + XmlElement channel = document.CreateElement("channel"); + + XmlElement title = document.CreateElement("title"); + title.InnerText = "LightTube subscriptions RSS feed for " + UserID; + channel.AppendChild(title); + + XmlElement description = document.CreateElement("description"); + description.InnerText = $"LightTube subscriptions RSS feed for {UserID} with {SubscribedChannels.Count} channels"; + channel.AppendChild(description); + + FeedVideo[] feeds = await YoutubeRSS.GetMultipleFeeds(SubscribedChannels); + IEnumerable feedVideos = feeds.Take(limit); + + foreach (FeedVideo video in feedVideos) + { + XmlElement item = document.CreateElement("item"); + + XmlElement id = document.CreateElement("id"); + id.InnerText = $"id:video:{video.Id}"; + item.AppendChild(id); + + XmlElement vtitle = document.CreateElement("title"); + vtitle.InnerText = video.Title; + item.AppendChild(vtitle); + + XmlElement vdescription = document.CreateElement("description"); + vdescription.InnerText = video.Description; + item.AppendChild(vdescription); + + XmlElement link = document.CreateElement("link"); + link.InnerText = $"https://{hostUrl}/watch?v={video.Id}"; + item.AppendChild(link); + + XmlElement published = document.CreateElement("pubDate"); + published.InnerText = video.PublishedDate.ToString("R"); + item.AppendChild(published); + + XmlElement author = document.CreateElement("author"); + + XmlElement name = document.CreateElement("name"); + name.InnerText = video.ChannelName; + author.AppendChild(name); + + XmlElement uri = document.CreateElement("uri"); + uri.InnerText = $"https://{hostUrl}/channel/{video.ChannelId}"; + author.AppendChild(uri); + + item.AppendChild(author); +/* + XmlElement mediaGroup = document.CreateElement("media_group"); + + XmlElement mediaTitle = document.CreateElement("media_title"); + mediaTitle.InnerText = video.Title; + mediaGroup.AppendChild(mediaTitle); + + XmlElement mediaThumbnail = document.CreateElement("media_thumbnail"); + mediaThumbnail.SetAttribute("url", video.Thumbnail); + mediaGroup.AppendChild(mediaThumbnail); + + XmlElement mediaContent = document.CreateElement("media_content"); + mediaContent.SetAttribute("url", $"https://{hostUrl}/embed/{video.Id}"); + mediaContent.SetAttribute("type", "text/html"); + mediaGroup.AppendChild(mediaContent); + + item.AppendChild(mediaGroup); +*/ + channel.AppendChild(item); + } + + rss.AppendChild(channel); + + document.AppendChild(rss); + return document.OuterXml;//.Replace("()) + { + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.SetAttribute("width", t.Width.ToString()); + thumbnail.SetAttribute("height", t.Height.ToString()); + thumbnail.InnerText = t.Url; + item.AppendChild(thumbnail); + } + + return item; + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/LoginManager.cs b/core/LightTube/Database/LoginManager.cs new file mode 100644 index 00000000..bcf6fb6e --- /dev/null +++ b/core/LightTube/Database/LoginManager.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using InnerTube.Models; +using MongoDB.Driver; + +namespace LightTube.Database +{ + public class LoginManager + { + private IMongoCollection _userCollection; + private IMongoCollection _tokenCollection; + + public LoginManager(IMongoCollection userCollection, IMongoCollection tokenCollection) + { + _userCollection = userCollection; + _tokenCollection = tokenCollection; + } + + public async Task CreateToken(string email, string password, string userAgent, string[] scopes) + { + IAsyncCursor users = await _userCollection.FindAsync(x => x.UserID == email); + if (!await users.AnyAsync()) + throw new UnauthorizedAccessException("Invalid credentials"); + LTUser user = (await _userCollection.FindAsync(x => x.UserID == email)).First(); + if (!BCrypt.Net.BCrypt.Verify(password, user.PasswordHash)) + throw new UnauthorizedAccessException("Invalid credentials"); + if (!scopes.Contains("web") && !user.ApiAccess) + throw new InvalidOperationException("This user has API access disabled"); + + LTLogin login = new() + { + Identifier = Guid.NewGuid().ToString(), + Email = email, + Token = GenerateToken(256), + UserAgent = userAgent, + Scopes = scopes.ToArray(), + Created = DateTimeOffset.Now, + LastSeen = DateTimeOffset.Now + }; + await _tokenCollection.InsertOneAsync(login); + return login; + } + + public async Task UpdateLastAccess(string id, DateTimeOffset offset) + { + LTLogin login = (await _tokenCollection.FindAsync(x => x.Identifier == id)).First(); + login.LastSeen = offset; + await _tokenCollection.ReplaceOneAsync(x => x.Identifier == id, login); + } + + public async Task RemoveToken(string token) + { + await _tokenCollection.FindOneAndDeleteAsync(t => t.Token == token); + } + + public async Task RemoveToken(string email, string password, string identifier) + { + IAsyncCursor users = await _userCollection.FindAsync(x => x.UserID == email); + if (!await users.AnyAsync()) + throw new KeyNotFoundException("Invalid credentials"); + LTUser user = (await _userCollection.FindAsync(x => x.UserID == email)).First(); + if (!BCrypt.Net.BCrypt.Verify(password, user.PasswordHash)) + throw new UnauthorizedAccessException("Invalid credentials"); + + await _tokenCollection.FindOneAndDeleteAsync(t => t.Identifier == identifier && t.Email == user.UserID); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public async Task RemoveTokenFromId(string sourceToken, string identifier) + { + LTLogin login = (await _tokenCollection.FindAsync(x => x.Token == sourceToken)).First(); + LTLogin deletedLogin = (await _tokenCollection.FindAsync(x => x.Identifier == identifier)).First(); + + if (login.Email == deletedLogin.Email) + await _tokenCollection.FindOneAndDeleteAsync(t => t.Identifier == identifier); + else + throw new UnauthorizedAccessException( + "Logged in user does not match the token that is supposed to be deleted"); + } + + public async Task GetUserFromToken(string token) + { + string email = (await _tokenCollection.FindAsync(x => x.Token == token)).First().Email; + return (await _userCollection.FindAsync(u => u.UserID == email)).First(); + } + + public async Task GetUserFromRssToken(string token) => (await _userCollection.FindAsync(u => u.RssToken == token)).First(); + + public async Task GetLoginFromToken(string token) + { + var res = await _tokenCollection.FindAsync(x => x.Token == token); + return res.First(); + } + + public async Task> GetAllUserTokens(string token) + { + string email = (await _tokenCollection.FindAsync(x => x.Token == token)).First().Email; + return await (await _tokenCollection.FindAsync(u => u.Email == email)).ToListAsync(); + } + + public async Task GetCurrentLoginId(string token) + { + return (await _tokenCollection.FindAsync(t => t.Token == token)).First().Identifier; + } + + public async Task<(LTChannel channel, bool subscribed)> SubscribeToChannel(LTUser user, YoutubeChannel channel) + { + LTChannel ltChannel = await DatabaseManager.Channels.UpdateChannel(channel.Id, channel.Name, channel.Subscribers, + channel.Avatars.FirstOrDefault()?.Url); + + if (user.SubscribedChannels.Contains(ltChannel.ChannelId)) + user.SubscribedChannels.Remove(ltChannel.ChannelId); + else + user.SubscribedChannels.Add(ltChannel.ChannelId); + + await _userCollection.ReplaceOneAsync(x => x.UserID == user.UserID, user); + return (ltChannel, user.SubscribedChannels.Contains(ltChannel.ChannelId)); + } + + public async Task SetApiAccess(LTUser user, bool access) + { + user.ApiAccess = access; + await _userCollection.ReplaceOneAsync(x => x.UserID == user.UserID, user); + } + + public async Task DeleteUser(string email, string password) + { + IAsyncCursor users = await _userCollection.FindAsync(x => x.UserID == email); + if (!await users.AnyAsync()) + throw new KeyNotFoundException("Invalid credentials"); + LTUser user = (await _userCollection.FindAsync(x => x.UserID == email)).First(); + if (!BCrypt.Net.BCrypt.Verify(password, user.PasswordHash)) + throw new UnauthorizedAccessException("Invalid credentials"); + + await _userCollection.DeleteOneAsync(x => x.UserID == email); + await _tokenCollection.DeleteManyAsync(x => x.Email == email); + foreach (LTPlaylist pl in await DatabaseManager.Playlists.GetUserPlaylists(email)) + await DatabaseManager.Playlists.DeletePlaylist(pl.Id); + } + + public async Task CreateUser(string email, string password) + { + IAsyncCursor users = await _userCollection.FindAsync(x => x.UserID == email); + if (await users.AnyAsync()) + throw new DuplicateNameException("A user with that email already exists"); + + LTUser user = new() + { + UserID = email, + PasswordHash = BCrypt.Net.BCrypt.HashPassword(password), + SubscribedChannels = new List(), + RssToken = GenerateToken(32) + }; + await _userCollection.InsertOneAsync(user); + } + + private string GenerateToken(int length) + { + string tokenAlphabet = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+*/()[]{}"; + Random rng = new(); + StringBuilder sb = new(); + for (int i = 0; i < length; i++) + sb.Append(tokenAlphabet[rng.Next(0, tokenAlphabet.Length)]); + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/PlaylistManager.cs b/core/LightTube/Database/PlaylistManager.cs new file mode 100644 index 00000000..4352e7f4 --- /dev/null +++ b/core/LightTube/Database/PlaylistManager.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using InnerTube; +using InnerTube.Models; +using MongoDB.Driver; +using Newtonsoft.Json.Linq; + +namespace LightTube.Database +{ + public class PlaylistManager + { + private IMongoCollection _userCollection; + private IMongoCollection _playlistCollection; + private IMongoCollection _videoCacheCollection; + private Youtube _youtube; + + public PlaylistManager(IMongoCollection userCollection, IMongoCollection playlistCollection, + IMongoCollection videoCacheCollection, Youtube youtube) + { + _userCollection = userCollection; + _playlistCollection = playlistCollection; + _videoCacheCollection = videoCacheCollection; + _youtube = youtube; + } + + public async Task CreatePlaylist(LTUser user, string name, string description, + PlaylistVisibility visibility, string idPrefix = null) + { + if (await _userCollection.CountDocumentsAsync(x => x.UserID == user.UserID) == 0) + throw new UnauthorizedAccessException("Local accounts cannot create playlists"); + + LTPlaylist pl = new() + { + Id = GenerateAuthorId(idPrefix), + Name = name, + Description = description, + Visibility = visibility, + VideoIds = new List(), + Author = user.UserID, + LastUpdated = DateTimeOffset.Now + }; + + await _playlistCollection.InsertOneAsync(pl).ConfigureAwait(false); + + return pl; + } + + public async Task GetPlaylist(string id) + { + IAsyncCursor cursor = await _playlistCollection.FindAsync(x => x.Id == id); + return await cursor.FirstOrDefaultAsync() ?? new LTPlaylist + { + Id = null, + Name = "", + Description = "", + Visibility = PlaylistVisibility.VISIBLE, + VideoIds = new List(), + Author = "", + LastUpdated = DateTimeOffset.MinValue + }; + } + + public async Task> GetPlaylistVideos(string id) + { + LTPlaylist pl = await GetPlaylist(id); + List videos = new(); + + foreach (string videoId in pl.VideoIds) + { + IAsyncCursor cursor = await _videoCacheCollection.FindAsync(x => x.Id == videoId); + videos.Add(await cursor.FirstAsync()); + } + + return videos; + } + + public async Task AddVideoToPlaylist(string playlistId, string videoId) + { + LTPlaylist pl = await GetPlaylist(playlistId); + YoutubeVideo vid = await _youtube.GetVideoAsync(videoId); + JObject ytPlayer = await InnerTube.Utils.GetAuthorizedPlayer(videoId, new HttpClient()); + + if (string.IsNullOrEmpty(vid.Id)) + throw new KeyNotFoundException($"Couldn't find a video with ID '{videoId}'"); + + LTVideo v = new() + { + Id = vid.Id, + Title = vid.Title, + Thumbnails = ytPlayer?["videoDetails"]?["thumbnail"]?["thumbnails"]?.ToObject() ?? new [] + { + new Thumbnail { Url = $"https://i.ytimg.com/vi_webp/{vid.Id}/maxresdefault.webp" } + }, + UploadedAt = vid.UploadDate, + Views = long.Parse(vid.Views.Split(" ")[0].Replace(",", "").Replace(".", "")), + Channel = vid.Channel, + Duration = GetDurationString(ytPlayer?["videoDetails"]?["lengthSeconds"]?.ToObject() ?? 0), + Index = pl.VideoIds.Count + }; + pl.VideoIds.Add(vid.Id); + + if (await _videoCacheCollection.CountDocumentsAsync(x => x.Id == vid.Id) == 0) + await _videoCacheCollection.InsertOneAsync(v); + else + await _videoCacheCollection.FindOneAndReplaceAsync(x => x.Id == vid.Id, v); + + UpdateDefinition update = Builders.Update + .Push(x => x.VideoIds, vid.Id); + _playlistCollection.FindOneAndUpdate(x => x.Id == playlistId, update); + + return v; + } + + public async Task RemoveVideoFromPlaylist(string playlistId, int videoIndex) + { + LTPlaylist pl = await GetPlaylist(playlistId); + + IAsyncCursor cursor = await _videoCacheCollection.FindAsync(x => x.Id == pl.VideoIds[videoIndex]); + LTVideo v = await cursor.FirstAsync(); + pl.VideoIds.RemoveAt(videoIndex); + + await _playlistCollection.FindOneAndReplaceAsync(x => x.Id == playlistId, pl); + + return v; + } + + public async Task> GetUserPlaylists(string userId) + { + IAsyncCursor cursor = await _playlistCollection.FindAsync(x => x.Author == userId); + + return cursor.ToEnumerable(); + } + + private string GetDurationString(long length) + { + string s = TimeSpan.FromSeconds(length).ToString(); + while (s.StartsWith("00:") && s.Length > 5) s = s[3..]; + return s; + } + + public static string GenerateAuthorId(string prefix) + { + StringBuilder sb = new(string.IsNullOrWhiteSpace(prefix) || prefix.Trim().Length > 20 + ? "LT-PL" + : "LT-PL-" + prefix.Trim() + "_"); + + string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + Random rng = new(); + while (sb.Length < 32) sb.Append(alphabet[rng.Next(0, alphabet.Length)]); + return sb.ToString(); + } + + public async Task DeletePlaylist(string playlistId) + { + await _playlistCollection.DeleteOneAsync(x => x.Id == playlistId); + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/SubscriptionChannels.cs b/core/LightTube/Database/SubscriptionChannels.cs new file mode 100644 index 00000000..551e4d21 --- /dev/null +++ b/core/LightTube/Database/SubscriptionChannels.cs @@ -0,0 +1,18 @@ +using System.Xml; + +namespace LightTube.Database +{ + public class SubscriptionChannels + { + public LTChannel[] Channels { get; set; } + + public XmlNode GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement feed = doc.CreateElement("Subscriptions"); + foreach (LTChannel channel in Channels) feed.AppendChild(channel.GetXmlElement(doc)); + doc.AppendChild(feed); + return doc; + } + } +} \ No newline at end of file diff --git a/core/LightTube/Database/SubscriptionFeed.cs b/core/LightTube/Database/SubscriptionFeed.cs new file mode 100644 index 00000000..ae343620 --- /dev/null +++ b/core/LightTube/Database/SubscriptionFeed.cs @@ -0,0 +1,18 @@ +using System.Xml; + +namespace LightTube.Database +{ + public class SubscriptionFeed + { + public FeedVideo[] videos; + + public XmlDocument GetXmlDocument() + { + XmlDocument doc = new(); + XmlElement feed = doc.CreateElement("Feed"); + foreach (FeedVideo feedVideo in videos) feed.AppendChild(feedVideo.GetXmlElement(doc)); + doc.AppendChild(feed); + return doc; + } + } +} \ No newline at end of file diff --git a/core/LightTube/LightTube.csproj b/core/LightTube/LightTube.csproj new file mode 100644 index 00000000..6e3abf1c --- /dev/null +++ b/core/LightTube/LightTube.csproj @@ -0,0 +1,19 @@ + + + + net5.0 + + + + + + + + + + + + + + + diff --git a/core/LightTube/Models/ErrorViewModel.cs b/core/LightTube/Models/ErrorViewModel.cs new file mode 100644 index 00000000..e0599a9e --- /dev/null +++ b/core/LightTube/Models/ErrorViewModel.cs @@ -0,0 +1,11 @@ +using System; + +namespace LightTube.Models +{ + public class ErrorViewModel + { + public string RequestId { get; set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + } +} \ No newline at end of file diff --git a/core/LightTube/Program.cs b/core/LightTube/Program.cs new file mode 100644 index 00000000..8b944285 --- /dev/null +++ b/core/LightTube/Program.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace LightTube +{ + public class Program + { + public static void Main(string[] args) + { + Configuration.LoadConfiguration(); + InnerTube.Utils.SetAuthorization(Configuration.Instance.Credentials.CanUseAuthorizedEndpoints(), + Configuration.Instance.Credentials.Sapisid, Configuration.Instance.Credentials.Psid); + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); + } +} \ No newline at end of file diff --git a/core/LightTube/Views/Account/Account.cshtml b/core/LightTube/Views/Account/Account.cshtml new file mode 100644 index 00000000..7faed537 --- /dev/null +++ b/core/LightTube/Views/Account/Account.cshtml @@ -0,0 +1,60 @@ +@using LightTube.Database +@using System.Web +@model LightTube.Contexts.BaseContext + +@{ + ViewBag.Title = "Account"; + Layout = "_Layout"; + + Context.Request.Cookies.TryGetValue("theme", out string theme); + if (!new[] { "light", "dark" }.Contains(theme)) theme = "light"; + + string newTheme = theme switch { + "light" => "dark", + "dark" => "light", + var _ => "dark" + }; + + bool compatibility = false; + if (Context.Request.Cookies.TryGetValue("compatibility", out string compatibilityString)) + bool.TryParse(compatibilityString, out compatibility); +} + + \ No newline at end of file diff --git a/core/LightTube/Views/Account/AddVideoToPlaylist.cshtml b/core/LightTube/Views/Account/AddVideoToPlaylist.cshtml new file mode 100644 index 00000000..ebc4b4b9 --- /dev/null +++ b/core/LightTube/Views/Account/AddVideoToPlaylist.cshtml @@ -0,0 +1,52 @@ +@using System.Web +@using LightTube.Database +@model LightTube.Contexts.AddToPlaylistContext + +@{ + ViewBag.Metadata = new Dictionary(); + ViewBag.Metadata["author"] = Model.Video.Channel.Name; + ViewBag.Metadata["og:title"] = Model.Video.Title; + ViewBag.Metadata["og:url"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}{Url.ActionContext.HttpContext.Request.Path}{Url.ActionContext.HttpContext.Request.QueryString}"; + ViewBag.Metadata["og:image"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Thumbnail)}"; + ViewBag.Metadata["twitter:card"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Thumbnail)}"; + ViewBag.Title = Model.Video.Title; + Layout = "_Layout"; +} + +
+
+
+ Watch +
+

@Model.Video.Title

+ @Model.Video.Views • @Model.Video.UploadDate + +
+
+

Add to one of these playlists:

+ + @foreach (LTPlaylist playlist in Model.Playlists) + { +
+ + +
+ + @playlist.Name + +
+ @playlist.VideoIds.Count videos +
+
+
+ } +
+
diff --git a/core/LightTube/Views/Account/CreatePlaylist.cshtml b/core/LightTube/Views/Account/CreatePlaylist.cshtml new file mode 100644 index 00000000..0a88b3bd --- /dev/null +++ b/core/LightTube/Views/Account/CreatePlaylist.cshtml @@ -0,0 +1,25 @@ +@model LightTube.Contexts.BaseContext + +@{ + ViewBag.Title = "Create Playlist"; + Layout = "_Layout"; +} + + diff --git a/core/LightTube/Views/Account/Delete.cshtml b/core/LightTube/Views/Account/Delete.cshtml new file mode 100644 index 00000000..843a3896 --- /dev/null +++ b/core/LightTube/Views/Account/Delete.cshtml @@ -0,0 +1,46 @@ +@using LightTube.Database +@model LightTube.Contexts.MessageContext +@{ + ViewData["Title"] = "Delete Account"; + Layout = "_Layout"; +} + +@if (!string.IsNullOrWhiteSpace(Model.Message)) +{ + +} + + \ No newline at end of file diff --git a/core/LightTube/Views/Account/Login.cshtml b/core/LightTube/Views/Account/Login.cshtml new file mode 100644 index 00000000..c0351b66 --- /dev/null +++ b/core/LightTube/Views/Account/Login.cshtml @@ -0,0 +1,29 @@ +@model LightTube.Contexts.MessageContext +@{ + ViewData["Title"] = "Login"; + Layout = "_Layout"; +} + +@if (!string.IsNullOrWhiteSpace(Model.Message)) +{ + +} + + \ No newline at end of file diff --git a/core/LightTube/Views/Account/Logins.cshtml b/core/LightTube/Views/Account/Logins.cshtml new file mode 100644 index 00000000..787ea260 --- /dev/null +++ b/core/LightTube/Views/Account/Logins.cshtml @@ -0,0 +1,18 @@ +@using LightTube.Database +@model LightTube.Contexts.LoginsContext +@{ + ViewData["Title"] = "Active Logins"; + Layout = "_Layout"; +} + +

Active Logins

+
+ @foreach (LTLogin login in Model.Logins) + { + + } +
\ No newline at end of file diff --git a/core/LightTube/Views/Account/Register.cshtml b/core/LightTube/Views/Account/Register.cshtml new file mode 100644 index 00000000..f1bee1ef --- /dev/null +++ b/core/LightTube/Views/Account/Register.cshtml @@ -0,0 +1,42 @@ +@model LightTube.Contexts.MessageContext +@{ + ViewData["Title"] = "Register"; + Layout = "_Layout"; +} + +@if (!string.IsNullOrWhiteSpace(Model.Message)) +{ + +} + + \ No newline at end of file diff --git a/core/LightTube/Views/Account/Settings.cshtml b/core/LightTube/Views/Account/Settings.cshtml new file mode 100644 index 00000000..0587aa10 --- /dev/null +++ b/core/LightTube/Views/Account/Settings.cshtml @@ -0,0 +1,63 @@ +@model LightTube.Contexts.SettingsContext + +@{ + ViewBag.Title = "Settings"; + Layout = "_Layout"; +} + + +
+
+

Settings

+
+ + +

This is the visual theme the website will use.

+
+
+ + +

The language YouTube will deliver the content in. This will not affect LightTube's UI language.

+
+
+ + +

The language YouTube will deliver the content for. It is used for the explore page and the recommendations.

+
+
+ + +

Player behaviour. DASH playback allows for resolutions over 720p, but it is not compatible in all browsers. (e.g: Firefox Mobile)

+
+
+ + +

This will allow apps to log in using your username and password

+
+ +
+
+ +
\ No newline at end of file diff --git a/core/LightTube/Views/Feed/Channels.cshtml b/core/LightTube/Views/Feed/Channels.cshtml new file mode 100644 index 00000000..31e8493c --- /dev/null +++ b/core/LightTube/Views/Feed/Channels.cshtml @@ -0,0 +1,26 @@ +@using LightTube.Database +@model LightTube.Contexts.FeedContext + +@{ + ViewBag.Title = "Channel list"; +} + +
+ @foreach (LTChannel channel in Model.Channels) + { + + } +
\ No newline at end of file diff --git a/core/LightTube/Views/Feed/Explore.cshtml b/core/LightTube/Views/Feed/Explore.cshtml new file mode 100644 index 00000000..c7836daa --- /dev/null +++ b/core/LightTube/Views/Feed/Explore.cshtml @@ -0,0 +1,8 @@ +@{ + ViewData["Title"] = "Explore"; + ViewData["SelectedGuideItem"] = "explore"; +} + +
+

Coming soon!

+
\ No newline at end of file diff --git a/core/LightTube/Views/Feed/Playlists.cshtml b/core/LightTube/Views/Feed/Playlists.cshtml new file mode 100644 index 00000000..aa270cd1 --- /dev/null +++ b/core/LightTube/Views/Feed/Playlists.cshtml @@ -0,0 +1,35 @@ +@using LightTube.Database +@model LightTube.Contexts.PlaylistsContext + +@{ + ViewData["Title"] = "Playlists"; + ViewData["SelectedGuideItem"] = "library"; + Layout = "_Layout"; +} + +
+

Playlists

+ @foreach (LTPlaylist playlist in Model.Playlists) + { + + } +
\ No newline at end of file diff --git a/core/LightTube/Views/Feed/Subscriptions.cshtml b/core/LightTube/Views/Feed/Subscriptions.cshtml new file mode 100644 index 00000000..cbc7fcfc --- /dev/null +++ b/core/LightTube/Views/Feed/Subscriptions.cshtml @@ -0,0 +1,55 @@ +@using Humanizer +@using LightTube.Database +@using System.Web +@model LightTube.Contexts.FeedContext +@{ + ViewData["Title"] = "Subscriptions"; + ViewData["SelectedGuideItem"] = "subs"; + + bool minMode = false; + if (Context.Request.Cookies.TryGetValue("minMode", out string minModeString)) + bool.TryParse(minModeString, out minMode); +} + +
+ + +
Manage Channels
+
+ + +
RSS Feed
+
+ @foreach (LTChannel channel in Model.Channels) + { + + +
@channel.Name
+
+ } +
+ +
+ @foreach (FeedVideo video in Model.Videos) + { +
+ + + + + + +
+ @video.Title +
+ @video.ChannelName +
+ @video.ViewCount views + + @video.PublishedDate.Humanize(DateTimeOffset.Now) +
+
+
+
+ } +
\ No newline at end of file diff --git a/core/LightTube/Views/Home/Index.cshtml b/core/LightTube/Views/Home/Index.cshtml new file mode 100644 index 00000000..17fb8789 --- /dev/null +++ b/core/LightTube/Views/Home/Index.cshtml @@ -0,0 +1,15 @@ +@model LightTube.Contexts.BaseContext +@{ + ViewBag.Metadata = new Dictionary + { + ["og:title"] = "LightTube", + ["og:url"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}{Url.ActionContext.HttpContext.Request.Path}{Url.ActionContext.HttpContext.Request.QueryString}", + ["og:description"] = "An alternative, privacy respecting front end for YouTube", + }; + ViewData["Title"] = "Home Page"; + ViewData["SelectedGuideItem"] = "home"; +} + +
+

@Configuration.Instance.Interface.MessageOfTheDay

+
\ No newline at end of file diff --git a/core/LightTube/Views/Shared/Error.cshtml b/core/LightTube/Views/Shared/Error.cshtml new file mode 100644 index 00000000..0c93851d --- /dev/null +++ b/core/LightTube/Views/Shared/Error.cshtml @@ -0,0 +1,17 @@ +@model LightTube.Contexts.ErrorContext +@{ + ViewData["Title"] = "Error"; +} + +

Error.

+

An error occurred while processing your request.

+

+ You can try other alternatives to access this resource such as: + + Invidious + + or + + YouTube + +

\ No newline at end of file diff --git a/core/LightTube/Views/Shared/_Layout.cshtml b/core/LightTube/Views/Shared/_Layout.cshtml new file mode 100644 index 00000000..ed51b6fd --- /dev/null +++ b/core/LightTube/Views/Shared/_Layout.cshtml @@ -0,0 +1,139 @@ +@using System.Web +@using LightTube.Contexts +@model LightTube.Contexts.BaseContext +@{ + bool compatibility = false; + if (Context.Request.Cookies.TryGetValue("compatibility", out string compatibilityString)) + bool.TryParse(compatibilityString, out compatibility); + + bool minMode = false; + if (Context.Request.Cookies.TryGetValue("minMode", out string minModeString)) + bool.TryParse(minModeString, out minMode); +} + + + + + + + + @if (ViewBag.Metadata is not null) + { + @foreach (KeyValuePair metaTag in ViewBag.Metadata) + { + if (metaTag.Key.StartsWith("og:")) + { + + } + else + { + + } + } + } + + @ViewData["Title"] - lighttube + @if ((ViewData["HideGuide"] ?? false).Equals(true)) + { + + } + @{ + Context.Request.Cookies.TryGetValue("theme", out string theme); + if (!new[] { "light", "dark" }.Contains(theme)) theme = "light"; + } + + @if (Model.MobileLayout) + { + + + } + else + { + + + } + + + + + +
+ +
+
+ + +
+
+
+ + + +
+ +
+ +
+ + + + + + +
+

+ About
+ How LightTube works
+ Source code + API + License
+ Running on LightTube v@(Utils.GetVersion()) +

+
+ +
+ @RenderBody() +
+ + +@await RenderSectionAsync("Scripts", required: false) + + diff --git a/core/LightTube/Views/Shared/_LoginLogoutPartial.cshtml b/core/LightTube/Views/Shared/_LoginLogoutPartial.cshtml new file mode 100644 index 00000000..fb47116a --- /dev/null +++ b/core/LightTube/Views/Shared/_LoginLogoutPartial.cshtml @@ -0,0 +1,16 @@ +@using LightTube.Database +@if (Context.TryGetUser(out LTUser user, "web")) +{ + + @if (user.PasswordHash != "local_account") + { + + } + +} +else +{ + + +} + diff --git a/core/LightTube/Views/Youtube/Channel.cshtml b/core/LightTube/Views/Youtube/Channel.cshtml new file mode 100644 index 00000000..0768d172 --- /dev/null +++ b/core/LightTube/Views/Youtube/Channel.cshtml @@ -0,0 +1,80 @@ +@using InnerTube.Models +@using System.Web +@model LightTube.Contexts.ChannelContext + +@{ + ViewBag.Metadata = new Dictionary(); + ViewBag.Metadata["og:title"] = Model.Channel.Name; + ViewBag.Metadata["og:url"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}{Url.ActionContext.HttpContext.Request.Path}{Url.ActionContext.HttpContext.Request.QueryString}"; + ViewBag.Metadata["og:image"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Channel.Avatars.FirstOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["twitter:card"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Channel.Avatars.LastOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["og:description"] = Model.Channel.Description; + ViewBag.Title = Model.Channel.Name; + Layout = "_Layout"; + + DynamicItem[] contents; + try + { + contents = ((ItemSectionItem)((ItemSectionItem)Model.Channel.Videos[0]).Contents[0]).Contents; + } + catch + { + contents = Model.Channel.Videos; + } +} + +
+ @if (Model.Channel.Banners.Length > 0) + { + Channel Banner + } + +
+
+ + Channel Avatar + +
+ @Model.Channel.Name + @Model.Channel.Subscribers +
+ +
+
+ +

About

+

@Html.Raw(Model.Channel.GetHtmlDescription())

+

+

Uploads

+
+ @foreach (VideoItem video in contents.Where(x => x is VideoItem).Cast()) + { + +
@video.Duration
+
+ @video.Title +
+
+ @video.Views views + @video.UploadedAt +
+
+
+
+ } +
+ +
+ @if (!string.IsNullOrWhiteSpace(Model.ContinuationToken)) + { + First Page + } +
+ +
+ @if (!string.IsNullOrWhiteSpace(contents.FirstOrDefault(x => x is ContinuationItem)?.Id)) + { + Next Page + } +
+
diff --git a/core/LightTube/Views/Youtube/Download.cshtml b/core/LightTube/Views/Youtube/Download.cshtml new file mode 100644 index 00000000..11c56129 --- /dev/null +++ b/core/LightTube/Views/Youtube/Download.cshtml @@ -0,0 +1,95 @@ +@using System.Web +@using InnerTube +@using InnerTube.Models +@model LightTube.Contexts.PlayerContext + +@{ + ViewBag.Metadata = new Dictionary(); + ViewBag.Metadata["author"] = Model.Video.Channel.Name; + ViewBag.Metadata["og:title"] = Model.Player.Title; + ViewBag.Metadata["og:url"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}{Url.ActionContext.HttpContext.Request.Path}{Url.ActionContext.HttpContext.Request.QueryString}"; + ViewBag.Metadata["og:image"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Player.Thumbnails.FirstOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["twitter:card"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Player.Thumbnails.LastOrDefault()?.Url?.ToString())}"; + ViewBag.Title = Model.Player.Title; + Layout = "_Layout"; +} + +
+
+
+ Watch +
+

@Model.Player.Title

+ @Model.Video.Views • @Model.Video.UploadDate + +
+
+
+

Muxed formats

+

These downloads have both video and audio in them

+ @foreach (Format format in Model.Player.Formats) + { + + } +
+
+

Audio only formats

+

These downloads have only have audio in them

+ @foreach (Format format in Model.Player.AdaptiveFormats.Where(x => x.VideoCodec == "none")) + { +
+
+ @format.FormatNote (Codec: @format.AudioCodec, Sample Rate: @format.AudioSampleRate) +
+ + + Download through LightTube + + + + Download through YouTube + +
+ } +
+
+

Video only formats

+

These downloads have only have video in them

+ @foreach (Format format in Model.Player.AdaptiveFormats.Where(x => x.AudioCodec == "none")) + { +
+
+ @format.FormatNote (Codec: @format.VideoCodec) +
+ + + Download through LightTube + + + + Download through YouTube + +
+ } +
+
+
diff --git a/core/LightTube/Views/Youtube/Embed.cshtml b/core/LightTube/Views/Youtube/Embed.cshtml new file mode 100644 index 00000000..e49c15dd --- /dev/null +++ b/core/LightTube/Views/Youtube/Embed.cshtml @@ -0,0 +1,146 @@ +@using System.Collections.Specialized +@using System.Web +@using InnerTube.Models +@model LightTube.Contexts.PlayerContext + +@{ + ViewBag.Metadata = new Dictionary(); + ViewBag.Metadata["author"] = Model.Video.Channel.Name; + ViewBag.Metadata["og:title"] = Model.Player.Title; + ViewBag.Metadata["og:url"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}{Url.ActionContext.HttpContext.Request.Path}{Url.ActionContext.HttpContext.Request.QueryString}"; + ViewBag.Metadata["og:image"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Player.Thumbnails.FirstOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["twitter:card"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Player.Thumbnails.LastOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["og:description"] = Model.Player.Description; + ViewBag.Title = Model.Player.Title; + + Layout = null; + try + { + ViewBag.Metadata["og:video"] = $"/proxy/video?url={HttpUtility.UrlEncode(Model.Player.Formats.First().Url.ToString())}"; + Model.Resolution ??= Model.Player.Formats.First().FormatNote; + } + catch + { + } + bool live = Model.Player.Formats.Length == 0 && Model.Player.AdaptiveFormats.Length > 0; + bool canPlay = true; +} + + + + + + + + + @if (ViewBag.Metadata is not null) + { + @foreach (KeyValuePair metaTag in ViewBag.Metadata) + { + if (metaTag.Key.StartsWith("og:")) + { + + } + else + { + + } + } + } + + @ViewData["Title"] - lighttube + + + + + + + +@if (live) +{ + +} +else if (Model.Player.Formats.Length > 0) +{ + +} +else +{ + canPlay = false; +
+ @if (string.IsNullOrWhiteSpace(Model.Player.ErrorMessage)) + { + + No playable streams returned from the API (@Model.Player.Formats.Length/@Model.Player.AdaptiveFormats.Length) + + } + else + { + + @Model.Player.ErrorMessage + + } +
+} + +@if (canPlay) +{ + + @if (!Model.CompatibilityMode && !live) + { + + + } + else if (live) + { + + + } + else + { + + } +} + + \ No newline at end of file diff --git a/core/LightTube/Views/Youtube/Playlist.cshtml b/core/LightTube/Views/Youtube/Playlist.cshtml new file mode 100644 index 00000000..3c14c3dd --- /dev/null +++ b/core/LightTube/Views/Youtube/Playlist.cshtml @@ -0,0 +1,85 @@ +@using InnerTube.Models +@using System.Web +@model LightTube.Contexts.PlaylistContext + +@{ + ViewBag.Title = Model.Playlist.Title; + ViewBag.Metadata = new Dictionary(); + ViewBag.Metadata["og:title"] = Model.Playlist.Title; + ViewBag.Metadata["og:url"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}{Url.ActionContext.HttpContext.Request.Path}{Url.ActionContext.HttpContext.Request.QueryString}"; + ViewBag.Metadata["og:image"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Playlist.Thumbnail.FirstOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["twitter:card"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Playlist.Thumbnail.LastOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["og:description"] = Model.Playlist.Description; + Layout = "_Layout"; +} + +@if (!string.IsNullOrWhiteSpace(Model.Message)) +{ +
+ @Model.Message +
+} +
+
+
+ Play all +
+

@Model.Playlist.Title

+ @Model.Playlist.VideoCount videos • @Model.Playlist.ViewCount views • @Model.Playlist.LastUpdated + @Html.Raw(Model.Playlist.GetHtmlDescription()) + +
+ + + + + +
+
+
+ @foreach (PlaylistVideoItem video in Model.Playlist.Videos.Cast()) + { + + } +
+
+
+ @if (!string.IsNullOrWhiteSpace(Model.ContinuationToken)) + { + First Page + } +
+ +
+ @if (!string.IsNullOrWhiteSpace(Model.Playlist.ContinuationKey)) + { + Next Page + } +
diff --git a/core/LightTube/Views/Youtube/Search.cshtml b/core/LightTube/Views/Youtube/Search.cshtml new file mode 100644 index 00000000..9202529d --- /dev/null +++ b/core/LightTube/Views/Youtube/Search.cshtml @@ -0,0 +1,28 @@ +@using InnerTube.Models +@model LightTube.Contexts.SearchContext + +@{ + ViewBag.Title = Model.Query; + Layout = "_Layout"; + ViewData["UseFullSizeSearchBar"] = Model.MobileLayout; +} + +
+ @foreach (DynamicItem preview in Model.Results.Results) + { + @preview.GetHtml() + } +
+
+ @if (!string.IsNullOrWhiteSpace(Model.ContinuationKey)) + { + First Page + } +
+ +
+ @if (!string.IsNullOrWhiteSpace(Model.Results.ContinuationKey)) + { + Next Page + } +
diff --git a/core/LightTube/Views/Youtube/Watch.cshtml b/core/LightTube/Views/Youtube/Watch.cshtml new file mode 100644 index 00000000..9dd35e4d --- /dev/null +++ b/core/LightTube/Views/Youtube/Watch.cshtml @@ -0,0 +1,325 @@ +@using System.Text.RegularExpressions +@using System.Web +@using InnerTube.Models +@model LightTube.Contexts.PlayerContext + +@{ + bool compatibility = false; + if (Context.Request.Cookies.TryGetValue("compatibility", out string compatibilityString)) + bool.TryParse(compatibilityString, out compatibility); + + ViewBag.Metadata = new Dictionary(); + ViewBag.Metadata["author"] = Model.Video.Channel.Name; + ViewBag.Metadata["og:title"] = Model.Player.Title; + ViewBag.Metadata["og:url"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}{Url.ActionContext.HttpContext.Request.Path}{Url.ActionContext.HttpContext.Request.QueryString}"; + ViewBag.Metadata["og:image"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Player.Thumbnails.FirstOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["twitter:card"] = $"{Url.ActionContext.HttpContext.Request.Scheme}://{Url.ActionContext.HttpContext.Request.Host}/proxy/image?url={HttpUtility.UrlEncode(Model.Player.Thumbnails.LastOrDefault()?.Url?.ToString())}"; + ViewBag.Metadata["og:description"] = Model.Player.Description; + ViewBag.Title = Model.Player.Title; + + Layout = "_Layout"; + try + { + ViewBag.Metadata["og:video"] = $"/proxy/video?url={HttpUtility.UrlEncode(Model.Player.Formats.First().Url.ToString())}"; + Model.Resolution ??= Model.Player.Formats.First().FormatNote; + } + catch + { + } + ViewData["HideGuide"] = true; + + bool live = Model.Player.Formats.Length == 0 && Model.Player.AdaptiveFormats.Length > 0; + string description = Model.Video.GetHtmlDescription(); + const string youtubePattern = @"[w.]*youtube[-nockie]*\.com"; + + // turn URLs into hyperlinks + Regex urlRegex = new(youtubePattern, RegexOptions.IgnoreCase); + Match m; + for (m = urlRegex.Match(description); m.Success; m = m.NextMatch()) + description = description.Replace(m.Groups[0].ToString(), + $"{Url.ActionContext.HttpContext.Request.Host}"); + + bool canPlay = true; +} + + +
+
+
+ + @if (live) + { + + } + else if (Model.Player.Formats.Length > 0) + { + + } + else + { + canPlay = false; +
+ @if (string.IsNullOrWhiteSpace(Model.Player.ErrorMessage)) + { + + No playable streams returned from the API (@Model.Player.Formats.Length/@Model.Player.AdaptiveFormats.Length) + + } + else + { + + @Model.Player.ErrorMessage + + } +
+ } +
+ @if (Model.MobileLayout) + { +
+
@Model.Video.Title
+
+ @Model.Video.Views + Published @Model.Video.UploadDate +
+
+
+ @Model.Engagement.Likes +
+
+ @Model.Engagement.Dislikes +
+ + + Download + + + + Save + + + + YouTube link + +
+
+
+ + + + + +
+

@Html.Raw(description)

+
+
+ } + else + { +
+
@Model.Video.Title
+

+ @Model.Video.Views  @Model.Video.UploadDate  @Html.Raw(description) +

+
+
+ + @Model.Engagement.Likes +
+
+ + @Model.Engagement.Dislikes +
+ + + Download + + + + Save + + + + YouTube link + +
+
+
+ + + + +
+ @Model.Video.Channel.SubscriberCount +
+ +
+ } +
+
+ + +
+
+ +@if (canPlay) +{ + @if (Model.MobileLayout) + { + + } + else + { + + } + @if (!Model.CompatibilityMode && !live) + { + + + } + else if (live) + { + + + } + else + { + + } +} diff --git a/core/LightTube/Views/_ViewImports.cshtml b/core/LightTube/Views/_ViewImports.cshtml new file mode 100644 index 00000000..6090672f --- /dev/null +++ b/core/LightTube/Views/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using LightTube +@using LightTube.Models +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers \ No newline at end of file diff --git a/core/LightTube/Views/_ViewStart.cshtml b/core/LightTube/Views/_ViewStart.cshtml new file mode 100644 index 00000000..9f61dfb5 --- /dev/null +++ b/core/LightTube/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} \ No newline at end of file diff --git a/core/LightTube/YoutubeRSS.cs b/core/LightTube/YoutubeRSS.cs new file mode 100644 index 00000000..c3b1d936 --- /dev/null +++ b/core/LightTube/YoutubeRSS.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; + +namespace LightTube +{ + public static class YoutubeRSS + { + private static HttpClient _httpClient = new(); + + public static async Task GetChannelFeed(string channelId) + { + HttpResponseMessage response = + await _httpClient.GetAsync("https://www.youtube.com/feeds/videos.xml?channel_id=" + channelId); + if (!response.IsSuccessStatusCode) + throw response.StatusCode switch + { + HttpStatusCode.NotFound => new KeyNotFoundException($"Channel '{channelId}' does not exist"), + var _ => new Exception("Failed to fetch RSS feed for channel " + channelId) + }; + + ChannelFeed feed = new(); + + string xml = await response.Content.ReadAsStringAsync(); + XDocument doc = XDocument.Parse(xml); + + feed.Name = doc.Descendants().First(p => p.Name.LocalName == "title").Value; + feed.Id = doc.Descendants().First(p => p.Name.LocalName == "channelId").Value; + feed.Videos = doc.Descendants().Where(p => p.Name.LocalName == "entry").Select(x => new FeedVideo + { + Id = x.Descendants().First(p => p.Name.LocalName == "videoId").Value, + Title = x.Descendants().First(p => p.Name.LocalName == "title").Value, + Description = x.Descendants().First(p => p.Name.LocalName == "description").Value, + ViewCount = long.Parse(x.Descendants().First(p => p.Name.LocalName == "statistics").Attribute("views")?.Value ?? "-1"), + Thumbnail = x.Descendants().First(p => p.Name.LocalName == "thumbnail").Attribute("url")?.Value, + ChannelName = x.Descendants().First(p => p.Name.LocalName == "name").Value, + ChannelId = x.Descendants().First(p => p.Name.LocalName == "channelId").Value, + PublishedDate = DateTimeOffset.Parse(x.Descendants().First(p => p.Name.LocalName == "published").Value) + }).ToArray(); + + return feed; + } + + public static async Task GetMultipleFeeds(IEnumerable channelIds) + { + Task[] feeds = channelIds.Select(YoutubeRSS.GetChannelFeed).ToArray(); + await Task.WhenAll(feeds); + + List videos = new(); + foreach (ChannelFeed feed in feeds.Select(x => x.Result)) videos.AddRange(feed.Videos); + + videos.Sort((a, b) => DateTimeOffset.Compare(b.PublishedDate, a.PublishedDate)); + return videos.ToArray(); + } + } + + public class ChannelFeed + { + public string Name; + public string Id; + public FeedVideo[] Videos; + } + + public class FeedVideo + { + public string Id; + public string Title; + public string Description; + public long ViewCount; + public string Thumbnail; + public string ChannelName; + public string ChannelId; + public DateTimeOffset PublishedDate; + + public XmlElement GetXmlElement(XmlDocument doc) + { + XmlElement item = doc.CreateElement("Video"); + item.SetAttribute("id", Id); + item.SetAttribute("views", ViewCount.ToString()); + item.SetAttribute("uploadedAt", PublishedDate.ToUnixTimeSeconds().ToString()); + + XmlElement title = doc.CreateElement("Title"); + title.InnerText = Title; + item.AppendChild(title); + XmlElement channel = doc.CreateElement("Channel"); + channel.SetAttribute("id", ChannelId); + + XmlElement channelTitle = doc.CreateElement("Name"); + channelTitle.InnerText = ChannelName; + channel.AppendChild(channelTitle); + + item.AppendChild(channel); + + XmlElement thumbnail = doc.CreateElement("Thumbnail"); + thumbnail.InnerText = Thumbnail; + item.AppendChild(thumbnail); + + if (!string.IsNullOrWhiteSpace(Description)) + { + XmlElement description = doc.CreateElement("Description"); + description.InnerText = Description; + item.AppendChild(description); + } + + return item; + } + } +} \ No newline at end of file diff --git a/core/LightTube/appsettings.Development.json b/core/LightTube/appsettings.Development.json new file mode 100644 index 00000000..8983e0fc --- /dev/null +++ b/core/LightTube/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/core/LightTube/appsettings.json b/core/LightTube/appsettings.json new file mode 100644 index 00000000..d9d9a9bf --- /dev/null +++ b/core/LightTube/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/core/LightTube/wwwroot/css/bootstrap-icons/bootstrap-icons.css b/core/LightTube/wwwroot/css/bootstrap-icons/bootstrap-icons.css new file mode 100644 index 00000000..5712315e --- /dev/null +++ b/core/LightTube/wwwroot/css/bootstrap-icons/bootstrap-icons.css @@ -0,0 +1,1704 @@ +@font-face { + font-family: "bootstrap-icons"; + src: url("./fonts/bootstrap-icons.woff2?524846017b983fc8ded9325d94ed40f3") format("woff2"), +url("./fonts/bootstrap-icons.woff?524846017b983fc8ded9325d94ed40f3") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-1::before { content: "\f2a5"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-1::before { content: "\f68a"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-1::before { content: "\f68d"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-1::before { content: "\f690"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-1::before { content: "\f695"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-1::before { content: "\f698"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-mortorboard-fill::before { content: "\f6a2"; } +.bi-mortorboard::before { content: "\f6a3"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-1::before { content: "\f6b6"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash-1::before { content: "\f6c2"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport-1::before { content: "\f6e0"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-ssd-fill::before { content: "\f6ed"; } +.bi-ssd::before { content: "\f6ee"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt-1::before { content: "\f759"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls-1::before { content: "\f769"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } diff --git a/core/LightTube/wwwroot/css/bootstrap-icons/fonts/bootstrap-icons.woff b/core/LightTube/wwwroot/css/bootstrap-icons/fonts/bootstrap-icons.woff new file mode 100644 index 00000000..b26ccd1a Binary files /dev/null and b/core/LightTube/wwwroot/css/bootstrap-icons/fonts/bootstrap-icons.woff differ diff --git a/core/LightTube/wwwroot/css/bootstrap-icons/fonts/bootstrap-icons.woff2 b/core/LightTube/wwwroot/css/bootstrap-icons/fonts/bootstrap-icons.woff2 new file mode 100644 index 00000000..f865a4b2 Binary files /dev/null and b/core/LightTube/wwwroot/css/bootstrap-icons/fonts/bootstrap-icons.woff2 differ diff --git a/core/LightTube/wwwroot/css/colors-dark.css b/core/LightTube/wwwroot/css/colors-dark.css new file mode 100644 index 00000000..7ef622ce --- /dev/null +++ b/core/LightTube/wwwroot/css/colors-dark.css @@ -0,0 +1,19 @@ +:root { + --text-primary: #fff; + --text-secondary: #808080; + --text-link: #3ea6ff; + + --app-background: #181818; + --context-menu-background: #333; + --border-color: #444; + --item-hover-background: #373737; + --item-active-background: #383838; + + --top-bar-background: #202020; + --guide-background: #212121; + + --thumbnail-background: #252525; + + --channel-info-background: #181818; + --channel-contents-background: #0f0f0f; +} diff --git a/core/LightTube/wwwroot/css/colors-light.css b/core/LightTube/wwwroot/css/colors-light.css new file mode 100644 index 00000000..bb69429b --- /dev/null +++ b/core/LightTube/wwwroot/css/colors-light.css @@ -0,0 +1,19 @@ +:root { + --text-primary: #000; + --text-secondary: #606060; + --text-link: #3ea6ff; + + --app-background: #f9f9f9; + --context-menu-background: #f2f2f2; + --border-color: #c5c5c5; + --item-hover-background: #f2f2f2; + --item-active-background: #E5E5E5;; + + --top-bar-background: #FFF; + --guide-background: #FFF; + + --thumbnail-background: #CCC; + + --channel-info-background: #fff; + --channel-contents-background: #f9f9f9; +} diff --git a/core/LightTube/wwwroot/css/desktop.css b/core/LightTube/wwwroot/css/desktop.css new file mode 100644 index 00000000..8cd25266 --- /dev/null +++ b/core/LightTube/wwwroot/css/desktop.css @@ -0,0 +1,1232 @@ +/* common stuff */ + +* { + box-sizing: border-box; + color: var(--text-secondary); +} + +h1, h2, h3, h4, h5, h6 { + color: var(--text-primary); +} + +.divider { + flex-grow: 1; +} + +.max-lines-1 { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; +} + +.max-lines-2 { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + line-clamp: 2; + -webkit-box-orient: vertical; +} + +/* shared layout */ + +body { + display: grid; + grid-template-columns: min-content 1fr; + grid-template-rows: 56px 1fr; + grid-template-areas: "top-bar top-bar" "guide app"; + margin: 0; + padding: 0; + font-family: sans-serif; +} + +html { + background-color: var(--app-background); +} + +body.noguide { + grid-template-areas: "top-bar top-bar" "app app"; +} + +.top-bar { + grid-area: top-bar; + + display: flex; + padding: 0 16px; + align-items: center; + background-color: var(--top-bar-background); + color: var(--text-primary); + z-index: 9999; +} + +.divider { + flex-grow: 1; +} + +.top-bar > .search-button { + display: none; +} + +.top-bar > form { + height: 40px; + flex-grow: 1; + display: flex; +} + +.top-bar > form > input { + box-sizing: border-box; + height: 40px; + border: 1px solid var(--border-color); + border-radius: 0; + color: var(--text-primary); + background-color: var(--item-active-background); +} + +.top-bar > form > input[type=text] { + flex-grow: 1; +} + +.top-bar > form > input[type=submit] { + width: 64px; + flex-basis: 64px; +} + +.logo { + color: var(--text-primary) !important; + text-decoration: none; + font-size: larger; +} + +.guide { + grid-area: guide; + background-color: var(--guide-background); + color: var(--text-primary); + width: 300px; + height: 100%; + min-height: calc(100vh - 56px); +} + +.account { + width: 56px; + height: 56px; + display: flex; + align-items: center; + justify-content: center; +} + +a.icon-button, a.icon-button > img { + width: 32px; + height: 32px; +} + +.account-menu { + display: none; + + background-color: var(--context-menu-background); +} + +.account-menu > .guide-item { + background-color: var(--context-menu-background); +} + +.account:hover .account-menu { + display: block; + + position: absolute; + top: 56px; + right: 0; + width: 250px; + background-color: #fff; + border: 1px solid var(--border-color); +} + +.account:hover { + background-color: var(--context-menu-background); +} + +.app { + grid-area: app; + background-color: var(--app-background); +} + +.noguide > .guide { + display: none; +} + +/* guide */ + +.guide-item:hover { + background-color: var(--item-hover-background); +} + +.guide-item > a { + height: 40px; + padding: 0 24px; + display: flex; + align-items: center; + color: var(--text-primary); + text-decoration: none; +} + +.guide-item > a > .icon { + height: 24px; + width: 24px; + margin-right: 24px; + line-height: 24px; + text-align: center; +} + +.guide-item.active { + background-color: var(--item-active-background); +} + +.guide hr { + color: #fff; +} + +.guide > p { + padding: 16px 24px; + font-size: small; + font-weight: bold; +} + +.guide > p > a { + color: var(--text-secondary); + text-decoration: none; +} + +/* guide (minmode) */ + +.guide.minmode { + width: 72px; +} + +.guide.minmode > .guide-item { + /* height: 74px; */ + padding-top: 16px; + padding-bottom: 14px; +} + +.guide.minmode > .guide-item > a { + height: 40px; + padding: 0 24px; + display: flex; + text-align: center; + flex-direction: column; + font-size: x-small; + align-items: center; + color: var(--text-primary); + text-decoration: none; + justify-content: center; +} + +.guide.minmode > .guide-item > a > .icon { + font-size: initial; + margin-right: 0; +} + +.guide.minmode > .hide-on-minmode { + display: none; +} + +.guide > .show-on-minmode { + display: none; +} + +.guide.minmode > .show-on-minmode { + display: block; +} + +@media screen and (max-width: 600px) { + .guide, .top-bar > form { + display: none; + } + + .search-button { + display: block !important; + } +} + +/* watch page */ + +.watch-page { + margin: 24px; + display: flex; + flex-direction: row; +} + +@media screen and (max-width: 1000px) { + .watch-page { + flex-direction: column; + } + + .video-info { + display: grid; + grid-auto-rows: 1fr; + grid-template-columns: 1fr; + grid-template-rows: max-content max-content max-content; + gap: 8px; + grid-template-areas: "title" "info" "buttons"; + } + + .recommended-list { + width: calc(100vw - 48px) !important; + } +} + +@media screen and (min-width: 1000px) { + .video-info { + display: grid; + grid-auto-rows: 1fr; + grid-template-columns: 615px 1fr max-content; + grid-template-rows: max-content max-content; + gap: 8px; + grid-template-areas: "title title title" "info . buttons"; + } +} + +.watch-page > .primary { + flex-grow: 1; +} + +.video-player-container { + max-width: 100%; + margin: auto; + max-height: 75vh; + aspect-ratio: 16 / 9; +} + +.player { + width: 100%; + height: 100%; +} + +.player.error { + display: flex; + align-items: center; + justify-content: center; + background-color: #ccc; + background-image: url('/img/player-error.png') !important; + background-size: contain; +} + +.player.error > * { + background-color: #000; + color: #fff; +} + +.video-info { + color: var(--text-secondary); +} + +.video-title { + grid-area: title; + color: var(--text-primary); + font-size: larger; + margin-top: 8px; +} + +.video-info-bar { + font-size: unset; + column-gap: 16px; + border-bottom: 1px solid var(--border-color); + display: flex; + align-items: center; + padding: 8px 0; +} + +.video-info-bar > a { + color: var(--text-secondary); + text-decoration: none; +} + +.video-info-buttons { + grid-area: buttons; + display: flex; + flex-direction: row; + column-gap: 8px; +} + +.video-info-buttons > * { + color: var(--text-primary); + display: flex; + justify-content: center; + align-content: center; + column-gap: 4px; + text-decoration: none; + height: 36px; + line-height: 32px; + font-size: 14px; + font-weight: bold; +} + +.video-info-buttons > * > .bi { + color: var(--text-primary); + width: 24px; + font-size: 18px +} + +.channel-info { + display: grid; + grid-template-columns: 48px max-content 1fr min-content; + grid-template-rows: 48px; + grid-auto-columns: 1fr; + gap: 8px; + grid-auto-flow: row; + grid-template-areas: "avatar name . subscribe-button"; + + padding-top: 16px; +} + +.channel-info > .avatar > img { + width: 100%; + height: 100%; +} + +.channel-info__bordered { + border: 1px solid var(--border-color); + border-radius: 4px; + display: grid; + grid-template-columns: 48px max-content 1fr min-content; + grid-template-rows: 16px 16px; + grid-auto-columns: 1fr; + column-gap: 8px; + row-gap: 4px; + grid-auto-flow: row; + grid-template-areas: "avatar name . subscribe-button" "avatar subs . subscribe-button"; + padding: 8px; +} + +.avatar { + grid-area: avatar; +} + +.avatar > img { + width: 36px; + height: 36px; + border-radius: 50%; +} + +.name { + grid-area: name; + + display: flex; + flex-direction: column; + justify-content: center; +} + +.name > a { + color: var(--text-primary); + text-decoration: none; +} + +.subscriber-count { + grid-area: subs; +} + +.subscribe-button { + grid-area: subscribe-button; + + background-color: #c00; + color: #fff; + text-transform: uppercase; + font-weight: bold; + padding: 10px 16px; + border: none; + margin: auto; + + height: 37px; +} + +.subscribe-button.subscribed { + background-color: #ECECEC; + color: var(--text-secondary); +} + +.video-sub-info { + grid-area: info; + font-weight: lighter; + font-size: 95%; + max-width: 615px; +} + +.video-sub-info > span { + color: var(--text-primary); + font-weight: bold; +} + +.description > a { + text-decoration: none; + color: var(--text-link); +} + +.watch-page > .secondary { + width: 400px; +} + +.resolutions-list { + width: 400px; + padding: 4px; + border: 1px solid var(--border-color); + margin: 0 16px; +} + +.resolutions-list > div { + display: flex; + column-gap: 16px; +} + +/* recommended video list */ + +.recommended-list { + display: flex; + flex-direction: column; + flex-wrap: wrap; + row-gap: 16px; + padding: 16px; + width: 400px; +} + +.recommended-list > .video { + display: grid; + grid-template-columns: 168px 1fr; + grid-template-rows: 94px; + grid-auto-flow: row; + grid-gap: 0 8px; + grid-template-areas: "thumbnail info"; + + color: var(--text-secondary); +} + +.recommended-list > .playlist { + display: grid; + grid-template-columns: 168px 1fr; + grid-template-rows: 94px; + grid-auto-flow: row; + grid-gap: 0 8px; + grid-template-areas: "thumbnail info"; + + color: var(--text-secondary); +} + +/* rich video grid */ + +.rich-video-grid { + display: flex; + flex-wrap: wrap; + column-gap: 16px; + row-gap: 40px; + padding: 16px; +} + +.rich-video-grid > .video { + display: grid; + grid-template-columns: 40px 240px; + grid-template-rows: 160px 52px; + grid-auto-flow: row; + grid-gap: 10px 0; + grid-template-areas: + "thumbnail thumbnail" + "avatar info"; + + color: var(--text-secondary); +} + +.rich-video-grid > .video > .avatar { + width: 40px; + height: 40px; +} + +/* list video item */ + +.video a { + text-decoration: none; + color: var(--text-secondary); +} + +.video > .thumbnail { + grid-area: thumbnail; + + background-color: var(--thumbnail-background); + + display: flex; + justify-content: flex-end; + align-items: flex-end; + padding: 4px; + + background-position-y: center; + background-size: cover; +} + +.video > .thumbnail.img-thumbnail { + padding: 0 !important; +} + +.video > .thumbnail > img { + object-fit: cover; + width: 100%; + height: 100%; +} + +.video > .thumbnail > .video-length { + font-size: smaller; + + background-color: #0008; + color: #fff; + padding: 2px; + border-radius: 2px; +} + +.video > .info { + grid-area: info; + font-size: small; +} + +.video > .info > div > a > img { + width: 24px; + height: 24px; + border-radius: 50%; +} + +.video > .info > .title { + color: var(--text-primary) !important; + font-weight: bold; + font-size: initial; + margin-bottom: 8px; +} + +/* playlist video item */ + +.playlist-video a { + text-decoration: none; + color: #606060; +} + +.playlist-video > .thumbnail { + grid-area: thumbnail; + background-color: #CCC; + width: 100%; + height: fit-content; + aspect-ratio: 16 / 9; + + display: flex; + justify-content: flex-end; + align-items: flex-end; + padding: 4px; + + background-position-y: center; + background-size: cover; +} + +.playlist-video > .thumbnail > span { + font-size: smaller; + + background-color: #0008; + color: #fff; + padding: 2px; + border-radius: 2px; +} + +.playlist-video > .avatar { + grid-area: avatar; + width: 36px; + height: 36px; + border-radius: 18px; + background-color: #E3E3E3; + + margin-left: 12px; +} + +.playlist-video > .avatar > img { + width: 36px; + height: 36px; + border-radius: 18px; +} + +.playlist-video > .info { + grid-area: info; +} + +.playlist-video > .info > div { + display: flex; + flex-direction: row; + flex-wrap: wrap; + color: #606060; + column-gap: 8px; + overflow-y: hidden; +} + +.playlist-video > .info > .title { + color: var(--text-primary) !important; + font-size: large; + padding-bottom: 8px; +} + +.playlist-video > .index { + grid-area: index; + display: flex; + justify-content: center; + align-items: center; +} + +/* list playlist item */ + +.playlist a { + text-decoration: none; + color: var(--text-secondary); +} + +.playlist > .thumbnail { + grid-area: thumbnail; + + background-color: var(--thumbnail-background); + + display: flex; + justify-content: flex-end; + align-items: center; + + background-position-y: center; + background-size: cover; +} + +.playlist > .thumbnail > div { + font-size: smaller; + + background-color: #0008; + color: #fff; + padding: 2px; + width: 50%; + height: 100%; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + row-gap: 8px; +} + +.playlist > .thumbnail > div > * { + color: #fff; +} + +.playlist > .thumbnail > div > *:nth-child(1) { + font-size: x-large; +} + +.playlist > .info { + grid-area: info; + font-size: small; +} + +.playlist > .info > div > ul { + display: none; +} + +.playlist > .info > .title { + color: var(--text-primary) !important; + font-weight: bold; + font-size: initial; + margin-bottom: 8px; +} + +/* list video item */ + +.channel a { + text-decoration: none; + color: var(--text-secondary); +} + +.channel > .avatar { + grid-area: thumbnail; + + display: flex; + justify-content: center; + align-items: center; +} + +.channel > .avatar > img { + background-color: var(--thumbnail-background); + + height: 136px; + width: 136px; +} + +.channel > .info { + grid-area: info; + font-size: small; + padding-top: 32px; +} + +.channel > .info > .name { + color: var(--text-primary) !important; + font-weight: bold; + font-size: initial; + margin-bottom: 8px; +} + +/* channel page */ + +.channel-banner { + display: block; + width: 100%; + height: auto; + aspect-ratio: 6.2; + background-color: #000a; + background-size: contain; +} + +.channel-info-container { + background-color: var(--channel-info-background); +} + +.channel-info-container > .channel-info { + max-width: 1200px; + margin: auto; + + grid-template-columns: 80px max-content 1fr min-content; + grid-template-rows: 80px; + gap: 16px; + padding: 16px 0; +} + +.channel-info-container > .channel-info > .subscribe-button { + margin: 20px 0; +} + +.channel-info-container > .channel-info > .name > *:first-child { + font-size: larger; + color: var(--text-primary); +} + +.channel-info-container > .channel-info > .name > * { + color: var(--text-secondary); +} + +.channel-page > p { + color: var(--text-secondary) +} + +.channel-page .video-grid { + background-color: var(--channel-contents-background); +} + +/* card list item */ + +.card-list { + display: flex; + flex-direction: row; + overflow-x: scroll; + column-gap: 16px; +} + +.card { + width: 150px; + background: var(--context-menu-background); + border: 1px solid var(--border-color); + border-radius: 8px; + text-decoration: none; +} + +.card > img { + aspect-ratio: 16 / 9; + width: 150px; + height: fit-content; +} + +.card > span { + text-decoration: none; + color: var(--text-primary); + margin: 0 8px; +} + +/* channel video grid */ + +.video-grid { + display: flex; + flex-wrap: wrap; + column-gap: 16px; + row-gap: 40px; + padding: 16px; +} + +.video-grid > .video { + text-decoration: none; + display: grid; + grid-template-columns: 280px; + grid-template-rows: 160px 52px; + grid-auto-flow: row; + grid-gap: 10px 0; + grid-template-areas: + "thumbnail" + "info"; + + color: var(--text-secondary); +} + +.video-grid > .avatar { + display: none; +} + +/* Pagination links */ + +.pagination-buttons { + border-top: 1px solid var(--border-color); + width: 100%; + display: flex; +} + +.pagination-buttons > * { + height: 3rem; + line-height: 3rem; + color: var(--text-secondary); + text-decoration: none; +} + +/* normal video list */ + +.video-list { + max-width: 850px; + margin: auto; + display: flex; + flex-direction: column; + row-gap: 16px; + padding: 16px; +} + +.video-list > .video { + text-decoration: none; + display: grid; + grid-template-columns: 280px; + grid-template-rows: 160px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "thumbnail info"; + + color: var(--text-secondary); +} + +.video-list > .playlist-video { + text-decoration: none; + display: grid; + grid-template-columns: 36px 160px 1fr; + grid-template-rows: 90px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "index thumbnail info"; + + color: var(--text-secondary); + font-size: small; +} + +.video-list > .playlist { + text-decoration: none; + display: grid; + grid-template-columns: 280px; + grid-template-rows: 160px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "thumbnail info"; + + color: var(--text-secondary); +} + +.video-list > .channel { + text-decoration: none; + display: grid; + grid-template-columns: 280px 1fr max-content; + grid-template-rows: 160px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "thumbnail info subscribe-button"; + + color: var(--text-secondary); +} + +.video-list > .channel > .subscribe-button { + margin-top: 60px; +} + +.video-list > .avatar { + display: none; +} + +.video-list > .playlist > .info > div > ul { + display: block; + padding-left: 0; + list-style: none; +} + +.video-list > .playlist > .info > div > ul > li > * { + color: var(--text-primary); + line-height: 24px; + height: 24px; + display: inline-block; +} + +.video-list > .playlist > .info > div > ul > li:last-child > * { + color: var(--text-secondary); + text-transform: uppercase; +} + +/* Playlist page */ + +.playlist-page { + display: grid; + grid-auto-columns: 1fr; + grid-template-columns: 360px 1fr; + grid-template-rows: 1fr; + gap: 0px 0px; + grid-template-areas: "info content"; +} + +.playlist-info > .thumbnail { + grid-area: info; + width: 100%; + height: auto; + aspect-ratio: 16 / 9; + background-color: var(--thumbnail-background); + display: flex; + justify-content: center; + align-items: flex-end; + + background-position-y: center; + background-size: cover; +} + +.playlist-info > .thumbnail > a { + background-color: #0008; + color: #fff; + padding: 8px; + border-radius: 2px; + width: 100%; + text-align: center; +} + +.playlist-info > .title { + font-size: x-large; + color: var(--text-primary); +} + +.playlist-info { + background-color: var(--channel-contents-background); + padding: 16px; +} + +.playlist-video-list { + grid-area: content; + max-width: 100%; + margin: 0; +} + +.playlist-info > .info { + display: block; +} + +.playlist-info > .description { + display: block; + padding: 16px 0; +} + +.playlist-info > .channel-info > .subscribe-button { + margin-top: 4px; +} + +/* horizontal channel list */ + +.horizontal-channel-list { + display: flex; + column-gap: 16px; + padding: 16px; + overflow-x: scroll; + background-color: var(--item-hover-background); +} + +.horizontal-channel-list > .channel { + text-decoration: none; + display: flex; + flex-direction: column; + row-gap: 4px; + color: var(--text-secondary); +} + +.horizontal-channel-list > .channel > div { + font-size: small; + text-align: center; + width: 72px; + color: var(--text-secondary); +} + +.horizontal-channel-list > .channel > img { + width: 72px; + height: 72px; + border-radius: 50%; + background-color: var(--thumbnail-background); +} + +.horizontal-channel-list > .channel > i { + font-size: 36px; + line-height: 72px; + text-align: center; + width: 72px; + height: 72px; + border-radius: 50%; + background-color: var(--thumbnail-background); +} + +/* Login / Register / Delete pages */ + +.login-container { + display: flex; + flex-direction: row; +} + +@media screen and (max-width: 1300px) { + .login-container { + flex-direction: column; + } +} + +.login-container > * { + flex: 1 1 0; +} + +.login-container > * > div { + max-width: 600px; + margin: auto; +} + +.login-form { + display: flex; + flex-direction: column; + max-width: 400px; + row-gap: 10px; + margin: auto; +} + +.login-form > input, .login-button { + background-color: var(--item-active-background); + color: var(--text-primary); + border: 1px solid var(--border-color); + padding: 10px; + max-width: 400px; + row-gap: 10px; + margin: auto; +} + +.login-button { + background-color: var(--item-active-background); + color: var(--text-primary); + display: block; + text-align: center; + text-decoration: none; + width: fit-content; +} + +.login-button.danger { + color: red; + font-weight: bold; +} + +.login-form > h1 { + text-align: center; +} + +.login-message { + width: calc(100% - 96px); + margin: 48px; + padding: 16px; + border: 1px solid var(--border-color); + background-color: var(--item-active-background); + border-radius: 5px; +} + +/* download page */ + +.download-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; + column-gap: 32px; +} + +.download-format { + max-width: 400px; + padding: 8px; + display: flex; + flex-direction: column; + row-gap: 8px; +} + +.download-format > div { + color: var(--text-primary); +} + +.download-format > a { + padding: 8px; + background-color: var(--channel-contents-background); + border: 1px solid var(--border-color); + text-decoration: none; +} + +/* settings page */ + +.settings-categories { + background-color: var(--context-menu-background); + display: flex; + column-gap: 16px; + padding: 0 16px; +} + +.settings-categories > a { + height: 3rem; + line-height: 3rem; + padding: 0 8px; + text-decoration: none; +} + +.settings-content { + max-width: 400px; + margin: auto; +} + +.settings-content > div { + width: 100%; + padding: 8px; +} + +.settings-content > div > label { + width: 40%; + display: inline-block; + font-weight: bold; + color: var(--text-primary); +} + +.settings-content > div > select { + width: 50%; + display: inline-block; + border: 1px solid var(--border-color); + padding: 4px; + background-color: var(--context-menu-background); + color: var(--text-primary); +} + +/* logins page */ + +.logins-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-evenly; + gap: 16px; + padding: 16px; +} + +.login { + border: 1px solid var(--border-color); + border-radius: 4px; + width: 500px; + padding: 8px; +} \ No newline at end of file diff --git a/core/LightTube/wwwroot/css/lt-video/player-desktop.css b/core/LightTube/wwwroot/css/lt-video/player-desktop.css new file mode 100644 index 00000000..36666dcb --- /dev/null +++ b/core/LightTube/wwwroot/css/lt-video/player-desktop.css @@ -0,0 +1,267 @@ +* { + font-family: sans-serif; +} + +.player { + background-color: #000 !important; + display: grid; + grid-template-columns: 1fr min-content; + grid-template-rows: max-content 1fr max-content max-content max-content; + gap: 0 0; + width: 100%; + height: 100%; +} + +.player * { + color: #fff; + box-sizing: content-box; +} + +.player.embed, video.embed { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +.player * { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.player > video { + position: relative; + width: 100%; + height: 100%; + z-index: 0; + grid-area: 1 / 1 / 6 / 3; +} + +.player.hide-controls > .player-title, +.player.hide-controls > .player-controls, +.player.hide-controls > .player-playback-bar-container, +.player.hide-controls > .player-menu { + display: none !important; +} + +.player-title { + grid-area: 1 / 1 / 2 / 3; + color: white; + z-index: 2; + font-size: 27px; + background-image: linear-gradient(180deg, #0007 0%, #0000 100%); + padding: 8px; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; +} + +.player-controls { + padding-top: 4px; + color: #ddd !important; + width: 100%; + height: min-content; + position: relative; + bottom: 0; + z-index: 2; + background-image: linear-gradient(0deg, #0007 0%, #0007 80%, #0000 100%); + grid-area: 5 / 1 / 6 / 3; +} + +.player-controls { + display: flex; +} + +.player-controls > span { + line-height: 48px; + height: 48px; + font-size: 109%; +} + +.player-controls-padding { + width: 12px; +} + +.player-button { + cursor: pointer; + display: flex; + flex-direction: row; + transition: width ease-in 250ms; + width: 48px; + height: 48px; + font-size: 36px; + text-align: center; + line-height: 48px; +} + +.player-button, .player-button * { + color: #dddddd !important; + text-decoration: none; +} + +.player-button > i { + min-width: 48px; +} + +.player-button:hover, .player-button:hover * { + color: #fff !important; +} + +.player-volume { + overflow-x: hidden; +} + +.player-volume:hover { + width: 200px; +} + +.player-button-divider { + flex-grow: 1; +} + +.player-button-menu { + flex-direction: column-reverse; +} + +.player-menu { + grid-area: 3 / 2 / 4 / 3; + z-index: 3; + position: relative; + background-color: #000a !important; + width: 200px; +} + +.player-menu > div { + overflow-y: scroll; + max-height: 300px; +} + +.player-menu-item { + padding: 4px 8px; + height: 2rem; + line-height: 2rem; + color: white; + + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; +} + +.player-menu-item > .bi { + width: 16px; + height: 16px; + margin-right: 8px; +} + +.player-menu-item > .bi-::before { + width: 16px; + height: 16px; + content: "" +} + +.player-menu-item:hover { + background-color: #fff3 !important; +} + +.player-playback-bar { + transition: width linear 100ms; +} + +.player-playback-bar-container { + grid-area: 4 / 1 / 5 / 3; + height: 4px; + transition: height linear 100ms; + width: 100%; + z-index: 2; +} + +.player-playback-bar-bg { + background-color: #fff3 !important; + width: calc(100% - 24px); + margin: auto; + height: 100%; + z-index: 2; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; +} + +.player-playback-bar-bg > * { + grid-area: 1 / 1 / 2 / 2; +} + +.player-playback-bar-container:hover { + height: 8px; +} + +.player-playback-bar-buffer { + background-color: #fffa !important; + height: 100%; + width: 0; + z-index: 3; +} + +.player-playback-bar-fg { + background-color: #f00 !important; + height: 100%; + width: 0; + z-index: 4; +} + +.player-playback-bar-hover { + width: min-content !important; + padding: 4px; + position: fixed; + color: white; + display: none; + text-align: center; +} + +.player-playback-bar-hover > span { + background-color: #000 !important; + padding: 4px; +} + +.player-storyboard-image-container { + background-repeat: no-repeat; + display: inline-block; + width: 144px; + height: 81px; +} + +.player-storyboard-image { + background-repeat: no-repeat; + display: inline-block; + width: 48px; + height: 27px; + background-position-x: 0; + background-position-y: 0; + transform: scale(3); + position: relative; + box-sizing: content-box; + border: 1px solid white; + top: 10px; +} + +.player-buffering { + grid-area: 1 / 1 / 6 / 3; + background-color: #000A; + z-index: 1; + display: flex; + justify-content: center; + align-items: center; +} + +.player-buffering-spinner { + width: 80px; + height: 80px; +} \ No newline at end of file diff --git a/core/LightTube/wwwroot/css/lt-video/player-mobile.css b/core/LightTube/wwwroot/css/lt-video/player-mobile.css new file mode 100644 index 00000000..ff835fd4 --- /dev/null +++ b/core/LightTube/wwwroot/css/lt-video/player-mobile.css @@ -0,0 +1,153 @@ +body, html { + margin: 0; + padding: 0; +} + +* { + font-family: sans-serif; +} + +.player { + background-color: #000 !important; + display: grid; + grid-template-columns: 1fr min-content; + grid-template-rows: max-content 1fr max-content max-content max-content; + gap: 0 0; + width: 100%; + /* + height: 100%; + */ + aspect-ratio: 16 / 9; +} + +.player * { + color: #fff; +} + +.player.embed, video.embed { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +.player * { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.player > video { + position: relative; + width: 100%; + height: 100%; + z-index: 0; + grid-area: 1 / 1 / 6 / 3; +} + +.player.hide-controls > .player-title, +.player.hide-controls > .player-controls, +.player.hide-controls > .player-playback-bar-container, +.player.hide-controls > .player-menu { + display: none !important; +} + +.player-controls { + background-color: #0007; + display: flex; + justify-content: center; + align-items: center; + z-index: 1; + grid-area: 1 / 1 / 6 / 3; +} + +.player-button { + width: 96px; + height: 96px; + font-size: 90px; + text-align: center; + line-height: 48px; +} + +.player-tiny-button { + width: 40px; + font-size: 20px; + text-align: center; +} + +.player-tiny-button > i { + color: #ddd; +} + +.player-button, .player-button * { + color: #dddddd !important; + text-decoration: none; +} + +.player-button > i { + min-width: 48px; +} + +.player-button:hover, .player-button:hover * { + color: #fff !important; +} + +.player-playback-bar { + transition: width linear 100ms; +} + +.player-playback-bar-container { + grid-area: 4 / 1 / 5 / 3; + display: flex; + column-gap: 8px; + justify-content: center; + align-items: center; + height: 8px; + transition: height linear 100ms; + width: 100%; + z-index: 2; + margin-bottom: 10px; +} + +.player-playback-bar-bg { + background-color: #fff3 !important; + width: 100%; + height: 100%; + z-index: 2; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; +} + +.player-playback-bar-bg > * { + grid-area: 1 / 1 / 2 / 2; +} + +.player-playback-bar-buffer { + background-color: #fffa !important; + height: 100%; + width: 0; + z-index: 3; +} + +.player-playback-bar-fg { + background-color: #f00 !important; + height: 100%; + width: 0; + z-index: 4; +} + +.player-buffering { + grid-area: 1 / 1 / 6 / 3; + z-index: 1; + display: flex; + justify-content: center; + align-items: center; +} + +.player-buffering-spinner { + width: 80px; + height: 80px; +} \ No newline at end of file diff --git a/core/LightTube/wwwroot/css/mobile.css b/core/LightTube/wwwroot/css/mobile.css new file mode 100644 index 00000000..2a75365d --- /dev/null +++ b/core/LightTube/wwwroot/css/mobile.css @@ -0,0 +1,1201 @@ +/* common stuff */ + +.max-lines-1 { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; +} + +.max-lines-2 { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + line-clamp: 2; + -webkit-box-orient: vertical; +} + +/* shared layout */ + +body { + margin: 48px 0; + padding: 0; + font-family: sans-serif; +} + +html { + background-color: var(--app-background); +} + +body.noguide { + grid-template-areas: "top-bar top-bar" "app app"; +} + +* { + box-sizing: border-box; + color: var(--text-secondary); +} + +h1, h2, h3, h4, h5, h6 { + color: var(--text-primary); +} + +.top-bar { + position: fixed; + top: 0; + left: 0; + right: 0; + height: 48px; + + display: flex; + align-items: center; + padding: 0 16px; + + box-shadow: #0004 0 2px 5px; + background-color: var(--top-bar-background); + + z-index: 9999; +} + +.top-bar > form { + display: none; +} + +.top-bar > .divider { + flex-grow: 1; +} + +.guide { + position: fixed; + left: 0; + right: 0; + bottom: 0; + height: 48px; + + border-top: 1px solid var(--border-color); + + display: flex; + flex-direction: row; + justify-content: space-around; + + background-color: var(--guide-background); +} + +.top-bar.full-size-search > .logo, +.top-bar.full-size-search > .divider, +.top-bar.full-size-search > .search-button, +.top-bar.full-size-search > .account { + display: none; +} + +.top-bar.full-size-search > form { + height: 40px; + flex-grow: 1; + display: flex !important; +} + +.top-bar.full-size-search > form > input { + box-sizing: border-box; + height: 40px; + border: 1px solid var(--border-color); + border-radius: 0; + color: var(--text-primary); + background-color: var(--item-active-background); +} + +.top-bar.full-size-search > form > input[type=text] { + flex-grow: 1; +} + +.top-bar.full-size-search > form > input[type=submit] { + width: 64px; + flex-basis: 64px; +} + +.app { + background-color: var(--app-background); + margin-top: 48px; +} + +a.icon-link, a.icon-link > i { + width: 32px; + height: 32px; + line-height: 32px; + text-align: center; +} + +.noguide > .guide { + display: none; +} + +/* guide */ + +.guide-item > a { + height: 100%; + padding: 0 24px; + display: flex; + text-align: center; + flex-direction: column; + font-size: x-small; + align-items: center; + text-decoration: none; + justify-content: center; + + color: var(--text-primary); +} + +.guide-item > a > .icon { + width: 24px; + height: 24px; + line-height: 24px; + font-size: initial; + margin-right: 0; +} + +.guide-item:hover { + background-color: var(--item-hover-background); +} + +.guide-item.active { + background-color: var(--item-active-background); +} + +.hide-on-minmode { + display: none; +} + +.show-on-minmode { + display: none; +} + +/* top bar */ + +.logo { + color: var(--text-primary) !important; + text-decoration: none; + font-size: larger; +} + +.account { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; +} + +.account > img { + width: 32px; + height: 32px; +} + +.account-menu { + display: none; +} + +.search-button { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; +} + +/* rich video grid */ + +@media screen and (min-width: 850px) { + .rich-video-grid { + width: 100%; + + display: flex; + flex-wrap: wrap; + gap: 16px 16px; + padding-top: 16px; + justify-content: space-evenly; + } + + .rich-video-grid > .video { + display: grid; + grid-template-columns: 52px 1fr; + grid-template-rows: min-content min-content; + grid-auto-flow: row; + grid-gap: 10px 0; + grid-template-areas: + "thumbnail thumbnail" + "avatar info"; + + margin-bottom: 16px; + width: 400px; + } +} + +@media screen and (max-width: 850px) { + .rich-video-grid { + width: 100%; + } + + .rich-video-grid > .video { + display: grid; + grid-template-columns: 52px 1fr; + grid-template-rows: min-content min-content; + grid-auto-flow: row; + grid-gap: 10px 0; + grid-template-areas: + "thumbnail thumbnail" + "avatar info"; + + margin-bottom: 16px; + } +} + +/* list video item */ + +.video a { + text-decoration: none; + color: #606060; +} + +.video > .thumbnail { + grid-area: thumbnail; + background-color: #CCC; + width: 100%; + height: fit-content; + aspect-ratio: 16 / 9; + + display: flex; + justify-content: flex-end; + align-items: flex-end; + padding: 4px; + + background-position-y: center; + background-size: cover; +} + +.video > .thumbnail.img-thumbnail { + padding: 0 !important; +} + +.video > .thumbnail > img { + object-fit: cover; + width: 100%; + height: 100%; +} + +.video > .thumbnail > span { + font-size: smaller; + + background-color: #0008; + color: #fff; + padding: 2px; + border-radius: 2px; +} + +.video > .avatar { + grid-area: avatar; + width: 36px; + height: 36px; + border-radius: 18px; + background-color: #E3E3E3; + + margin-left: 12px; +} + +.video > .avatar > img { + width: 36px; + height: 36px; + border-radius: 18px; +} + +.video > .info { + grid-area: info; +} + +.video > .info > div { + display: flex; + flex-direction: row; + flex-wrap: wrap; + color: #606060; + column-gap: 8px; + overflow-y: hidden; +} + +.video > .info > .title { + color: var(--text-primary) !important; +} + +/* playlist video item */ + +.playlist-video a { + text-decoration: none; + color: #606060; +} + +.playlist-video > .thumbnail { + grid-area: thumbnail; + background-color: #CCC; + width: 100%; + height: fit-content; + aspect-ratio: 16 / 9; + + display: flex; + justify-content: flex-end; + align-items: flex-end; + padding: 4px; + + background-position-y: center; + background-size: cover; +} + +.playlist-video > .thumbnail > span { + font-size: smaller; + + background-color: #0008; + color: #fff; + padding: 2px; + border-radius: 2px; +} + +.playlist-video > .avatar { + grid-area: avatar; + width: 36px; + height: 36px; + border-radius: 18px; + background-color: #E3E3E3; + + margin-left: 12px; +} + +.playlist-video > .avatar > img { + width: 36px; + height: 36px; + border-radius: 18px; +} + +.playlist-video > .info { + grid-area: info; +} + +.playlist-video > .info > div { + display: flex; + flex-direction: row; + flex-wrap: wrap; + color: #606060; + column-gap: 8px; + overflow-y: hidden; +} + +.playlist-video > .info > .title { + color: var(--text-primary) !important; +} + +.playlist-video > .index { + grid-area: index; + display: none; +} + +.playlist-video > .edit { + grid-area: edit; + display: flex; + justify-content: center; + align-items: center; +} + +/* list playlist item */ + +.playlist a { + text-decoration: none; + color: var(--text-secondary); +} + +.playlist > .thumbnail { + grid-area: thumbnail; + + background-color: #CCC; + + display: flex; + justify-content: flex-end; + align-items: center; + + background-position-y: center; + background-size: cover; +} + +.playlist > .thumbnail > div { + font-size: smaller; + + background-color: #0008; + color: #fff; + padding: 2px; + width: 50%; + height: 100%; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + row-gap: 8px; +} + +.playlist > .thumbnail > div > * { + color: #fff; +} + +.playlist > .thumbnail > div > *:nth-child(1) { + font-size: x-large; +} + +.playlist > .info { + grid-area: info; + font-size: small; +} + +.playlist > .info > div > ul { + display: none; +} + +.playlist > .info > .title { + color: var(--text-primary) !important; + font-weight: bold; + font-size: initial; + margin-bottom: 8px; +} + +/* list playlist item */ + +.channel a { + text-decoration: none; + color: var(--text-secondary); +} + +.channel > .avatar { + grid-area: thumbnail; + + display: flex; + justify-content: center; + align-items: center; +} + +.channel > .avatar > img { + background-color: #CCC; + + height: 90px; + width: 90px; +} + +.channel > .info { + grid-area: info; + font-size: small; +} + +.channel > .info > .name { + color: var(--text-primary) !important; + font-weight: bold; + font-size: initial; + margin-bottom: 8px; +} + +.channel > .info p { + display: none; +} + +/* watch page */ + +.watch-page { + display: grid; + grid-template-columns: 1fr 256px; + grid-template-rows: 1fr; + grid-template-areas: "primary secondary"; +} + +@media screen and (max-width: 900px) { + .watch-page { + grid-template-areas: "primary" "secondary"; + grid-template-columns: 1fr; + grid-template-rows: max-content 1fr; + } +} + +.primary { + grid-area: primary; +} + +.video-player-container { + max-width: 100%; + margin: auto; + max-height: 75vh; + aspect-ratio: 16 / 9; + background-color: #000; +} + +.player { + width: 100%; + height: 100%; +} + +.player.error { + display: flex; + align-items: center; + justify-content: center; + background-color: #ccc; + background-image: url('/img/player-error.png') !important; + background-size: contain; +} + +.player.error > * { + background-color: #000; + color: #fff; +} + +.video-info { + padding: 12px; +} + +.video-title { + font-size: large; + color: var(--text-primary); +} + +.video-info-bar { + font-size: small; + display: grid; + grid-auto-columns: 1fr; + grid-template-columns: max-content max-content max-content 1fr max-content; + grid-template-rows: max-content max-content; + gap: 0 8px; + grid-template-areas: + "views . uploaddate divider" + "buttons buttons buttons buttons"; +} + +.video-info-bar > span:nth-child(1) { + grid-area: views; +} + +.video-info-bar > .divider { + grid-area: divider; +} + +.video-info-bar > span:nth-child(3) { + grid-area: uploaddate; +} + +.video-info-bar > .video-info-buttons { + grid-area: buttons; +} + +.video-info-buttons { + display: flex; + justify-content: space-evenly; + flex-direction: row; + column-gap: 8px; + padding: 8px 0; +} + +.video-info-buttons > * { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + column-gap: 4px; + text-decoration: none; +} + +.video-info-buttons > * > i.bi { + font-size: x-large; +} + +.channel-info, .channel-info__bordered { + display: grid; + grid-template-columns: 34px max-content 1fr min-content; + grid-template-rows: 34px; + grid-auto-columns: 1fr; + gap: 8px; + grid-auto-flow: row; + grid-template-areas: "avatar name . subscribe-button"; + + padding: 8px 0; + + border-top: 1px solid var(--border-color); + border-bottom: 1px solid var(--border-color); +} + +.avatar { + grid-area: avatar; +} + +.avatar > img { + width: 100%; + height: 100%; + border-radius: 50%; +} + +.name { + grid-area: name; + + display: flex; + flex-direction: column; + justify-content: center; +} + +.name > a { + color: var(--text-primary); + text-decoration: none; +} + +.name > span { + font-size: small; + color: var(--text-secondary); +} + +.subscribe-button { + grid-area: subscribe-button; + + background-color: #0000; + color: #c00; + text-transform: uppercase; + border: none; + + height: 100%; +} + +.subscribe-button.subscribed { + color: var(--text-secondary); +} + +.secondary { + grid-area: secondary; + + padding: 16px 8px; +} + +.resolutions-list { + width: 100%; + padding: 4px; + border: 1px solid var(--border-color); + margin-bottom: 16px; +} + +.resolutions-list > div { + display: flex; + flex-direction: column; + column-gap: 16px; +} + +.resolutions-list > div > * { + line-height: 32px; +} + +.recommended-list { + display: flex; + flex-direction: column; + row-gap: 16px; +} + +.recommended-list > .video { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr max-content; + grid-auto-flow: row; + grid-gap: 0 8px; + grid-template-areas: "thumbnail" "info"; + + color: var(--text-secondary); +} + +.recommended-list > .video > .info { + font-size: small; +} + +.recommended-list > .video > .info > a { + font-size: initial; +} + +.recommended-list > .video > .info > div { + flex-wrap: wrap; + max-height: unset; +} + +/* channel page */ + +.channel-banner { + display: block; + width: 100%; + height: auto; + aspect-ratio: 6.2; + background-color: #000a; + background-size: contain; +} + +.channel-info-container { + background-color: var(--channel-info-background); +} + +.channel-info-container > .channel-info { + grid-template-columns: 50px 1fr; + grid-template-rows: 50px min-content; + grid-template-areas: "avatar name" ". subscribe-button"; + column-gap: 16px; + padding: 16px; +} + +.channel-info-container > .channel-info > .subscribe-button { + width: max-content; +} + +.channel-info-container > .channel-info > .name > *:first-child { + font-size: larger; + color: var(--text-primary); +} + +.channel-info-container > .channel-info > .name > * { + color: var(--text-secondary); +} + +.channel-page > p { + color: var(--text-secondary) +} + +.channel-page .video-grid { + background-color: var(--channel-contents-background); +} + +/* card list item */ + +.card-list { + display: flex; + flex-direction: row; + overflow-x: scroll; + column-gap: 16px; +} + +.card { + width: 150px; + background: var(--context-menu-background); + border: 1px solid var(--border-color); + border-radius: 8px; + text-decoration: none; +} + +.card > img { + aspect-ratio: 16 / 9; + width: 150px; + height: fit-content; +} + +.card > span { + text-decoration: none; + color: var(--text-primary); + margin: 0 8px; +} + +/* channel video "grid" */ + +.video-grid { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + column-gap: 16px; + row-gap: 12px; + padding: 0 12px; +} + +.video-grid > .video { + display: grid; + grid-template-columns: 160px 1fr; + grid-template-rows: 90px; + grid-auto-flow: row; + grid-gap: 10px 10px; + grid-template-areas: + "thumbnail info"; + + color: var(--text-secondary); + text-decoration: none; +} + +.video-grid > .avatar { + display: none; +} + +.video-grid > .video > .info > span { + font-weight: bold; + font-size: initial; +} + +.video-grid > .video > .info > div > div { + display: flex; + flex-direction: column; + flex-wrap: wrap; +} + +/* Pagination links */ + +.pagination-buttons { + border-top: 1px solid var(--border-color); + width: 100%; + display: flex; +} + +.pagination-buttons > * { + height: 3rem; + line-height: 3rem; + color: var(--text-secondary); + text-decoration: none; +} + +.pagination-buttons > .divider { + flex-grow: 1; +} + +/* normal video list */ + +.video-list { + margin: auto; + display: flex; + flex-direction: column; + row-gap: 16px; + padding: 16px; +} + +.video-list > .video { + text-decoration: none; + display: grid; + grid-template-columns: 160px; + grid-template-rows: 90px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "thumbnail info"; + + color: var(--text-secondary); + font-size: small; +} + +.video-list > .playlist-video { + text-decoration: none; + display: grid; + grid-template-columns: 160px 1fr 50px; + grid-template-rows: 90px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "thumbnail info edit"; + + color: var(--text-secondary); + font-size: small; +} + +.video-list > .video > .info > .title, +.video-list > .playlist-video > .info > .title { + font-weight: bold; +} + +.video-list > .video > .info > div > a > img { + display: none; +} + +.video-list > .playlist { + text-decoration: none; + display: grid; + grid-template-columns: 160px; + grid-template-rows: 90px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "thumbnail info"; + + color: var(--text-secondary); +} + +.video-list > .channel { + text-decoration: none; + display: grid; + grid-template-columns: 160px 1fr max-content; + grid-template-rows: 90px; + grid-auto-flow: row; + grid-gap: 0 16px; + grid-template-areas: "thumbnail info subscribe-button"; + + color: var(--text-secondary); +} + +.video-list > .channel > .subscribe-button { + display: none; +} + +/* Playlist page */ + +.playlist-info > .thumbnail { + width: 100%; + height: auto; + aspect-ratio: 16 / 9; + background-color: var(--thumbnail-background); + background-size: contain; +} + +.playlist-info > .thumbnail > a { + display: none; +} + +.playlist-info > .title { + font-size: x-large; + color: var(--text-primary); +} + +.playlist-info { + background-color: var(--channel-contents-background); + padding-bottom: 16px; +} + +.playlist-info > .title, +.playlist-info > .info, +.playlist-info > .description { + display: block; + padding: 0 16px; +} + +.playlist-info > .channel-info { + display: none; +} + +/* horizontal channel list */ + +.horizontal-channel-list { + display: flex; + column-gap: 16px; + padding: 16px; + overflow-x: scroll; + background-color: var(--item-hover-background); +} + +.horizontal-channel-list > .channel { + text-decoration: none; + display: flex; + flex-direction: column; + row-gap: 4px; + color: var(--text-secondary); +} + +.horizontal-channel-list > .channel > div { + font-size: small; + text-align: center; + width: 48px; + color: var(--text-secondary); +} + +.horizontal-channel-list > .channel > img { + width: 48px; + height: 48px; + border-radius: 50%; + background-color: var(--thumbnail-background); +} + +.horizontal-channel-list > .channel > i { + font-size: 24px; + line-height: 48px; + text-align: center; + width: 48px; + height: 48px; + border-radius: 50%; + background-color: var(--thumbnail-background); +} + +/* Login / Register / Delete pages */ + +.login-container { + display: flex; + flex-direction: row; + padding: 24px; +} + +@media screen and (max-width: 1300px) { + .login-container { + flex-direction: column; + } +} + +.login-container > * { + flex: 1 1 0; +} + +.login-container > * > div { + max-width: 600px; + margin: auto; +} + +.login-form { + display: flex; + flex-direction: column; + max-width: 400px; + row-gap: 10px; + margin: auto; +} + +.login-form > input, .login-button { + background-color: var(--item-active-background); + color: var(--text-primary); + border: 1px solid var(--border-color); + padding: 10px; + max-width: 400px; + row-gap: 10px; + margin: auto; +} + +.playlist-form { + display: flex; + flex-direction: column; + max-width: 400px; + row-gap: 10px; + margin: auto; +} + +.playlist-form > input, .playlist-form > select, .login-button { + background-color: var(--item-active-background); + color: var(--text-primary); + border: 1px solid var(--border-color); + padding: 10px; + width: 80%; + row-gap: 10px; + margin: auto; +} + +.login-button { + background-color: var(--item-active-background); + color: var(--text-primary); + display: block; + text-align: center; + text-decoration: none; + width: fit-content; +} + +.login-button.danger { + color: red; + font-weight: bold; +} + +.login-form > h1 { + text-align: center; +} + +.login-message { + width: calc(100% - 96px); + margin: 48px; + padding: 16px; + border: 1px solid var(--border-color); + background-color: var(--item-active-background); + border-radius: 5px; +} + + +/* Account Menu */ + +.fullscreen-account-menu > .guide-item:hover { + background-color: var(--item-hover-background); +} + +.fullscreen-account-menu > .guide-item > a { + height: 40px; + display: flex; + align-items: start; + color: var(--text-primary); + text-decoration: none; + font-size: initial; + padding: 0; +} + +.fullscreen-account-menu > .guide-item > a > .icon { + height: 24px; + width: 24px; + margin-right: 24px; +} + +.fullscreen-account-menu > .guide-item.active { + background-color: var(--item-active-background); +} + +/* download page */ + +.download-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; + column-gap: 32px; +} + +.download-format { + max-width: 400px; + padding: 8px; + display: flex; + flex-direction: column; + row-gap: 8px; +} + +.download-format > div { + color: var(--text-primary); +} + +.download-format > a { + padding: 8px; + background-color: var(--channel-contents-background); + border: 1px solid var(--border-color); + text-decoration: none; +} + +/* settings page */ + +.settings-categories { + background-color: var(--context-menu-background); + display: flex; + column-gap: 16px; + padding: 0 16px; +} + +.settings-categories > a { + height: 3rem; + line-height: 3rem; + padding: 0 8px; + text-decoration: none; +} + +.settings-content { + max-width: 400px; + margin: auto; +} + +.settings-content > div { + width: 100%; + padding: 8px; +} + +.settings-content > div > label { + width: 45%; + display: inline-block; + font-weight: bold; + color: var(--text-primary); +} + +.settings-content > div > select { + width: 50%; + display: inline-block; + border: 1px solid var(--border-color); + padding: 8px; + background-color: var(--context-menu-background); + color: var(--text-primary); +} + +/* logins page */ + +.logins-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-evenly; + gap: 16px; + padding: 16px; +} + +.login { + border: 1px solid var(--border-color); + border-radius: 4px; + width: 500px; + padding: 8px; +} \ No newline at end of file diff --git a/core/LightTube/wwwroot/favicon.ico b/core/LightTube/wwwroot/favicon.ico new file mode 100644 index 00000000..7bd584d6 Binary files /dev/null and b/core/LightTube/wwwroot/favicon.ico differ diff --git a/core/LightTube/wwwroot/icons/collapse_guide.svg b/core/LightTube/wwwroot/icons/collapse_guide.svg new file mode 100644 index 00000000..119e86ff --- /dev/null +++ b/core/LightTube/wwwroot/icons/collapse_guide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/compass.svg b/core/LightTube/wwwroot/icons/compass.svg new file mode 100644 index 00000000..d1ff7845 --- /dev/null +++ b/core/LightTube/wwwroot/icons/compass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/dislike.svg b/core/LightTube/wwwroot/icons/dislike.svg new file mode 100644 index 00000000..4da2de1e --- /dev/null +++ b/core/LightTube/wwwroot/icons/dislike.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/home.svg b/core/LightTube/wwwroot/icons/home.svg new file mode 100644 index 00000000..ad0aa3d5 --- /dev/null +++ b/core/LightTube/wwwroot/icons/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/icons.txt b/core/LightTube/wwwroot/icons/icons.txt new file mode 100644 index 00000000..e34dcc9a --- /dev/null +++ b/core/LightTube/wwwroot/icons/icons.txt @@ -0,0 +1,16 @@ +https://systemuicons.com/ +========================= +home: +https://systemuicons.com/images/icons/home_door.svg +browse: +https://systemuicons.com/images/icons/compass.svg +subscriptions: +- +profile: +https://systemuicons.com/images/icons/user_male_circle.svg +search: +https://systemuicons.com/images/icons/search.svg +like: +https://systemuicons.com/images/icons/thumbs_up.svg +dislike: +https://systemuicons.com/images/icons/thumbs_down.svg diff --git a/core/LightTube/wwwroot/icons/like.svg b/core/LightTube/wwwroot/icons/like.svg new file mode 100644 index 00000000..3388d8e3 --- /dev/null +++ b/core/LightTube/wwwroot/icons/like.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/profile.svg b/core/LightTube/wwwroot/icons/profile.svg new file mode 100644 index 00000000..7ddf938d --- /dev/null +++ b/core/LightTube/wwwroot/icons/profile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/search.svg b/core/LightTube/wwwroot/icons/search.svg new file mode 100644 index 00000000..40eb8c90 --- /dev/null +++ b/core/LightTube/wwwroot/icons/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/settings.svg b/core/LightTube/wwwroot/icons/settings.svg new file mode 100644 index 00000000..960a0bdf --- /dev/null +++ b/core/LightTube/wwwroot/icons/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/subscriptions.svg b/core/LightTube/wwwroot/icons/subscriptions.svg new file mode 100644 index 00000000..f067e2a2 --- /dev/null +++ b/core/LightTube/wwwroot/icons/subscriptions.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/icons/uncollapse_guide.svg b/core/LightTube/wwwroot/icons/uncollapse_guide.svg new file mode 100644 index 00000000..057dfabe --- /dev/null +++ b/core/LightTube/wwwroot/icons/uncollapse_guide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core/LightTube/wwwroot/img/player-error.png b/core/LightTube/wwwroot/img/player-error.png new file mode 100644 index 00000000..afdb669b Binary files /dev/null and b/core/LightTube/wwwroot/img/player-error.png differ diff --git a/core/LightTube/wwwroot/img/spinner.gif b/core/LightTube/wwwroot/img/spinner.gif new file mode 100644 index 00000000..0b3ba628 Binary files /dev/null and b/core/LightTube/wwwroot/img/spinner.gif differ diff --git a/core/LightTube/wwwroot/js/hls.js/hls.min.js b/core/LightTube/wwwroot/js/hls.js/hls.min.js new file mode 100644 index 00000000..46a96813 --- /dev/null +++ b/core/LightTube/wwwroot/js/hls.js/hls.min.js @@ -0,0 +1,2 @@ +/* hls.js v1.1.5 - https://github.com/video-dev/hls.js/ */ +"undefined"!=typeof window&&function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Hls=e():t.Hls=e()}(this,(function(){return function(t){var e={};function r(i){if(e[i])return e[i].exports;var n=e[i]={i:i,l:!1,exports:{}};return t[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=t,r.c=e,r.d=function(t,e,i){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)r.d(i,n,function(e){return t[e]}.bind(null,n));return i},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="/dist/",r(r.s=20)}([function(t,e,r){"use strict";var i;r.d(e,"a",(function(){return i})),function(t){t.MEDIA_ATTACHING="hlsMediaAttaching",t.MEDIA_ATTACHED="hlsMediaAttached",t.MEDIA_DETACHING="hlsMediaDetaching",t.MEDIA_DETACHED="hlsMediaDetached",t.BUFFER_RESET="hlsBufferReset",t.BUFFER_CODECS="hlsBufferCodecs",t.BUFFER_CREATED="hlsBufferCreated",t.BUFFER_APPENDING="hlsBufferAppending",t.BUFFER_APPENDED="hlsBufferAppended",t.BUFFER_EOS="hlsBufferEos",t.BUFFER_FLUSHING="hlsBufferFlushing",t.BUFFER_FLUSHED="hlsBufferFlushed",t.MANIFEST_LOADING="hlsManifestLoading",t.MANIFEST_LOADED="hlsManifestLoaded",t.MANIFEST_PARSED="hlsManifestParsed",t.LEVEL_SWITCHING="hlsLevelSwitching",t.LEVEL_SWITCHED="hlsLevelSwitched",t.LEVEL_LOADING="hlsLevelLoading",t.LEVEL_LOADED="hlsLevelLoaded",t.LEVEL_UPDATED="hlsLevelUpdated",t.LEVEL_PTS_UPDATED="hlsLevelPtsUpdated",t.LEVELS_UPDATED="hlsLevelsUpdated",t.AUDIO_TRACKS_UPDATED="hlsAudioTracksUpdated",t.AUDIO_TRACK_SWITCHING="hlsAudioTrackSwitching",t.AUDIO_TRACK_SWITCHED="hlsAudioTrackSwitched",t.AUDIO_TRACK_LOADING="hlsAudioTrackLoading",t.AUDIO_TRACK_LOADED="hlsAudioTrackLoaded",t.SUBTITLE_TRACKS_UPDATED="hlsSubtitleTracksUpdated",t.SUBTITLE_TRACKS_CLEARED="hlsSubtitleTracksCleared",t.SUBTITLE_TRACK_SWITCH="hlsSubtitleTrackSwitch",t.SUBTITLE_TRACK_LOADING="hlsSubtitleTrackLoading",t.SUBTITLE_TRACK_LOADED="hlsSubtitleTrackLoaded",t.SUBTITLE_FRAG_PROCESSED="hlsSubtitleFragProcessed",t.CUES_PARSED="hlsCuesParsed",t.NON_NATIVE_TEXT_TRACKS_FOUND="hlsNonNativeTextTracksFound",t.INIT_PTS_FOUND="hlsInitPtsFound",t.FRAG_LOADING="hlsFragLoading",t.FRAG_LOAD_EMERGENCY_ABORTED="hlsFragLoadEmergencyAborted",t.FRAG_LOADED="hlsFragLoaded",t.FRAG_DECRYPTED="hlsFragDecrypted",t.FRAG_PARSING_INIT_SEGMENT="hlsFragParsingInitSegment",t.FRAG_PARSING_USERDATA="hlsFragParsingUserdata",t.FRAG_PARSING_METADATA="hlsFragParsingMetadata",t.FRAG_PARSED="hlsFragParsed",t.FRAG_BUFFERED="hlsFragBuffered",t.FRAG_CHANGED="hlsFragChanged",t.FPS_DROP="hlsFpsDrop",t.FPS_DROP_LEVEL_CAPPING="hlsFpsDropLevelCapping",t.ERROR="hlsError",t.DESTROYING="hlsDestroying",t.KEY_LOADING="hlsKeyLoading",t.KEY_LOADED="hlsKeyLoaded",t.LIVE_BACK_BUFFER_REACHED="hlsLiveBackBufferReached",t.BACK_BUFFER_REACHED="hlsBackBufferReached"}(i||(i={}))},function(t,e,r){"use strict";r.d(e,"a",(function(){return o})),r.d(e,"b",(function(){return l}));var i=function(){},n={trace:i,debug:i,log:i,warn:i,info:i,error:i},a=n;function s(t){var e=self.console[t];return e?e.bind(self.console,"["+t+"] >"):i}function o(t){if(self.console&&!0===t||"object"==typeof t){!function(t){for(var e=arguments.length,r=new Array(e>1?e-1:0),i=1;i>8*(15-r)&255;return e},r.setDecryptDataFromLevelKey=function(t,e){var r=t;return"AES-128"===(null==t?void 0:t.method)&&t.uri&&!t.iv&&((r=o.a.fromURI(t.uri)).method=t.method,r.iv=this.createInitializationVector(e),r.keyFormat="identity"),r},r.setElementaryStreamInfo=function(t,e,r,i,n,a){void 0===a&&(a=!1);var s=this.elementaryStreams,o=s[t];o?(o.startPTS=Math.min(o.startPTS,e),o.endPTS=Math.max(o.endPTS,r),o.startDTS=Math.min(o.startDTS,i),o.endDTS=Math.max(o.endDTS,n)):s[t]={startPTS:e,endPTS:r,startDTS:i,endDTS:n,partial:a}},r.clearElementaryStreamInfo=function(){var t=this.elementaryStreams;t[i.AUDIO]=null,t[i.VIDEO]=null,t[i.AUDIOVIDEO]=null},c(e,[{key:"decryptdata",get:function(){if(!this.levelkey&&!this._decryptdata)return null;if(!this._decryptdata&&this.levelkey){var t=this.sn;"number"!=typeof t&&(this.levelkey&&"AES-128"===this.levelkey.method&&!this.levelkey.iv&&s.b.warn('missing IV for initialization segment with method="'+this.levelkey.method+'" - compliance issue'),t=0),this._decryptdata=this.setDecryptDataFromLevelKey(this.levelkey,t)}return this._decryptdata}},{key:"end",get:function(){return this.start+this.duration}},{key:"endProgramDateTime",get:function(){if(null===this.programDateTime)return null;if(!Object(n.a)(this.programDateTime))return null;var t=Object(n.a)(this.duration)?this.duration:0;return this.programDateTime+1e3*t}},{key:"encrypted",get:function(){var t;return!(null===(t=this.decryptdata)||void 0===t||!t.keyFormat||!this.decryptdata.uri)}}]),e}(f),v=function(t){function e(e,r,i,n,a){var s;(s=t.call(this,i)||this).fragOffset=0,s.duration=0,s.gap=!1,s.independent=!1,s.relurl=void 0,s.fragment=void 0,s.index=void 0,s.stats=new l.a,s.duration=e.decimalFloatingPoint("DURATION"),s.gap=e.bool("GAP"),s.independent=e.bool("INDEPENDENT"),s.relurl=e.enumeratedString("URI"),s.fragment=r,s.index=n;var o=e.enumeratedString("BYTERANGE");return o&&s.setByteRange(o,a),a&&(s.fragOffset=a.fragOffset+a.duration),s}return u(e,t),c(e,[{key:"start",get:function(){return this.fragment.start+this.fragOffset}},{key:"end",get:function(){return this.start+this.duration}},{key:"loaded",get:function(){var t=this.elementaryStreams;return!!(t.audio||t.video||t.audiovideo)}}]),e}(f)},function(t,e,r){"use strict";r.d(e,"b",(function(){return h})),r.d(e,"g",(function(){return d})),r.d(e,"f",(function(){return c})),r.d(e,"d",(function(){return f})),r.d(e,"c",(function(){return g})),r.d(e,"e",(function(){return p})),r.d(e,"h",(function(){return m})),r.d(e,"a",(function(){return y}));var i=r(9),n=r(5),a=Math.pow(2,32)-1,s=[].push;function o(t){return String.fromCharCode.apply(null,t)}function l(t,e){"data"in t&&(e+=t.start,t=t.data);var r=t[e]<<24|t[e+1]<<16|t[e+2]<<8|t[e+3];return r<0?4294967296+r:r}function u(t,e,r){"data"in t&&(e+=t.start,t=t.data),t[e]=r>>24,t[e+1]=r>>16&255,t[e+2]=r>>8&255,t[e+3]=255&r}function h(t,e){var r,i,n,a=[];if(!e.length)return a;"data"in t?(r=t.data,i=t.start,n=t.end):(i=0,n=(r=t).byteLength);for(var u=i;u1?u+d:n;if(o(r.subarray(u+4,u+8))===e[0])if(1===e.length)a.push({data:r,start:u+8,end:c});else{var f=h({data:r,start:u+8,end:c},e.slice(1));f.length&&s.apply(a,f)}u=c}return a}function d(t){var e=h(t,["moov"])[0],r=e?e.end:null,i=h(t,["sidx"]);if(!i||!i[0])return null;var n=[],a=i[0],s=a.data[0],o=0===s?8:16,u=l(a,o);o+=4;o+=0===s?8:16,o+=2;var d=a.end+0,c=function(t,e){"data"in t&&(e+=t.start,t=t.data);var r=t[e]<<8|t[e+1];return r<0?65536+r:r}(a,o);o+=2;for(var f=0;f>>31)return console.warn("SIDX has hierarchical references (not supported)"),null;var m=l(a,g);g+=4,n.push({referenceSize:p,subsegmentDuration:m,info:{duration:m/u,start:d,end:d+p-1}}),d+=p,o=g+=4}return{earliestPresentationTime:0,timescale:u,version:s,referencesCount:c,references:n,moovEndOffset:r}}function c(t){for(var e=[],r=h(t,["moov","trak"]),i=0;i0)return t.subarray(r,r+i)},o=function(t,e){var r=0;return r=(127&t[e])<<21,r|=(127&t[e+1])<<14,r|=(127&t[e+2])<<7,r|=127&t[e+3]},l=function(t,e){return n(t,e)&&o(t,e+6)+10<=t.length-e},u=function(t){for(var e=c(t),r=0;r>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:u+=String.fromCharCode(a);break;case 12:case 13:s=t[h++],u+=String.fromCharCode((31&a)<<6|63&s);break;case 14:s=t[h++],o=t[h++],u+=String.fromCharCode((15&a)<<12|(63&s)<<6|(63&o)<<0)}}return u};function T(){return i||void 0===self.TextDecoder||(i=new self.TextDecoder("utf-8")),i}},function(t,e,r){"use strict";r.d(e,"c",(function(){return n})),r.d(e,"b",(function(){return a})),r.d(e,"a",(function(){return s}));function i(t,e,r,i){void 0===r&&(r=1),void 0===i&&(i=!1);var n=t*e*r;return i?Math.round(n):n}function n(t,e,r,n){return void 0===r&&(r=1),void 0===n&&(n=!1),i(t,e,1/r,n)}function a(t,e){return void 0===e&&(e=!1),i(t,1e3,1/9e4,e)}function s(t,e){return void 0===e&&(e=1),i(t,9e4,1/e)}},function(t,e,r){"use strict";function i(t,e,r){return Uint8Array.prototype.slice?t.slice(e,r):new Uint8Array(Array.prototype.slice.call(t,e,r))}r.d(e,"a",(function(){return i}))},function(t,e,r){"use strict";r.d(e,"c",(function(){return lt})),r.d(e,"d",(function(){return ht})),r.d(e,"a",(function(){return dt})),r.d(e,"b",(function(){return ct}));var i=r(0),n=r(2),a=r(15),s=r(3),o=r(7);var l=r(6),u=r(9),h=function(){function t(){this._audioTrack=void 0,this._id3Track=void 0,this.frameIndex=0,this.cachedData=null,this.initPTS=null}var e=t.prototype;return e.resetInitSegment=function(t,e,r){this._id3Track={type:"id3",id:3,pid:-1,inputTimeScale:9e4,sequenceNumber:0,samples:[],dropped:0}},e.resetTimeStamp=function(){},e.resetContiguity=function(){},e.canParse=function(t,e){return!1},e.appendFrame=function(t,e,r){},e.demux=function(t,e){this.cachedData&&(t=Object(l.a)(this.cachedData,t),this.cachedData=null);var r,i,n=o.b(t,0),a=n?n.length:0,s=this._audioTrack,h=this._id3Track,c=n?o.d(n):void 0,f=t.length;for(0!==this.frameIndex&&null!==this.initPTS||(this.initPTS=d(c,e)),n&&n.length>0&&h.samples.push({pts:this.initPTS,dts:this.initPTS,data:n}),i=this.initPTS;a>>5}function m(t,e){return e+1=t.length)return!1;var i=p(t,e);if(i<=r)return!1;var n=e+i;return n===t.length||m(t,n)}return!1}function T(t,e,r,a,s){if(!t.samplerate){var o=function(t,e,r,a){var s,o,l,u,h=navigator.userAgent.toLowerCase(),d=a,c=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350];s=1+((192&e[r+2])>>>6);var g=(60&e[r+2])>>>2;if(!(g>c.length-1))return l=(1&e[r+2])<<2,l|=(192&e[r+3])>>>6,f.b.log("manifest codec:"+a+", ADTS type:"+s+", samplingIndex:"+g),/firefox/i.test(h)?g>=6?(s=5,u=new Array(4),o=g-3):(s=2,u=new Array(2),o=g):-1!==h.indexOf("android")?(s=2,u=new Array(2),o=g):(s=5,u=new Array(4),a&&(-1!==a.indexOf("mp4a.40.29")||-1!==a.indexOf("mp4a.40.5"))||!a&&g>=6?o=g-3:((a&&-1!==a.indexOf("mp4a.40.2")&&(g>=6&&1===l||/vivaldi/i.test(h))||!a&&1===l)&&(s=2,u=new Array(2)),o=g)),u[0]=s<<3,u[0]|=(14&g)>>1,u[1]|=(1&g)<<7,u[1]|=l<<3,5===s&&(u[1]|=(14&o)>>1,u[2]=(1&o)<<7,u[2]|=8,u[3]=0),{config:u,samplerate:c[g],channelCount:l,codec:"mp4a.40."+s,manifestCodec:d};t.trigger(i.a.ERROR,{type:n.b.MEDIA_ERROR,details:n.a.FRAG_PARSING_ERROR,fatal:!0,reason:"invalid ADTS sampling index:"+g})}(e,r,a,s);if(!o)return;t.config=o.config,t.samplerate=o.samplerate,t.channelCount=o.channelCount,t.codec=o.codec,t.manifestCodec=o.manifestCodec,f.b.log("parsed codec:"+t.codec+", rate:"+o.samplerate+", channels:"+o.channelCount)}}function b(t){return 9216e4/t}function E(t,e,r,i,n){var a=function(t,e,r,i,n){var a=v(t,e),s=p(t,e);if((s-=a)>0)return{headerLength:a,frameLength:s,stamp:r+i*n}}(e,r,i,n,b(t.samplerate));if(a){var s,o=a.frameLength,l=a.headerLength,u=a.stamp,h=l+o,d=Math.max(0,r+h-e.length);d?(s=new Uint8Array(h-l)).set(e.subarray(r+l,e.length),0):s=e.subarray(r+l,r+h);var c={unit:s,pts:u};return d||t.samples.push(c),{sample:c,length:h,missing:d}}}function S(t,e){return(S=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}var L=function(t){var e,r;function i(e,r){var i;return(i=t.call(this)||this).observer=void 0,i.config=void 0,i.observer=e,i.config=r,i}r=t,(e=i).prototype=Object.create(r.prototype),e.prototype.constructor=e,S(e,r);var n=i.prototype;return n.resetInitSegment=function(e,r,i){t.prototype.resetInitSegment.call(this,e,r,i),this._audioTrack={container:"audio/adts",type:"audio",id:2,pid:-1,sequenceNumber:0,isAAC:!0,samples:[],manifestCodec:e,duration:i,inputTimeScale:9e4,dropped:0}},i.probe=function(t){if(!t)return!1;for(var e=(o.b(t,0)||[]).length,r=t.length;e0},e.demux=function(t){var e=t,r={type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0};if(this.config.progressive){this.remainderData&&(e=Object(l.a)(this.remainderData,t));var i=Object(l.h)(e);this.remainderData=i.remainder,r.samples=i.valid||new Uint8Array}else r.samples=e;return{audioTrack:{type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0},avcTrack:r,id3Track:{type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0},textTrack:{type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0}}},e.flush=function(){var t={type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0};return t.samples=this.remainderData||new Uint8Array,this.remainderData=null,{audioTrack:{type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0},avcTrack:t,id3Track:{type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0},textTrack:{type:"",id:-1,pid:-1,inputTimeScale:9e4,sequenceNumber:-1,samples:[],dropped:0}}},e.demuxSampleAes=function(t,e,r){return Promise.reject(new Error("The MP4 demuxer does not support SAMPLE-AES decryption"))},e.destroy=function(){},t}();R.minProbeByteLength=1024;var D=R,k=null,_=[32,64,96,128,160,192,224,256,288,320,352,384,416,448,32,48,56,64,80,96,112,128,160,192,224,256,320,384,32,40,48,56,64,80,96,112,128,160,192,224,256,320,32,48,56,64,80,96,112,128,144,160,176,192,224,256,8,16,24,32,40,48,56,64,80,96,112,128,144,160],I=[44100,48e3,32e3,22050,24e3,16e3,11025,12e3,8e3],C=[[0,72,144,12],[0,0,0,0],[0,72,144,12],[0,144,144,12]],w=[0,1,1,4];function O(t,e,r,i,n){if(!(r+24>e.length)){var a=x(e,r);if(a&&r+a.frameLength<=e.length){var s=i+n*(9e4*a.samplesPerFrame/a.sampleRate),o={unit:e.subarray(r,r+a.frameLength),pts:s,dts:s};return t.config=[],t.channelCount=a.channelCount,t.samplerate=a.sampleRate,t.samples.push(o),{sample:o,length:a.frameLength,missing:0}}}}function x(t,e){var r=t[e+1]>>3&3,i=t[e+1]>>1&3,n=t[e+2]>>4&15,a=t[e+2]>>2&3;if(1!==r&&0!==n&&15!==n&&3!==a){var s=t[e+2]>>1&1,o=t[e+3]>>6,l=1e3*_[14*(3===r?3-i:3===i?3:4)+n-1],u=I[3*(3===r?0:2===r?1:2)+a],h=3===o?1:2,d=C[r][i],c=w[i],f=8*d*c,g=Math.floor(d*l/u+s)*c;if(null===k){var v=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);k=v?parseInt(v[1]):0}return!!k&&k<=87&&2===i&&l>=224e3&&0===o&&(t[e+3]=128|t[e+3]),{sampleRate:u,channelCount:h,frameLength:g,samplesPerFrame:f}}}function P(t,e){return 255===t[e]&&224==(224&t[e+1])&&0!=(6&t[e+1])}function M(t,e){return e+1t?(this.word<<=t,this.bitsAvailable-=t):(t-=this.bitsAvailable,t-=(e=t>>3)>>3,this.bytesAvailable-=e,this.loadWord(),this.word<<=t,this.bitsAvailable-=t)},e.readBits=function(t){var e=Math.min(this.bitsAvailable,t),r=this.word>>>32-e;return t>32&&f.b.error("Cannot read more than 32 bits at a time"),this.bitsAvailable-=e,this.bitsAvailable>0?this.word<<=e:this.bytesAvailable>0&&this.loadWord(),(e=t-e)>0&&this.bitsAvailable?r<>>t))return this.word<<=t,this.bitsAvailable-=t,t;return this.loadWord(),t+this.skipLZ()},e.skipUEG=function(){this.skipBits(1+this.skipLZ())},e.skipEG=function(){this.skipBits(1+this.skipLZ())},e.readUEG=function(){var t=this.skipLZ();return this.readBits(t+1)-1},e.readEG=function(){var t=this.readUEG();return 1&t?1+t>>>1:-1*(t>>>1)},e.readBoolean=function(){return 1===this.readBits(1)},e.readUByte=function(){return this.readBits(8)},e.readUShort=function(){return this.readBits(16)},e.readUInt=function(){return this.readBits(32)},e.skipScalingList=function(t){for(var e=8,r=8,i=0;i=t.length)return void r();if(!(t[e].unit.length<32)){var i=this.decrypter.isSync();if(this.decryptAacSample(t,e,r,i),!i)return}}},e.getAvcEncryptedData=function(t){for(var e=16*Math.floor((t.length-48)/160)+16,r=new Int8Array(e),i=0,n=32;n=t.length)return void i();for(var n=t[e].units;!(r>=n.length);r++){var a=n[r];if(!(a.data.length<=48||1!==a.type&&5!==a.type)){var s=this.decrypter.isSync();if(this.decryptAvcSample(t,e,r,i,a,s),!s)return}}}},t}(),B={video:1,audio:2,id3:3,text:4},G=function(){function t(t,e,r){this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.sampleAes=null,this.pmtParsed=!1,this.audioCodec=void 0,this.videoCodec=void 0,this._duration=0,this.aacLastPTS=null,this._initPTS=null,this._initDTS=null,this._pmtId=-1,this._avcTrack=void 0,this._audioTrack=void 0,this._id3Track=void 0,this._txtTrack=void 0,this.aacOverFlow=null,this.avcSample=null,this.remainderData=null,this.observer=t,this.config=e,this.typeSupported=r}t.probe=function(e){var r=t.syncOffset(e);return!(r<0)&&(r&&f.b.warn("MPEG2-TS detected but first sync word found @ offset "+r+", junk ahead ?"),!0)},t.syncOffset=function(t){for(var e=Math.min(1e3,t.length-564),r=0;r>4>1){if((_=R+5+e[R+4])===R+188)continue}else _=R+4;switch(k){case c:D&&(g&&(o=V(g))&&this.parseAVCPES(o,!1),g={data:[],size:0}),g&&(g.data.push(e.subarray(_,R+188)),g.size+=R+188-_);break;case v:D&&(m&&(o=V(m))&&(h.isAAC?this.parseAACPES(o):this.parseMPEGPES(o)),m={data:[],size:0}),m&&(m.data.push(e.subarray(_,R+188)),m.size+=R+188-_);break;case p:D&&(y&&(o=V(y))&&this.parseID3PES(o),y={data:[],size:0}),y&&(y.data.push(e.subarray(_,R+188)),y.size+=R+188-_);break;case 0:D&&(_+=e[_]+1),E=this._pmtId=j(e,_);break;case E:D&&(_+=e[_]+1);var I=H(e,_,!0===this.typeSupported.mpeg||!0===this.typeSupported.mp3,a);(c=I.avc)>0&&(u.pid=c),(v=I.audio)>0&&(h.pid=v,h.isAAC=I.isAAC),(p=I.id3)>0&&(d.pid=p),T&&!b&&(f.b.log("reparse from beginning"),T=!1,R=L-188),b=this.pmtParsed=!0;break;case 17:case 8191:break;default:T=!0}}else A++;A>0&&this.observer.emit(i.a.ERROR,i.a.ERROR,{type:n.b.MEDIA_ERROR,details:n.a.FRAG_PARSING_ERROR,fatal:!1,reason:"Found "+A+" TS packet/s that do not start with 0x47"}),u.pesData=g,h.pesData=m,d.pesData=y;var C={audioTrack:h,avcTrack:u,id3Track:d,textTrack:this._txtTrack};return s&&this.extractRemainingSamples(C),C},e.flush=function(){var t,e=this.remainderData;return this.remainderData=null,t=e?this.demux(e,-1,!1,!0):{audioTrack:this._audioTrack,avcTrack:this._avcTrack,textTrack:this._txtTrack,id3Track:this._id3Track},this.extractRemainingSamples(t),this.sampleAes?this.decrypt(t,this.sampleAes):t},e.extractRemainingSamples=function(t){var e,r=t.audioTrack,i=t.avcTrack,n=t.id3Track,a=i.pesData,s=r.pesData,o=n.pesData;a&&(e=V(a))?(this.parseAVCPES(e,!0),i.pesData=null):i.pesData=a,s&&(e=V(s))?(r.isAAC?this.parseAACPES(e):this.parseMPEGPES(e),r.pesData=null):(null!=s&&s.size&&f.b.log("last AAC PES packet truncated,might overlap between fragments"),r.pesData=s),o&&(e=V(o))?(this.parseID3PES(e),n.pesData=null):n.pesData=o},e.demuxSampleAes=function(t,e,r){var i=this.demux(t,r,!0,!this.config.progressive),n=this.sampleAes=new U(this.observer,this.config,e);return this.decrypt(i,n)},e.decrypt=function(t,e){return new Promise((function(r){var i=t.audioTrack,n=t.avcTrack;i.samples&&i.isAAC?e.decryptAacSamples(i.samples,0,(function(){n.samples?e.decryptAvcSamples(n.samples,0,0,(function(){r(t)})):r(t)})):n.samples&&e.decryptAvcSamples(n.samples,0,0,(function(){r(t)}))}))},e.destroy=function(){this._initPTS=this._initDTS=null,this._duration=0},e.parseAVCPES=function(t,e){var r,i=this,n=this._avcTrack,a=this.parseAVCNALu(t.data),s=this.avcSample,l=!1;t.data=null,s&&a.length&&!n.audFound&&(W(s,n),s=this.avcSample=K(!1,t.pts,t.dts,"")),a.forEach((function(e){switch(e.type){case 1:r=!0,s||(s=i.avcSample=K(!0,t.pts,t.dts,"")),s.frame=!0;var a=e.data;if(l&&a.length>4){var u=new N(a).readSliceType();2!==u&&4!==u&&7!==u&&9!==u||(s.key=!0)}break;case 5:r=!0,s||(s=i.avcSample=K(!0,t.pts,t.dts,"")),s.key=!0,s.frame=!0;break;case 6:r=!0;var h=new N(q(e.data));h.readUByte();for(var d=0,c=0,f=!1,g=0;!f&&h.bytesAvailable>1;){d=0;do{d+=g=h.readUByte()}while(255===g);c=0;do{c+=g=h.readUByte()}while(255===g);if(4===d&&0!==h.bytesAvailable){if(f=!0,181===h.readUByte())if(49===h.readUShort())if(1195456820===h.readUInt())if(3===h.readUByte()){for(var v=h.readUByte(),p=31&v,m=[v,h.readUByte()],y=0;y16){for(var T=[],b=0;b<16;b++)T.push(h.readUByte().toString(16)),3!==b&&5!==b&&7!==b&&9!==b||T.push("-");for(var E=c-16,S=new Uint8Array(E),L=0;L=0){var d={data:t.subarray(u,l-a-1),type:h};o.push(d)}else{var c=this.getLastNalUnit();if(c&&(s&&l<=4-s&&c.state&&(c.data=c.data.subarray(0,c.data.byteLength-s)),(r=l-a-1)>0)){var f=new Uint8Array(c.data.byteLength+r);f.set(c.data,0),f.set(t.subarray(0,r),c.data.byteLength),c.data=f,c.state=0}}l=0&&a>=0){var g={data:t.subarray(u,i),type:h,state:a};o.push(g)}if(0===o.length){var v=this.getLastNalUnit();if(v){var p=new Uint8Array(v.data.byteLength+t.byteLength);p.set(v.data,0),p.set(t,v.data.byteLength),v.data=p}}return n.naluState=a,o},e.parseAACPES=function(t){var e,r,a,s,o,l=0,u=this._audioTrack,h=this.aacOverFlow,d=t.data;if(h){this.aacOverFlow=null;var c=h.sample.unit.byteLength,g=Math.min(h.missing,c),v=c-g;h.sample.unit.set(d.subarray(0,g),v),u.samples.push(h.sample),l=h.missing}for(e=l,r=d.length;e1;){var l=new Uint8Array(o[0].length+o[1].length);l.set(o[0]),l.set(o[1],o[0].length),o[0]=l,o.splice(1,1)}if(1===((e=o[0])[0]<<16)+(e[1]<<8)+e[2]){if((r=(e[4]<<8)+e[5])&&r>t.size-6)return null;var u=e[7];192&u&&(n=536870912*(14&e[9])+4194304*(255&e[10])+16384*(254&e[11])+128*(255&e[12])+(254&e[13])/2,64&u?n-(a=536870912*(14&e[14])+4194304*(255&e[15])+16384*(254&e[16])+128*(255&e[17])+(254&e[18])/2)>54e5&&(f.b.warn(Math.round((n-a)/9e4)+"s delta between PTS and DTS, align them"),n=a):a=n);var h=(i=e[8])+9;if(t.size<=h)return null;t.size-=h;for(var d=new Uint8Array(t.size),c=0,g=o.length;cv){h-=v;continue}e=e.subarray(h),v-=h,h=0}d.set(e,s),s+=v}return r&&(r-=i+3),{data:d,pts:n,dts:a,len:r}}return null}function W(t,e){if(t.units.length&&t.frame){if(void 0===t.pts){var r=e.samples,i=r.length;if(!i)return void e.dropped++;var n=r[i-1];t.pts=n.pts,t.dts=n.dts}e.samples.push(t)}t.debug.length&&f.b.log(t.pts+"/"+t.dts+":"+t.debug)}function Y(t,e){var r=t.length;if(r>0){if(e.pts>=t[r-1].pts)t.push(e);else for(var i=r-1;i>=0;i--)if(e.pts0?this.lastEndDTS=p:(f.b.warn("Duration parsed from mp4 should be greater than zero"),this.resetNextTimestamp());var m=!!c.audio,y=!!c.video,T="";m&&(T+="audio"),y&&(T+="video");var b={data1:h,startPTS:v,startDTS:v,endPTS:p,endDTS:p,type:T,hasAudio:m,hasVideo:y,nb:1,dropped:0};return u.audio="audio"===b.type?b:void 0,u.video="audio"!==b.type?b:void 0,u.text=i,u.id3=r,u.initSegment=d,u},t}(),et=function(t,e,r){return Object(l.d)(t,e)-r};function rt(t,e){var r=null==t?void 0:t.codec;return r&&r.length>4?r:"hvc1"===r?"hvc1.1.c.L120.90":"av01"===r?"av01.0.04M.08":"avc1"===r||e===Z.a.VIDEO?"avc1.42e01e":"mp4a.40.5"}var it,nt=tt,at=r(13);try{it=self.performance.now.bind(self.performance)}catch(t){f.b.debug("Unable to use Performance API on this environment"),it=self.Date.now}var st=[{demux:X,remux:J.a},{demux:D,remux:nt},{demux:A,remux:J.a},{demux:$,remux:J.a}],ot=1024;st.forEach((function(t){var e=t.demux;ot=Math.max(ot,e.minProbeByteLength)}));var lt=function(){function t(t,e,r,i,n){this.observer=void 0,this.typeSupported=void 0,this.config=void 0,this.vendor=void 0,this.id=void 0,this.demuxer=void 0,this.remuxer=void 0,this.decrypter=void 0,this.probe=void 0,this.decryptionPromise=null,this.transmuxConfig=void 0,this.currentTransmuxState=void 0,this.cache=new at.a,this.observer=t,this.typeSupported=e,this.config=r,this.vendor=i,this.id=n}var e=t.prototype;return e.configure=function(t){this.transmuxConfig=t,this.decrypter&&this.decrypter.reset()},e.push=function(t,e,r,i){var n=this,a=r.transmuxing;a.executeStart=it();var s=new Uint8Array(t),o=this.cache,u=this.config,h=this.currentTransmuxState,d=this.transmuxConfig;i&&(this.currentTransmuxState=i);var c=function(t,e){var r=null;t.byteLength>0&&null!=e&&null!=e.key&&null!==e.iv&&null!=e.method&&(r=e);return r}(s,e);if(c&&"AES-128"===c.method){var f=this.getDecrypter();if(!u.enableSoftwareAES)return this.decryptionPromise=f.webCryptoDecrypt(s,c.key.buffer,c.iv.buffer).then((function(t){var e=n.push(t,null,r);return n.decryptionPromise=null,e})),this.decryptionPromise;var g=f.softwareDecrypt(s,c.key.buffer,c.iv.buffer);if(!g)return a.executeEnd=it(),ut(r);s=new Uint8Array(g)}var v=i||h,p=v.contiguous,m=v.discontinuity,y=v.trackSwitch,T=v.accurateTimeOffset,b=v.timeOffset,E=v.initSegmentChange,S=d.audioCodec,L=d.videoCodec,A=d.defaultInitPts,R=d.duration,D=d.initSegmentData;if((m||y||E)&&this.resetInitSegment(D,S,L,R),(m||E)&&this.resetInitialTimestamp(A),p||this.resetContiguity(),this.needsProbing(s,m,y)){if(o.dataLength){var k=o.flush();s=Object(l.a)(k,s)}this.configureTransmuxer(s,d)}var _=this.transmux(s,c,b,T,r),I=this.currentTransmuxState;return I.contiguous=!0,I.discontinuity=!1,I.trackSwitch=!1,a.executeEnd=it(),_},e.flush=function(t){var e=this,r=t.transmuxing;r.executeStart=it();var a=this.decrypter,s=this.cache,o=this.currentTransmuxState,l=this.decryptionPromise;if(l)return l.then((function(){return e.flush(t)}));var u=[],h=o.timeOffset;if(a){var d=a.flush();d&&u.push(this.push(d,null,t))}var c=s.dataLength;s.reset();var f=this.demuxer,g=this.remuxer;if(!f||!g)return c>=ot&&this.observer.emit(i.a.ERROR,i.a.ERROR,{type:n.b.MEDIA_ERROR,details:n.a.FRAG_PARSING_ERROR,fatal:!0,reason:"no demux matching with content found"}),r.executeEnd=it(),[ut(t)];var v=f.flush(h);return ht(v)?v.then((function(r){return e.flushRemux(u,r,t),u})):(this.flushRemux(u,v,t),u)},e.flushRemux=function(t,e,r){var i=e.audioTrack,n=e.avcTrack,a=e.id3Track,s=e.textTrack,o=this.currentTransmuxState,l=o.accurateTimeOffset,u=o.timeOffset;f.b.log("[transmuxer.ts]: Flushed fragment "+r.sn+(r.part>-1?" p: "+r.part:"")+" of level "+r.level);var h=this.remuxer.remux(i,n,a,s,u,l,!0,this.id);t.push({remuxResult:h,chunkMeta:r}),r.transmuxing.executeEnd=it()},e.resetInitialTimestamp=function(t){var e=this.demuxer,r=this.remuxer;e&&r&&(e.resetTimeStamp(t),r.resetTimeStamp(t))},e.resetContiguity=function(){var t=this.demuxer,e=this.remuxer;t&&e&&(t.resetContiguity(),e.resetNextTimestamp())},e.resetInitSegment=function(t,e,r,i){var n=this.demuxer,a=this.remuxer;n&&a&&(n.resetInitSegment(e,r,i),a.resetInitSegment(t,e,r))},e.destroy=function(){this.demuxer&&(this.demuxer.destroy(),this.demuxer=void 0),this.remuxer&&(this.remuxer.destroy(),this.remuxer=void 0)},e.transmux=function(t,e,r,i,n){return e&&"SAMPLE-AES"===e.method?this.transmuxSampleAes(t,e,r,i,n):this.transmuxUnencrypted(t,r,i,n)},e.transmuxUnencrypted=function(t,e,r,i){var n=this.demuxer.demux(t,e,!1,!this.config.progressive),a=n.audioTrack,s=n.avcTrack,o=n.id3Track,l=n.textTrack;return{remuxResult:this.remuxer.remux(a,s,o,l,e,r,!1,this.id),chunkMeta:i}},e.transmuxSampleAes=function(t,e,r,i,n){var a=this;return this.demuxer.demuxSampleAes(t,e,r).then((function(t){return{remuxResult:a.remuxer.remux(t.audioTrack,t.avcTrack,t.id3Track,t.textTrack,r,i,!1,a.id),chunkMeta:n}}))},e.configureTransmuxer=function(t,e){for(var r,i=this.config,n=this.observer,a=this.typeSupported,s=this.vendor,o=e.audioCodec,l=e.defaultInitPts,u=e.duration,h=e.initSegmentData,d=e.videoCodec,c=0,g=st.length;c>>8^255&p^99,t[f]=p,e[p]=f;var m=c[f],y=c[m],T=c[y],b=257*c[p]^16843008*p;i[f]=b<<24|b>>>8,n[f]=b<<16|b>>>16,a[f]=b<<8|b>>>24,s[f]=b,b=16843009*T^65537*y^257*m^16843008*f,l[p]=b<<24|b>>>8,u[p]=b<<16|b>>>16,h[p]=b<<8|b>>>24,d[p]=b,f?(f=m^c[c[c[T^m]]],g^=c[c[g]]):f=g=1}},e.expandKey=function(t){for(var e=this.uint8ArrayToUint32Array_(t),r=!0,i=0;i1?r-1:0),n=1;n>24&255,o[1]=e>>16&255,o[2]=e>>8&255,o[3]=255&e,o.set(t,4),a=0,e=8;a>24&255,e>>16&255,e>>8&255,255&e,i>>24,i>>16&255,i>>8&255,255&i,n>>24,n>>16&255,n>>8&255,255&n,85,196,0,0]))},t.mdia=function(e){return t.box(t.types.mdia,t.mdhd(e.timescale,e.duration),t.hdlr(e.type),t.minf(e))},t.mfhd=function(e){return t.box(t.types.mfhd,new Uint8Array([0,0,0,0,e>>24,e>>16&255,e>>8&255,255&e]))},t.minf=function(e){return"audio"===e.type?t.box(t.types.minf,t.box(t.types.smhd,t.SMHD),t.DINF,t.stbl(e)):t.box(t.types.minf,t.box(t.types.vmhd,t.VMHD),t.DINF,t.stbl(e))},t.moof=function(e,r,i){return t.box(t.types.moof,t.mfhd(e),t.traf(i,r))},t.moov=function(e){for(var r=e.length,i=[];r--;)i[r]=t.trak(e[r]);return t.box.apply(null,[t.types.moov,t.mvhd(e[0].timescale,e[0].duration)].concat(i).concat(t.mvex(e)))},t.mvex=function(e){for(var r=e.length,i=[];r--;)i[r]=t.trex(e[r]);return t.box.apply(null,[t.types.mvex].concat(i))},t.mvhd=function(e,r){r*=e;var i=Math.floor(r/(a+1)),n=Math.floor(r%(a+1)),s=new Uint8Array([1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,e>>24&255,e>>16&255,e>>8&255,255&e,i>>24,i>>16&255,i>>8&255,255&i,n>>24,n>>16&255,n>>8&255,255&n,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return t.box(t.types.mvhd,s)},t.sdtp=function(e){var r,i,n=e.samples||[],a=new Uint8Array(4+n.length);for(r=0;r>>8&255),a.push(255&n),a=a.concat(Array.prototype.slice.call(i));for(r=0;r>>8&255),s.push(255&n),s=s.concat(Array.prototype.slice.call(i));var o=t.box(t.types.avcC,new Uint8Array([1,a[3],a[4],a[5],255,224|e.sps.length].concat(a).concat([e.pps.length]).concat(s))),l=e.width,u=e.height,h=e.pixelRatio[0],d=e.pixelRatio[1];return t.box(t.types.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,l>>8&255,255&l,u>>8&255,255&u,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),o,t.box(t.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),t.box(t.types.pasp,new Uint8Array([h>>24,h>>16&255,h>>8&255,255&h,d>>24,d>>16&255,d>>8&255,255&d])))},t.esds=function(t){var e=t.config.length;return new Uint8Array([0,0,0,0,3,23+e,0,1,0,4,15+e,64,21,0,0,0,0,0,0,0,0,0,0,0,5].concat([e]).concat(t.config).concat([6,1,2]))},t.mp4a=function(e){var r=e.samplerate;return t.box(t.types.mp4a,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,e.channelCount,0,16,0,0,0,0,r>>8&255,255&r,0,0]),t.box(t.types.esds,t.esds(e)))},t.mp3=function(e){var r=e.samplerate;return t.box(t.types[".mp3"],new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,e.channelCount,0,16,0,0,0,0,r>>8&255,255&r,0,0]))},t.stsd=function(e){return"audio"===e.type?e.isAAC||"mp3"!==e.codec?t.box(t.types.stsd,t.STSD,t.mp4a(e)):t.box(t.types.stsd,t.STSD,t.mp3(e)):t.box(t.types.stsd,t.STSD,t.avc1(e))},t.tkhd=function(e){var r=e.id,i=e.duration*e.timescale,n=e.width,s=e.height,o=Math.floor(i/(a+1)),l=Math.floor(i%(a+1));return t.box(t.types.tkhd,new Uint8Array([1,0,0,7,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,r>>24&255,r>>16&255,r>>8&255,255&r,0,0,0,0,o>>24,o>>16&255,o>>8&255,255&o,l>>24,l>>16&255,l>>8&255,255&l,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,n>>8&255,255&n,0,0,s>>8&255,255&s,0,0]))},t.traf=function(e,r){var i=t.sdtp(e),n=e.id,s=Math.floor(r/(a+1)),o=Math.floor(r%(a+1));return t.box(t.types.traf,t.box(t.types.tfhd,new Uint8Array([0,0,0,0,n>>24,n>>16&255,n>>8&255,255&n])),t.box(t.types.tfdt,new Uint8Array([1,0,0,0,s>>24,s>>16&255,s>>8&255,255&s,o>>24,o>>16&255,o>>8&255,255&o])),t.trun(e,i.length+16+20+8+16+8+8),i)},t.trak=function(e){return e.duration=e.duration||4294967295,t.box(t.types.trak,t.tkhd(e),t.mdia(e))},t.trex=function(e){var r=e.id;return t.box(t.types.trex,new Uint8Array([0,0,0,0,r>>24,r>>16&255,r>>8&255,255&r,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]))},t.trun=function(e,r){var i,n,a,s,o,l,u=e.samples||[],h=u.length,d=12+16*h,c=new Uint8Array(d);for(r+=8+d,c.set([0,0,15,1,h>>>24&255,h>>>16&255,h>>>8&255,255&h,r>>>24&255,r>>>16&255,r>>>8&255,255&r],0),i=0;i>>24&255,a>>>16&255,a>>>8&255,255&a,s>>>24&255,s>>>16&255,s>>>8&255,255&s,o.isLeading<<2|o.dependsOn,o.isDependedOn<<6|o.hasRedundancy<<4|o.paddingValue<<1|o.isNonSync,61440&o.degradPrio,15&o.degradPrio,l>>>24&255,l>>>16&255,l>>>8&255,255&l],12+16*i);return t.box(t.types.trun,c)},t.initSegment=function(e){t.types||t.init();var r=t.moov(e),i=new Uint8Array(t.FTYP.byteLength+r.byteLength);return i.set(t.FTYP),i.set(r,t.FTYP.byteLength),i},t}();s.types=void 0,s.HDLR_TYPES=void 0,s.STTS=void 0,s.STSC=void 0,s.STCO=void 0,s.STSZ=void 0,s.VMHD=void 0,s.SMHD=void 0,s.STSD=void 0,s.FTYP=void 0,s.DINF=void 0;var o=s,l=r(0),u=r(2),h=r(1),d=r(4),c=r(8);function f(){return(f=Object.assign||function(t){for(var e=1;e0?t:r.pts}),t[0].pts);return e&&h.b.debug("PTS rollover detected"),r},e.remux=function(t,e,r,i,n,a,s,o){var l,u,c,f,g,v,p=n,m=n,T=t.pid>-1,b=e.pid>-1,E=e.samples.length,S=t.samples.length>0,L=E>1;if((!T||S)&&(!b||L)||this.ISGenerated||s){this.ISGenerated||(c=this.generateIS(t,e,n));var A=this.isVideoContiguous,R=-1;if(L&&(R=function(t){for(var e=0;e0){h.b.warn("[mp4-remuxer]: Dropped "+R+" out of "+E+" video samples due to a missing keyframe");var D=this.getVideoStartPts(e.samples);e.samples=e.samples.slice(R),e.dropped+=R,m+=(e.samples[0].pts-D)/(e.timescale||9e4)}else-1===R&&(h.b.warn("[mp4-remuxer]: No keyframe found out of "+E+" video samples"),v=!1);if(this.ISGenerated){if(S&&L){var k=this.getVideoStartPts(e.samples),_=(y(t.samples[0].pts,k)-k)/e.inputTimeScale;p+=Math.max(0,_),m+=Math.max(0,-_)}if(S){if(t.samplerate||(h.b.warn("[mp4-remuxer]: regenerate InitSegment as audio detected"),c=this.generateIS(t,e,n)),u=this.remuxAudio(t,p,this.isAudioContiguous,a,b||L||o===d.b.AUDIO?m:void 0),L){var I=u?u.endPTS-u.startPTS:0;e.inputTimeScale||(h.b.warn("[mp4-remuxer]: regenerate InitSegment as video detected"),c=this.generateIS(t,e,n)),l=this.remuxVideo(e,m,A,I)}}else L&&(l=this.remuxVideo(e,m,A,0));l&&(l.firstKeyFrame=R,l.independent=-1!==R)}}return this.ISGenerated&&(r.samples.length&&(g=this.remuxID3(r,n)),i.samples.length&&(f=this.remuxText(i,n))),{audio:u,video:l,initSegment:c,independent:v,text:f,id3:g}},e.generateIS=function(t,e,r){var n,a,s,l=t.samples,u=e.samples,h=this.typeSupported,d={},c=!Object(i.a)(this._initPTS),f="audio/mp4";if(c&&(n=a=1/0),t.config&&l.length&&(t.timescale=t.samplerate,t.isAAC||(h.mpeg?(f="audio/mpeg",t.codec=""):h.mp3&&(t.codec="mp3")),d.audio={id:"audio",container:f,codec:t.codec,initSegment:!t.isAAC&&h.mpeg?new Uint8Array(0):o.initSegment([t]),metadata:{channelCount:t.channelCount}},c&&(s=t.inputTimeScale,n=a=l[0].pts-Math.round(s*r))),e.sps&&e.pps&&u.length&&(e.timescale=e.inputTimeScale,d.video={id:"main",container:"video/mp4",codec:e.codec,initSegment:o.initSegment([e]),metadata:{width:e.width,height:e.height}},c)){s=e.inputTimeScale;var g=this.getVideoStartPts(u),v=Math.round(s*r);a=Math.min(a,y(u[0].dts,g)-v),n=Math.min(n,g-v)}if(Object.keys(d).length)return this.ISGenerated=!0,c&&(this._initPTS=n,this._initDTS=a),{tracks:d,initPTS:n,timescale:s}},e.remuxVideo=function(t,e,r,i){var n,a,s,d=t.inputTimeScale,v=t.samples,m=[],b=v.length,E=this._initPTS,S=this.nextAvcDts,L=8,A=Number.POSITIVE_INFINITY,R=Number.NEGATIVE_INFINITY,D=0,k=!1;r&&null!==S||(S=e*d-(v[0].pts-y(v[0].dts,v[0].pts)));for(var _=0;_I.pts){D=Math.max(Math.min(D,I.pts-I.dts),-18e3)}I.dts0?_-1:_].dts&&(k=!0)}k&&v.sort((function(t,e){var r=t.dts-e.dts,i=t.pts-e.pts;return r||i})),a=v[0].dts,s=v[v.length-1].dts;var C=Math.round((s-a)/(b-1));if(D<0){if(D<-2*C){h.b.warn("PTS < DTS detected in video samples, offsetting DTS from PTS by "+Object(c.b)(-C,!0)+" ms");for(var w=D,O=0;OC;if(M||P<-1){M?h.b.warn("AVC: "+Object(c.b)(P,!0)+" ms ("+P+"dts) hole between fragments detected, filling it"):h.b.warn("AVC: "+Object(c.b)(-P,!0)+" ms ("+P+"dts) overlapping between fragments detected"),a=S;var F=v[0].pts-P;v[0].dts=a,v[0].pts=F,h.b.log("Video: First PTS/DTS adjusted: "+Object(c.b)(F,!0)+"/"+Object(c.b)(a,!0)+", delta: "+Object(c.b)(P,!0)+" ms")}}p&&(a=Math.max(0,a));for(var N=0,U=0,B=0;B0?X-1:X].dts;if(it.stretchShortVideoTrack&&null!==this.nextAudioPts){var at=Math.floor(it.maxBufferHole*d),st=(i?A+i*d:this.nextAudioPts)-z.pts;st>at?((n=st-nt)<0&&(n=nt),h.b.log("[mp4-remuxer]: It is approximately "+st/90+" ms to the next segment; using duration "+n/90+" ms for the last video frame.")):n=nt}else n=nt}var ot=Math.round(z.pts-z.dts);m.push(new T(z.key,n,$,ot))}if(m.length&&g&&g<70){var lt=m[0].flags;lt.dependsOn=2,lt.isNonSync=0}this.nextAvcDts=S=s+n,this.isVideoContiguous=!0;var ut={data1:o.moof(t.sequenceNumber++,a,f({},t,{samples:m})),data2:W,startPTS:A/d,endPTS:(R+n)/d,startDTS:a/d,endDTS:S/d,type:"video",hasAudio:!1,hasVideo:!0,nb:m.length,dropped:t.dropped};return t.samples=[],t.dropped=0,ut},e.remuxAudio=function(t,e,r,i,a){var s=t.inputTimeScale,d=s/(t.samplerate?t.samplerate:s),c=t.isAAC?1024:1152,g=c*d,v=this._initPTS,p=!t.isAAC&&this.typeSupported.mpeg,m=[],b=t.samples,E=p?0:8,S=this.nextAudioPts||-1,L=e*s;if(this.isAudioContiguous=r=r||b.length&&S>0&&(i&&Math.abs(L-S)<9e3||Math.abs(y(b[0].pts-v,L)-S)<20*g),b.forEach((function(t){t.pts=y(t.pts-v,L)})),!r||S<0){if(!(b=b.filter((function(t){return t.pts>=0}))).length)return;S=0===a?0:i?Math.max(0,L):b[0].pts}if(t.isAAC)for(var A=void 0!==a,R=this.config.maxAudioFramesDrift,D=0,k=S;D=R*g&&w<1e4&&A){var O=Math.round(C/g);(k=I-O*g)<0&&(O--,k+=g),0===D&&(this.nextAudioPts=S=k),h.b.warn("[mp4-remuxer]: Injecting "+O+" audio frame @ "+(k/s).toFixed(3)+"s due to "+Math.round(1e3*C/s)+" ms gap.");for(var x=0;x0))return;B+=E;try{F=new Uint8Array(B)}catch(t){return void this.observer.emit(l.a.ERROR,l.a.ERROR,{type:u.b.MUX_ERROR,details:u.a.REMUX_ALLOC_ERROR,fatal:!1,bytes:B,reason:"fail allocating audio mdat "+B})}p||(new DataView(F.buffer).setUint32(0,B),F.set(o.types.mdat,4))}F.set(V,E);var Y=V.byteLength;E+=Y,m.push(new T(!0,c,Y,0)),U=W}var q=m.length;if(q){var X=m[m.length-1];this.nextAudioPts=S=U+d*X.duration;var z=p?new Uint8Array(0):o.moof(t.sequenceNumber++,N/d,f({},t,{samples:m}));t.samples=[];var Q=N/s,$=S/s,J={data1:z,data2:F,startPTS:Q,endPTS:$,startDTS:Q,endDTS:$,type:"audio",hasAudio:!0,hasVideo:!1,nb:q};return this.isAudioContiguous=!0,J}},e.remuxEmptyAudio=function(t,e,r,i){var a=t.inputTimeScale,s=a/(t.samplerate?t.samplerate:a),o=this.nextAudioPts,l=(null!==o?o:i.startDTS*a)+this._initDTS,u=i.endDTS*a+this._initDTS,d=1024*s,c=Math.ceil((u-l)/d),f=n.getSilentFrame(t.manifestCodec||t.codec,t.channelCount);if(h.b.warn("[mp4-remuxer]: remux empty Audio"),f){for(var g=[],v=0;v4294967296;)t+=r;return t}var T=function(t,e,r,i){this.size=void 0,this.duration=void 0,this.cts=void 0,this.flags=void 0,this.duration=e,this.size=r,this.cts=i,this.flags=new b(t)},b=function(t){this.isLeading=0,this.isDependedOn=0,this.hasRedundancy=0,this.degradPrio=0,this.dependsOn=1,this.isNonSync=1,this.dependsOn=t?2:1,this.isNonSync=t?0:1}},function(t,e,r){"use strict";r.d(e,"a",(function(){return a}));var i=r(11);function n(t,e){for(var r=0;r0}),!1)}t.exports=function(t,e){e=e||{};var n={main:r.m},o=e.all?{main:Object.keys(n.main)}:function(t,e){for(var r={main:[e]},i={main:[]},n={main:{}};s(r);)for(var o=Object.keys(r),l=0;lt.endSN||e>0||0===e&&r>0,this.updated||this.advanced?this.misses=Math.floor(.6*t.misses):this.misses=t.misses+1,this.availabilityDelay=t.availabilityDelay},e=t,(r=[{key:"hasProgramDateTime",get:function(){return!!this.fragments.length&&Object(n.a)(this.fragments[this.fragments.length-1].programDateTime)}},{key:"levelTargetDuration",get:function(){return this.averagetargetduration||this.targetduration||10}},{key:"drift",get:function(){var t=this.driftEndTime-this.driftStartTime;return t>0?1e3*(this.driftEnd-this.driftStart)/t:1}},{key:"edge",get:function(){return this.partEnd||this.fragmentEnd}},{key:"partEnd",get:function(){var t;return null!==(t=this.partList)&&void 0!==t&&t.length?this.partList[this.partList.length-1].end:this.fragmentEnd}},{key:"fragmentEnd",get:function(){var t;return null!==(t=this.fragments)&&void 0!==t&&t.length?this.fragments[this.fragments.length-1].end:0}},{key:"age",get:function(){return this.advancedDateTime?Math.max(Date.now()-this.advancedDateTime,0)/1e3:0}},{key:"lastPartIndex",get:function(){var t;return null!==(t=this.partList)&&void 0!==t&&t.length?this.partList[this.partList.length-1].index:-1}},{key:"lastPartSn",get:function(){var t;return null!==(t=this.partList)&&void 0!==t&&t.length?this.partList[this.partList.length-1].fragment.sn:this.endSN}}])&&h(e.prototype,r),i&&h(e,i),t}(),c=r(17),f=/^(\d+)x(\d+)$/,g=/\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g,v=function(){function t(e){for(var r in"string"==typeof e&&(e=t.parseAttrList(e)),e)e.hasOwnProperty(r)&&(this[r]=e[r])}var e=t.prototype;return e.decimalInteger=function(t){var e=parseInt(this[t],10);return e>Number.MAX_SAFE_INTEGER?1/0:e},e.hexadecimalInteger=function(t){if(this[t]){var e=(this[t]||"0x").slice(2);e=(1&e.length?"0":"")+e;for(var r=new Uint8Array(e.length/2),i=0;iNumber.MAX_SAFE_INTEGER?1/0:e},e.decimalFloatingPoint=function(t){return parseFloat(this[t])},e.optionalFloat=function(t,e){var r=this[t];return r?parseFloat(r):e},e.enumeratedString=function(t){return this[t]},e.bool=function(t){return"YES"===this[t]},e.decimalResolution=function(t){var e=f.exec(this[t]);if(null!==e)return{width:parseInt(e[1],10),height:parseInt(e[2],10)}},t.parseAttrList=function(t){var e,r={};for(g.lastIndex=0;null!==(e=g.exec(t));){var i=e[2];0===i.indexOf('"')&&i.lastIndexOf('"')===i.length-1&&(i=i.slice(1,-1)),r[e[1]]=i}return r},t}(),p={audio:{a3ds:!0,"ac-3":!0,"ac-4":!0,alac:!0,alaw:!0,dra1:!0,"dts+":!0,"dts-":!0,dtsc:!0,dtse:!0,dtsh:!0,"ec-3":!0,enca:!0,g719:!0,g726:!0,m4ae:!0,mha1:!0,mha2:!0,mhm1:!0,mhm2:!0,mlpa:!0,mp4a:!0,"raw ":!0,Opus:!0,samr:!0,sawb:!0,sawp:!0,sevc:!0,sqcp:!0,ssmv:!0,twos:!0,ulaw:!0},video:{avc1:!0,avc2:!0,avc3:!0,avc4:!0,avcp:!0,av01:!0,drac:!0,dvav:!0,dvhe:!0,encv:!0,hev1:!0,hvc1:!0,mjp2:!0,mp4v:!0,mvc1:!0,mvc2:!0,mvc3:!0,mvc4:!0,resv:!0,rv60:!0,s263:!0,svc1:!0,svc2:!0,"vc-1":!0,vp08:!0,vp09:!0},text:{stpp:!0,wvtt:!0}};function m(t,e){return MediaSource.isTypeSupported((e||"video")+'/mp4;codecs="'+t+'"')}var y=/#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-SESSION-DATA:([^\r\n]*)[\r\n]+/g,T=/#EXT-X-MEDIA:(.*)/g,b=new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source,/(?!#) *(\S[\S ]*)/.source,/#EXT-X-BYTERANGE:*(.+)/.source,/#EXT-X-PROGRAM-DATE-TIME:(.+)/.source,/#.*/.source].join("|"),"g"),E=new RegExp([/#(EXTM3U)/.source,/#EXT-X-(PLAYLIST-TYPE):(.+)/.source,/#EXT-X-(MEDIA-SEQUENCE): *(\d+)/.source,/#EXT-X-(SKIP):(.+)/.source,/#EXT-X-(TARGETDURATION): *(\d+)/.source,/#EXT-X-(KEY):(.+)/.source,/#EXT-X-(START):(.+)/.source,/#EXT-X-(ENDLIST)/.source,/#EXT-X-(DISCONTINUITY-SEQ)UENCE: *(\d+)/.source,/#EXT-X-(DIS)CONTINUITY/.source,/#EXT-X-(VERSION):(\d+)/.source,/#EXT-X-(MAP):(.+)/.source,/#EXT-X-(SERVER-CONTROL):(.+)/.source,/#EXT-X-(PART-INF):(.+)/.source,/#EXT-X-(GAP)/.source,/#EXT-X-(BITRATE):\s*(\d+)/.source,/#EXT-X-(PART):(.+)/.source,/#EXT-X-(PRELOAD-HINT):(.+)/.source,/#EXT-X-(RENDITION-REPORT):(.+)/.source,/(#)([^:]*):(.*)/.source,/(#)(.*)(?:.*)\r?\n?/.source].join("|")),S=/\.(mp4|m4s|m4v|m4a)$/i;var L=function(){function t(){}return t.findGroup=function(t,e){for(var r=0;r2){var r=e.shift()+".";return r+=parseInt(e.shift()).toString(16),r+=("000"+parseInt(e.shift()).toString(16)).substr(-4)}return t},t.resolve=function(t,e){return i.buildAbsoluteURL(e,t,{alwaysNormalize:!0})},t.parseMasterPlaylist=function(e,r){var i,n=[],a={},s=!1;for(y.lastIndex=0;null!=(i=y.exec(e));)if(i[1]){var o=new v(i[1]),l={attrs:o,bitrate:o.decimalInteger("AVERAGE-BANDWIDTH")||o.decimalInteger("BANDWIDTH"),name:o.NAME,url:t.resolve(i[2],r)},u=o.decimalResolution("RESOLUTION");u&&(l.width=u.width,l.height=u.height),A((o.CODECS||"").split(/[ ,]+/).filter((function(t){return t})),l),l.videoCodec&&-1!==l.videoCodec.indexOf("avc1")&&(l.videoCodec=t.convertAVC1ToAVCOTI(l.videoCodec)),n.push(l)}else if(i[3]){var h=new v(i[3]);h["DATA-ID"]&&(s=!0,a[h["DATA-ID"]]=h)}return{levels:n,sessionData:s?a:null}},t.parseMasterPlaylistMedia=function(e,r,i,n){var a;void 0===n&&(n=[]);var s=[],o=0;for(T.lastIndex=0;null!==(a=T.exec(e));){var l=new v(a[1]);if(l.TYPE===i){var u={attrs:l,bitrate:0,id:o++,groupId:l["GROUP-ID"],instreamId:l["INSTREAM-ID"],name:l.NAME||l.LANGUAGE||"",type:i,default:l.bool("DEFAULT"),autoselect:l.bool("AUTOSELECT"),forced:l.bool("FORCED"),lang:l.LANGUAGE,url:l.URI?t.resolve(l.URI,r):""};if(n.length){var h=t.findGroup(n,u.groupId)||n[0];R(u,h,"audioCodec"),R(u,h,"textCodec")}s.push(u)}}return s},t.parseLevelPlaylist=function(t,e,r,a,s){var l,h,f,g=new d(e),p=g.fragments,m=null,y=0,T=0,L=0,A=0,R=null,k=new u.b(a,e),_=-1,I=!1;for(b.lastIndex=0,g.m3u8=t;null!==(l=b.exec(t));){I&&(I=!1,(k=new u.b(a,e)).start=L,k.sn=y,k.cc=A,k.level=r,m&&(k.initSegment=m,k.rawProgramDateTime=m.rawProgramDateTime));var C=l[1];if(C){k.duration=parseFloat(C);var w=(" "+l[2]).slice(1);k.title=w||null,k.tagList.push(w?["INF",C,w]:["INF",C])}else if(l[3])Object(n.a)(k.duration)&&(k.start=L,f&&(k.levelkey=f),k.sn=y,k.level=r,k.cc=A,k.urlId=s,p.push(k),k.relurl=(" "+l[3]).slice(1),D(k,R),R=k,L+=k.duration,y++,T=0,I=!0);else if(l[4]){var O=(" "+l[4]).slice(1);R?k.setByteRange(O,R):k.setByteRange(O)}else if(l[5])k.rawProgramDateTime=(" "+l[5]).slice(1),k.tagList.push(["PROGRAM-DATE-TIME",k.rawProgramDateTime]),-1===_&&(_=p.length);else{if(!(l=l[0].match(E))){o.b.warn("No matches on slow regex match for level playlist!");continue}for(h=1;h-1){o.b.warn("Keyformat "+q+" is not supported from the manifest");continue}if("identity"!==q)continue;j&&(f=c.a.fromURL(e,H),H&&["AES-128","SAMPLE-AES","SAMPLE-AES-CENC"].indexOf(j)>=0&&(f.method=j,f.keyFormat=q,Y&&(f.keyID=Y),W&&(f.keyFormatVersions=W),f.iv=V));break;case"START":var X=new v(P).decimalFloatingPoint("TIME-OFFSET");Object(n.a)(X)&&(g.startTimeOffset=X);break;case"MAP":var z=new v(P);k.relurl=z.URI,z.BYTERANGE&&k.setByteRange(z.BYTERANGE),k.level=r,k.sn="initSegment",f&&(k.levelkey=f),k.initSegment=null,m=k,I=!0;break;case"SERVER-CONTROL":var Q=new v(P);g.canBlockReload=Q.bool("CAN-BLOCK-RELOAD"),g.canSkipUntil=Q.optionalFloat("CAN-SKIP-UNTIL",0),g.canSkipDateRanges=g.canSkipUntil>0&&Q.bool("CAN-SKIP-DATERANGES"),g.partHoldBack=Q.optionalFloat("PART-HOLD-BACK",0),g.holdBack=Q.optionalFloat("HOLD-BACK",0);break;case"PART-INF":var $=new v(P);g.partTarget=$.decimalFloatingPoint("PART-TARGET");break;case"PART":var J=g.partList;J||(J=g.partList=[]);var Z=T>0?J[J.length-1]:void 0,tt=T++,et=new u.c(new v(P),k,e,tt,Z);J.push(et),k.duration+=et.duration;break;case"PRELOAD-HINT":var rt=new v(P);g.preloadHint=rt;break;case"RENDITION-REPORT":var it=new v(P);g.renditionReports=g.renditionReports||[],g.renditionReports.push(it);break;default:o.b.warn("line parsed but not handled: "+l)}}}R&&!R.relurl?(p.pop(),L-=R.duration,g.partList&&(g.fragmentHint=R)):g.partList&&(D(k,R),k.cc=A,g.fragmentHint=k);var nt=p.length,at=p[0],st=p[nt-1];if((L+=g.skippedSegments*g.targetduration)>0&&nt&&st){g.averagetargetduration=L/nt;var ot=st.sn;g.endSN="initSegment"!==ot?ot:0,at&&(g.startCC=at.cc,at.initSegment||g.fragments.every((function(t){return t.relurl&&(e=t.relurl,S.test(null!=(r=null===(n=i.parseURL(e))||void 0===n?void 0:n.path)?r:""));var e,r,n}))&&(o.b.warn("MP4 fragments found but no init segment (probably no MAP, incomplete M3U8), trying to fetch SIDX"),(k=new u.b(a,e)).relurl=st.relurl,k.level=r,k.sn="initSegment",at.initSegment=k,g.needSidxRanges=!0))}else g.endSN=0,g.startCC=0;return g.fragmentHint&&(L+=g.fragmentHint.duration),g.totalduration=L,g.endCC=A,_>0&&function(t,e){for(var r=t[e],i=e;i--;){var n=t[i];if(!n)return;n.programDateTime=r.programDateTime-1e3*n.duration,r=n}}(p,_),g},t}();function A(t,e){["video","audio","text"].forEach((function(r){var i=t.filter((function(t){return function(t,e){var r=p[e];return!!r&&!0===r[t.slice(0,4)]}(t,r)}));if(i.length){var n=i.filter((function(t){return 0===t.lastIndexOf("avc1",0)||0===t.lastIndexOf("mp4a",0)}));e[r+"Codec"]=n.length>0?n[0]:i[0],t=t.filter((function(t){return-1===i.indexOf(t)}))}})),e.unknownCodecs=t}function R(t,e,r){var i=e[r];i&&(t[r]=i)}function D(t,e){t.rawProgramDateTime?t.programDateTime=Date.parse(t.rawProgramDateTime):null!=e&&e.programDateTime&&(t.programDateTime=e.endProgramDateTime),Object(n.a)(t.programDateTime)||(t.programDateTime=null,t.rawProgramDateTime=null)}var k=r(4);function _(t,e){var r=t.url;return void 0!==r&&0!==r.indexOf("data:")||(r=e.url),r}var I=function(){function t(t){this.hls=void 0,this.loaders=Object.create(null),this.hls=t,this.registerListeners()}var e=t.prototype;return e.registerListeners=function(){var t=this.hls;t.on(a.a.MANIFEST_LOADING,this.onManifestLoading,this),t.on(a.a.LEVEL_LOADING,this.onLevelLoading,this),t.on(a.a.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),t.on(a.a.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this)},e.unregisterListeners=function(){var t=this.hls;t.off(a.a.MANIFEST_LOADING,this.onManifestLoading,this),t.off(a.a.LEVEL_LOADING,this.onLevelLoading,this),t.off(a.a.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),t.off(a.a.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this)},e.createInternalLoader=function(t){var e=this.hls.config,r=e.pLoader,i=e.loader,n=new(r||i)(e);return t.loader=n,this.loaders[t.type]=n,n},e.getInternalLoader=function(t){return this.loaders[t.type]},e.resetInternalLoader=function(t){this.loaders[t]&&delete this.loaders[t]},e.destroyInternalLoaders=function(){for(var t in this.loaders){var e=this.loaders[t];e&&e.destroy(),this.resetInternalLoader(t)}},e.destroy=function(){this.unregisterListeners(),this.destroyInternalLoaders()},e.onManifestLoading=function(t,e){var r=e.url;this.load({id:null,groupId:null,level:0,responseType:"text",type:k.a.MANIFEST,url:r,deliveryDirectives:null})},e.onLevelLoading=function(t,e){var r=e.id,i=e.level,n=e.url,a=e.deliveryDirectives;this.load({id:r,groupId:null,level:i,responseType:"text",type:k.a.LEVEL,url:n,deliveryDirectives:a})},e.onAudioTrackLoading=function(t,e){var r=e.id,i=e.groupId,n=e.url,a=e.deliveryDirectives;this.load({id:r,groupId:i,level:null,responseType:"text",type:k.a.AUDIO_TRACK,url:n,deliveryDirectives:a})},e.onSubtitleTrackLoading=function(t,e){var r=e.id,i=e.groupId,n=e.url,a=e.deliveryDirectives;this.load({id:r,groupId:i,level:null,responseType:"text",type:k.a.SUBTITLE_TRACK,url:n,deliveryDirectives:a})},e.load=function(t){var e,r,i,n,a,s,l=this.hls.config,u=this.getInternalLoader(t);if(u){var h=u.context;if(h&&h.url===t.url)return void o.b.trace("[playlist-loader]: playlist request ongoing");o.b.log("[playlist-loader]: aborting previous loader for type: "+t.type),u.abort()}switch(t.type){case k.a.MANIFEST:r=l.manifestLoadingMaxRetry,i=l.manifestLoadingTimeOut,n=l.manifestLoadingRetryDelay,a=l.manifestLoadingMaxRetryTimeout;break;case k.a.LEVEL:case k.a.AUDIO_TRACK:case k.a.SUBTITLE_TRACK:r=0,i=l.levelLoadingTimeOut;break;default:r=l.levelLoadingMaxRetry,i=l.levelLoadingTimeOut,n=l.levelLoadingRetryDelay,a=l.levelLoadingMaxRetryTimeout}if((u=this.createInternalLoader(t),null!==(e=t.deliveryDirectives)&&void 0!==e&&e.part)&&(t.type===k.a.LEVEL&&null!==t.level?s=this.hls.levels[t.level].details:t.type===k.a.AUDIO_TRACK&&null!==t.id?s=this.hls.audioTracks[t.id].details:t.type===k.a.SUBTITLE_TRACK&&null!==t.id&&(s=this.hls.subtitleTracks[t.id].details),s)){var d=s.partTarget,c=s.targetduration;d&&c&&(i=Math.min(1e3*Math.max(3*d,.8*c),i))}var f={timeout:i,maxRetry:r,retryDelay:n,maxRetryDelay:a,highWaterMark:0},g={onSuccess:this.loadsuccess.bind(this),onError:this.loaderror.bind(this),onTimeout:this.loadtimeout.bind(this)};u.load(t,f,g)},e.loadsuccess=function(t,e,r,i){if(void 0===i&&(i=null),r.isSidxRequest)return this.handleSidxRequest(t,r),void this.handlePlaylistLoaded(t,e,r,i);this.resetInternalLoader(r.type);var n=t.data;0===n.indexOf("#EXTM3U")?(e.parsing.start=performance.now(),n.indexOf("#EXTINF:")>0||n.indexOf("#EXT-X-TARGETDURATION:")>0?this.handleTrackOrLevelPlaylist(t,e,r,i):this.handleMasterPlaylist(t,e,r,i)):this.handleManifestParsingError(t,r,"no EXTM3U delimiter",i)},e.loaderror=function(t,e,r){void 0===r&&(r=null),this.handleNetworkError(e,r,!1,t)},e.loadtimeout=function(t,e,r){void 0===r&&(r=null),this.handleNetworkError(e,r,!0)},e.handleMasterPlaylist=function(t,e,r,i){var n=this.hls,s=t.data,l=_(t,r),u=L.parseMasterPlaylist(s,l),h=u.levels,d=u.sessionData;if(h.length){var c=h.map((function(t){return{id:t.attrs.AUDIO,audioCodec:t.audioCodec}})),f=h.map((function(t){return{id:t.attrs.SUBTITLES,textCodec:t.textCodec}})),g=L.parseMasterPlaylistMedia(s,l,"AUDIO",c),p=L.parseMasterPlaylistMedia(s,l,"SUBTITLES",f),m=L.parseMasterPlaylistMedia(s,l,"CLOSED-CAPTIONS");if(g.length)g.some((function(t){return!t.url}))||!h[0].audioCodec||h[0].attrs.AUDIO||(o.b.log("[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one"),g.unshift({type:"main",name:"main",default:!1,autoselect:!1,forced:!1,id:-1,attrs:new v({}),bitrate:0,url:""}));n.trigger(a.a.MANIFEST_LOADED,{levels:h,audioTracks:g,subtitles:p,captions:m,url:l,stats:e,networkDetails:i,sessionData:d})}else this.handleManifestParsingError(t,r,"no level found in manifest",i)},e.handleTrackOrLevelPlaylist=function(t,e,r,i){var o=this.hls,l=r.id,u=r.level,h=r.type,d=_(t,r),c=Object(n.a)(l)?l:0,f=Object(n.a)(u)?u:c,g=function(t){switch(t.type){case k.a.AUDIO_TRACK:return k.b.AUDIO;case k.a.SUBTITLE_TRACK:return k.b.SUBTITLE;default:return k.b.MAIN}}(r),p=L.parseLevelPlaylist(t.data,d,f,g,c);if(p.fragments.length){if(h===k.a.MANIFEST){var m={attrs:new v({}),bitrate:0,details:p,name:"",url:d};o.trigger(a.a.MANIFEST_LOADED,{levels:[m],audioTracks:[],url:d,stats:e,networkDetails:i,sessionData:null})}if(e.parsing.end=performance.now(),p.needSidxRanges){var y,T=null===(y=p.fragments[0].initSegment)||void 0===y?void 0:y.url;this.load({url:T,isSidxRequest:!0,type:h,level:u,levelDetails:p,id:l,groupId:null,rangeStart:0,rangeEnd:2048,responseType:"arraybuffer",deliveryDirectives:null})}else r.levelDetails=p,this.handlePlaylistLoaded(t,e,r,i)}else o.trigger(a.a.ERROR,{type:s.b.NETWORK_ERROR,details:s.a.LEVEL_EMPTY_ERROR,fatal:!1,url:d,reason:"no fragments found in level",level:"number"==typeof r.level?r.level:void 0})},e.handleSidxRequest=function(t,e){var r=Object(l.g)(new Uint8Array(t.data));if(r){var i=r.references,n=e.levelDetails;i.forEach((function(t,e){var i=t.info,a=n.fragments[e];0===a.byteRange.length&&a.setByteRange(String(1+i.end-i.start)+"@"+String(i.start)),a.initSegment&&a.initSegment.setByteRange(String(r.moovEndOffset)+"@0")}))}},e.handleManifestParsingError=function(t,e,r,i){this.hls.trigger(a.a.ERROR,{type:s.b.NETWORK_ERROR,details:s.a.MANIFEST_PARSING_ERROR,fatal:e.type===k.a.MANIFEST,url:t.url,reason:r,response:t,context:e,networkDetails:i})},e.handleNetworkError=function(t,e,r,i){void 0===r&&(r=!1),o.b.warn("[playlist-loader]: A network "+(r?"timeout":"error")+" occurred while loading "+t.type+" level: "+t.level+" id: "+t.id+' group-id: "'+t.groupId+'"');var n=s.a.UNKNOWN,l=!1,u=this.getInternalLoader(t);switch(t.type){case k.a.MANIFEST:n=r?s.a.MANIFEST_LOAD_TIMEOUT:s.a.MANIFEST_LOAD_ERROR,l=!0;break;case k.a.LEVEL:n=r?s.a.LEVEL_LOAD_TIMEOUT:s.a.LEVEL_LOAD_ERROR,l=!1;break;case k.a.AUDIO_TRACK:n=r?s.a.AUDIO_TRACK_LOAD_TIMEOUT:s.a.AUDIO_TRACK_LOAD_ERROR,l=!1;break;case k.a.SUBTITLE_TRACK:n=r?s.a.SUBTITLE_TRACK_LOAD_TIMEOUT:s.a.SUBTITLE_LOAD_ERROR,l=!1}u&&this.resetInternalLoader(t.type);var h={type:s.b.NETWORK_ERROR,details:n,fatal:l,url:t.url,loader:u,context:t,networkDetails:e};i&&(h.response=i),this.hls.trigger(a.a.ERROR,h)},e.handlePlaylistLoaded=function(t,e,r,i){var n=r.type,s=r.level,o=r.id,l=r.groupId,u=r.loader,h=r.levelDetails,d=r.deliveryDirectives;if(null!=h&&h.targetduration){if(u)switch(h.live&&(u.getCacheAge&&(h.ageHeader=u.getCacheAge()||0),u.getCacheAge&&!isNaN(h.ageHeader)||(h.ageHeader=0)),n){case k.a.MANIFEST:case k.a.LEVEL:this.hls.trigger(a.a.LEVEL_LOADED,{details:h,level:s||0,id:o||0,stats:e,networkDetails:i,deliveryDirectives:d});break;case k.a.AUDIO_TRACK:this.hls.trigger(a.a.AUDIO_TRACK_LOADED,{details:h,id:o||0,groupId:l||"",stats:e,networkDetails:i,deliveryDirectives:d});break;case k.a.SUBTITLE_TRACK:this.hls.trigger(a.a.SUBTITLE_TRACK_LOADED,{details:h,id:o||0,groupId:l||"",stats:e,networkDetails:i,deliveryDirectives:d})}}else this.handleManifestParsingError(t,r,"invalid target duration",i)},t}(),C=function(){function t(t){this.hls=void 0,this.loaders={},this.decryptkey=null,this.decrypturl=null,this.hls=t,this._registerListeners()}var e=t.prototype;return e._registerListeners=function(){this.hls.on(a.a.KEY_LOADING,this.onKeyLoading,this)},e._unregisterListeners=function(){this.hls.off(a.a.KEY_LOADING,this.onKeyLoading)},e.destroy=function(){for(var t in this._unregisterListeners(),this.loaders){var e=this.loaders[t];e&&e.destroy()}this.loaders={}},e.onKeyLoading=function(t,e){var r=e.frag,i=r.type,n=this.loaders[i];if(r.decryptdata){var s=r.decryptdata.uri;if(s!==this.decrypturl||null===this.decryptkey){var l=this.hls.config;if(n&&(o.b.warn("abort previous key loader for type:"+i),n.abort()),!s)return void o.b.warn("key uri is falsy");var u=l.loader,h=r.loader=this.loaders[i]=new u(l);this.decrypturl=s,this.decryptkey=null;var d={url:s,frag:r,responseType:"arraybuffer"},c={timeout:l.fragLoadingTimeOut,maxRetry:0,retryDelay:l.fragLoadingRetryDelay,maxRetryDelay:l.fragLoadingMaxRetryTimeout,highWaterMark:0},f={onSuccess:this.loadsuccess.bind(this),onError:this.loaderror.bind(this),onTimeout:this.loadtimeout.bind(this)};h.load(d,c,f)}else this.decryptkey&&(r.decryptdata.key=this.decryptkey,this.hls.trigger(a.a.KEY_LOADED,{frag:r}))}else o.b.warn("Missing decryption data on fragment in onKeyLoading")},e.loadsuccess=function(t,e,r){var i=r.frag;i.decryptdata?(this.decryptkey=i.decryptdata.key=new Uint8Array(t.data),i.loader=null,delete this.loaders[i.type],this.hls.trigger(a.a.KEY_LOADED,{frag:i})):o.b.error("after key load, decryptdata unset")},e.loaderror=function(t,e){var r=e.frag,i=r.loader;i&&i.abort(),delete this.loaders[r.type],this.hls.trigger(a.a.ERROR,{type:s.b.NETWORK_ERROR,details:s.a.KEY_LOAD_ERROR,fatal:!1,frag:r,response:t})},e.loadtimeout=function(t,e){var r=e.frag,i=r.loader;i&&i.abort(),delete this.loaders[r.type],this.hls.trigger(a.a.ERROR,{type:s.b.NETWORK_ERROR,details:s.a.KEY_LOAD_TIMEOUT,fatal:!1,frag:r})},t}();function w(t,e){var r;try{r=new Event("addtrack")}catch(t){(r=document.createEvent("Event")).initEvent("addtrack",!1,!1)}r.track=t,e.dispatchEvent(r)}function O(t,e){var r=t.mode;if("disabled"===r&&(t.mode="hidden"),t.cues&&!t.cues.getCueById(e.id))try{if(t.addCue(e),!t.cues.getCueById(e.id))throw new Error("addCue is failed for: "+e)}catch(r){o.b.debug("[texttrack-utils]: "+r);var i=new self.TextTrackCue(e.startTime,e.endTime,e.text);i.id=e.id,t.addCue(i)}"disabled"===r&&(t.mode=r)}function x(t){var e=t.mode;if("disabled"===e&&(t.mode="hidden"),t.cues)for(var r=t.cues.length;r--;)t.removeCue(t.cues[r]);"disabled"===e&&(t.mode=e)}function P(t,e,r){var i=t.mode;if("disabled"===i&&(t.mode="hidden"),t.cues&&t.cues.length>0)for(var n=function(t,e,r){var i=[],n=function(t,e){if(et[r].endTime)return-1;var i=0,n=r;for(;i<=n;){var a=Math.floor((n+i)/2);if(et[a].startTime&&i-1)for(var a=n,s=t.length;a=e&&o.endTime<=r)i.push(o);else if(o.startTime>r)return i}return i}(t.cues,e,r),a=0;a.05&&this.forwardBufferLength>1){var u=Math.min(2,Math.max(1,a)),h=Math.round(2/(1+Math.exp(-.75*o-this.edgeStalled))*20)/20;t.playbackRate=Math.min(u,Math.max(1,h))}else 1!==t.playbackRate&&0!==t.playbackRate&&(t.playbackRate=1)}}}}},n.estimateLiveEdge=function(){var t=this.levelDetails;return null===t?null:t.edge+t.age},n.computeLatency=function(){var t=this.estimateLiveEdge();return null===t?null:t-this.currentTime},e=t,(r=[{key:"latency",get:function(){return this._latency||0}},{key:"maxLatency",get:function(){var t=this.config,e=this.levelDetails;return void 0!==t.liveMaxLatencyDuration?t.liveMaxLatencyDuration:e?t.liveMaxLatencyDurationCount*e.targetduration:0}},{key:"targetLatency",get:function(){var t=this.levelDetails;if(null===t)return null;var e=t.holdBack,r=t.partHoldBack,i=t.targetduration,n=this.config,a=n.liveSyncDuration,s=n.liveSyncDurationCount,o=n.lowLatencyMode,l=this.hls.userConfig,u=o&&r||e;(l.liveSyncDuration||l.liveSyncDurationCount||0===u)&&(u=void 0!==a?a:s*i);var h=i;return u+Math.min(1*this.stallCount,h)}},{key:"liveSyncPosition",get:function(){var t=this.estimateLiveEdge(),e=this.targetLatency,r=this.levelDetails;if(null===t||null===e||null===r)return null;var i=r.edge,n=t-e-this.edgeStalled,a=i-r.totalduration,s=i-(this.config.lowLatencyMode&&r.partTarget||r.targetduration);return Math.min(Math.max(a,n),s)}},{key:"drift",get:function(){var t=this.levelDetails;return null===t?1:t.drift}},{key:"edgeStalled",get:function(){var t=this.levelDetails;if(null===t)return 0;var e=3*(this.config.lowLatencyMode&&t.partTarget||t.targetduration);return Math.max(t.age-e,0)}},{key:"forwardBufferLength",get:function(){var t=this.media,e=this.levelDetails;if(!t||!e)return 0;var r=t.buffered.length;return r?t.buffered.end(r-1):e.edge-this.currentTime}}])&&N(e.prototype,r),i&&N(e,i),t}();function G(t,e){for(var r=0;rt.sn?(a=r-t.start,i=t):(a=t.start-r,i=e),i.duration!==a&&(i.duration=a)}else if(e.sn>t.sn){t.cc===e.cc&&t.minEndPTS?e.start=t.start+(t.minEndPTS-t.start):e.start=t.start+t.duration}else e.start=Math.max(t.start-e.duration,0)}function Y(t,e,r,i,a,s){i-r<=0&&(o.b.warn("Fragment should have a positive duration",e),i=r+e.duration,s=a+e.duration);var l=r,u=i,h=e.startPTS,d=e.endPTS;if(Object(n.a)(h)){var c=Math.abs(h-r);Object(n.a)(e.deltaPTS)?e.deltaPTS=Math.max(c,e.deltaPTS):e.deltaPTS=c,l=Math.max(r,h),r=Math.min(r,h),a=Math.min(a,e.startDTS),u=Math.min(i,d),i=Math.max(i,d),s=Math.max(s,e.endDTS)}e.duration=i-r;var f=r-e.start;e.appendedPTS=i,e.start=e.startPTS=r,e.maxStartPTS=l,e.startDTS=a,e.endPTS=i,e.minEndPTS=u,e.endDTS=s;var g,v=e.sn;if(!t||vt.endSN)return 0;var p=v-t.startSN,m=t.fragments;for(m[p]=e,g=p;g>0;g--)W(m[g],m[g-1]);for(g=p;g=0;a--){var s=i[a].initSegment;if(s){r=s;break}}t.fragmentHint&&delete t.fragmentHint.endPTS;var l,u=0;(function(t,e,r){for(var i=e.skippedSegments,n=Math.max(t.startSN,e.startSN)-e.startSN,a=(t.fragmentHint?1:0)+(i?e.endSN:Math.min(t.endSN,e.endSN))-e.startSN,s=e.startSN-t.startSN,o=e.fragmentHint?e.fragments.concat(e.fragmentHint):e.fragments,l=t.fragmentHint?t.fragments.concat(t.fragmentHint):t.fragments,u=n;u<=a;u++){var h=l[s+u],d=o[u];i&&!d&&u=i.length||z(e,i[r].start)}function z(t,e){if(e){for(var r=t.fragments,i=t.skippedSegments;ie.partTarget&&(l+=1)}if(Object(n.a)(o))return new K(o,Object(n.a)(l)?l:void 0,U.No)}}},e.loadPlaylist=function(t){},e.shouldLoadTrack=function(t){return this.canLoad&&t&&!!t.url&&(!t.details||t.details.live)},e.playlistLoaded=function(t,e,r){var i=this,n=e.details,a=e.stats,s=a.loading.end?Math.max(0,self.performance.now()-a.loading.end):0;if(n.advancedDateTime=Date.now()-s,n.live||null!=r&&r.live){if(n.reloaded(r),r&&this.log("live playlist "+t+" "+(n.advanced?"REFRESHED "+n.lastPartSn+"-"+n.lastPartIndex:"MISSED")),r&&n.fragments.length>0&&q(r,n),!this.canLoad||!n.live)return;var o,l=void 0,u=void 0;if(n.canBlockReload&&n.endSN&&n.advanced){var h=this.hls.config.lowLatencyMode,d=n.lastPartSn,c=n.endSN,f=n.lastPartIndex,g=d===c;-1!==f?(l=g?c+1:d,u=g?h?0:f:f+1):l=c+1;var v=n.age,p=v+n.ageHeader,m=Math.min(p-n.partTarget,1.5*n.targetduration);if(m>0){if(r&&m>r.tuneInGoal)this.warn("CDN Tune-in goal increased from: "+r.tuneInGoal+" to: "+m+" with playlist age: "+n.age),m=0;else{var y=Math.floor(m/n.targetduration);if(l+=y,void 0!==u)u+=Math.round(m%n.targetduration/n.partTarget);this.log("CDN Tune-in age: "+n.ageHeader+"s last advanced "+v.toFixed(2)+"s goal: "+m+" skip sn "+y+" to part "+u)}n.tuneInGoal=m}if(o=this.getDeliveryDirectives(n,e.deliveryDirectives,l,u),h||!g)return void this.loadPlaylist(o)}else o=this.getDeliveryDirectives(n,e.deliveryDirectives,l,u);var T=function(t,e){var r,i=1e3*t.levelTargetDuration,n=i/2,a=t.age,s=a>0&&a<3*i,o=e.loading.end-e.loading.start,l=t.availabilityDelay;if(!1===t.updated)if(s){var u=333*t.misses;r=Math.max(Math.min(n,2*o),u),t.availabilityDelay=(t.availabilityDelay||0)+r}else r=n;else s?(l=Math.min(l||i/2,a),t.availabilityDelay=l,r=l+i-a):r=i-o;return Math.round(r)}(n,a);void 0!==l&&n.canBlockReload&&(T-=n.partTarget||1),this.log("reload live playlist "+t+" in "+Math.round(T)+" ms"),this.timer=self.setTimeout((function(){return i.loadPlaylist(o)}),T)}else this.clearTimer()},e.getDeliveryDirectives=function(t,e,r,i){var n=function(t,e){var r=t.canSkipUntil,i=t.canSkipDateRanges,n=t.endSN;return r&&(void 0!==e?e-n:0)-1&&null!==(e=t.context)&&void 0!==e&&e.deliveryDirectives)this.warn("retry playlist loading #"+this.retryCount+' after "'+t.details+'"'),this.loadPlaylist();else{var a=Math.min(Math.pow(2,this.retryCount)*i.levelLoadingRetryDelay,i.levelLoadingMaxRetryTimeout);this.timer=self.setTimeout((function(){return r.loadPlaylist()}),a),this.warn("retry playlist loading #"+this.retryCount+" in "+a+' ms after "'+t.details+'"')}else this.warn('cannot recover from error "'+t.details+'"'),this.clearTimer(),t.fatal=!0;return n},t}();function $(){return($=Object.assign||function(t){for(var e=1;e0){r=n[0].bitrate,n.sort((function(t,e){return t.bitrate-e.bitrate})),this._levels=n;for(var f=0;fthis.hls.config.fragLoadingMaxRetry&&(a=r.frag.level)):a=r.frag.level}break;case s.a.LEVEL_LOAD_ERROR:case s.a.LEVEL_LOAD_TIMEOUT:i&&(i.deliveryDirectives&&(l=!1),a=i.level),o=!0;break;case s.a.REMUX_ALLOC_ERROR:a=r.level,o=!0}void 0!==a&&this.recoverLevel(r,a,o,l)}}},u.recoverLevel=function(t,e,r,i){var n=t.details,a=this._levels[e];if(a.loadError++,r){if(!this.retryLoadingOrFail(t))return void(this.currentLevelIndex=-1);t.levelRetry=!0}if(i){var s=a.url.length;if(s>1&&a.loadError1){var i=(e.urlId+1)%r;this.warn("Switching to redundant URL-id "+i),this._levels.forEach((function(t){t.urlId=i})),this.level=t}},u.onFragLoaded=function(t,e){var r=e.frag;if(void 0!==r&&r.type===k.b.MAIN){var i=this._levels[r.level];void 0!==i&&(i.fragmentError=0,i.loadError=0)}},u.onLevelLoaded=function(t,e){var r,i,n=e.level,a=e.details,s=this._levels[n];if(!s)return this.warn("Invalid level index "+n),void(null!==(i=e.deliveryDirectives)&&void 0!==i&&i.skip&&(a.deltaUpdateFailed=!0));n===this.currentLevelIndex?(0===s.fragmentError&&(s.loadError=0,this.retryCount=0),this.playlistLoaded(n,e,s.details)):null!==(r=e.deliveryDirectives)&&void 0!==r&&r.skip&&(a.deltaUpdateFailed=!0)},u.onAudioTrackSwitched=function(t,e){var r=this.hls.levels[this.currentLevelIndex];if(r&&r.audioGroupIds){for(var i=-1,n=this.hls.audioTracks[e.id].groupId,a=0;a0){var i=r.urlId,n=r.url[i];if(t)try{n=t.addDirectives(n)}catch(t){this.warn("Could not construct new URL with HLS Delivery Directives: "+t)}this.log("Attempt loading level index "+e+(t?" at sn "+t.msn+" part "+t.part:"")+" with URL-id "+i+" "+n),this.clearTimer(),this.hls.trigger(a.a.LEVEL_LOADING,{url:n,level:e,id:i,deliveryDirectives:t||null})}},u.removeLevel=function(t,e){var r=function(t,r){return r!==e},i=this._levels.filter((function(i,n){return n!==t||i.url.length>1&&void 0!==e&&(i.url=i.url.filter(r),i.audioGroupIds&&(i.audioGroupIds=i.audioGroupIds.filter(r)),i.textGroupIds&&(i.textGroupIds=i.textGroupIds.filter(r)),i.urlId=0,!0)})).map((function(t,e){var r=t.details;return null!=r&&r.fragments&&r.fragments.forEach((function(t){t.level=e})),t}));this._levels=i,this.hls.trigger(a.a.LEVELS_UPDATED,{levels:i})},n=i,(o=[{key:"levels",get:function(){return 0===this._levels.length?null:this._levels}},{key:"level",get:function(){return this.currentLevelIndex},set:function(t){var e,r=this._levels;if(0!==r.length&&(this.currentLevelIndex!==t||null===(e=r[t])||void 0===e||!e.details)){if(t<0||t>=r.length){var i=t<0;if(this.hls.trigger(a.a.ERROR,{type:s.b.OTHER_ERROR,details:s.a.LEVEL_SWITCH_ERROR,level:t,fatal:i,reason:"invalid level idx"}),i)return;t=Math.min(t,r.length-1)}this.clearTimer();var n=this.currentLevelIndex,o=r[n],l=r[t];this.log("switching to level "+t+" from "+n),this.currentLevelIndex=t;var u=$({},l,{level:t,maxBitrate:l.maxBitrate,uri:l.uri,urlId:l.urlId});delete u._urlId,this.hls.trigger(a.a.LEVEL_SWITCHING,u);var h=l.details;if(!h||h.live){var d=this.switchParams(l.uri,null==o?void 0:o.details);this.loadPlaylist(d)}}}},{key:"manualLevel",get:function(){return this.manualLevelIndex},set:function(t){this.manualLevelIndex=t,void 0===this._startLevel&&(this._startLevel=t),-1!==t&&(this.level=t)}},{key:"firstLevel",get:function(){return this._firstLevel},set:function(t){this._firstLevel=t}},{key:"startLevel",get:function(){if(void 0===this._startLevel){var t=this.hls.config.startLevel;return void 0!==t?t:this._firstLevel}return this._startLevel},set:function(t){this._startLevel=t}},{key:"nextLoadLevel",get:function(){return-1!==this.manualLevelIndex?this.manualLevelIndex:this.hls.nextAutoLevel},set:function(t){this.level=t,-1===this.manualLevelIndex&&(this.hls.nextAutoLevel=t)}}])&&J(n.prototype,o),l&&J(n,l),i}(Q);!function(t){t.NOT_LOADED="NOT_LOADED",t.BACKTRACKED="BACKTRACKED",t.APPENDING="APPENDING",t.PARTIAL="PARTIAL",t.OK="OK"}(tt||(tt={}));var it=function(){function t(t){this.activeFragment=null,this.activeParts=null,this.fragments=Object.create(null),this.timeRanges=Object.create(null),this.bufferPadding=.2,this.hls=void 0,this.hls=t,this._registerListeners()}var e=t.prototype;return e._registerListeners=function(){var t=this.hls;t.on(a.a.BUFFER_APPENDED,this.onBufferAppended,this),t.on(a.a.FRAG_BUFFERED,this.onFragBuffered,this),t.on(a.a.FRAG_LOADED,this.onFragLoaded,this)},e._unregisterListeners=function(){var t=this.hls;t.off(a.a.BUFFER_APPENDED,this.onBufferAppended,this),t.off(a.a.FRAG_BUFFERED,this.onFragBuffered,this),t.off(a.a.FRAG_LOADED,this.onFragLoaded,this)},e.destroy=function(){this._unregisterListeners(),this.fragments=this.timeRanges=null},e.getAppendedFrag=function(t,e){if(e===k.b.MAIN){var r=this.activeFragment,i=this.activeParts;if(!r)return null;if(i)for(var n=i.length;n--;){var a=i[n],s=a?a.end:r.appendedPTS;if(a.start<=t&&void 0!==s&&t<=s)return n>9&&(this.activeParts=i.slice(n-9)),a}else if(r.start<=t&&void 0!==r.appendedPTS&&t<=r.appendedPTS)return r}return this.getBufferedFrag(t,e)},e.getBufferedFrag=function(t,e){for(var r=this.fragments,i=Object.keys(r),n=i.length;n--;){var a=r[i[n]];if((null==a?void 0:a.body.type)===e&&a.buffered){var s=a.body;if(s.start<=t&&t<=s.end)return s}}return null},e.detectEvictedFragments=function(t,e,r){var i=this;Object.keys(this.fragments).forEach((function(n){var a=i.fragments[n];if(a)if(a.buffered){var s=a.range[t];s&&s.time.some((function(t){var r=!i.isTimeBuffered(t.startPTS,t.endPTS,e);return r&&i.removeFragment(a.body),r}))}else a.body.type===r&&i.removeFragment(a.body)}))},e.detectPartialFragments=function(t){var e=this,r=this.timeRanges,i=t.frag,n=t.part;if(r&&"initSegment"!==i.sn){var a=at(i),s=this.fragments[a];s&&(Object.keys(r).forEach((function(t){var a=i.elementaryStreams[t];if(a){var o=r[t],l=null!==n||!0===a.partial;s.range[t]=e.getBufferedTimes(i,n,l,o)}})),s.backtrack=s.loaded=null,Object.keys(s.range).length?s.buffered=!0:this.removeFragment(s.body))}},e.fragBuffered=function(t){var e=at(t),r=this.fragments[e];r&&(r.backtrack=r.loaded=null,r.buffered=!0)},e.getBufferedTimes=function(t,e,r,i){for(var n={time:[],partial:r},a=e?e.start:t.start,s=e?e.end:t.end,o=t.minEndPTS||s,l=t.maxStartPTS||a,u=0;u=h&&o<=d){n.time.push({startPTS:Math.max(a,i.start(u)),endPTS:Math.min(s,i.end(u))});break}if(ah)n.partial=!0,n.time.push({startPTS:Math.max(a,i.start(u)),endPTS:Math.min(s,i.end(u))});else if(s<=h)break}return n},e.getPartialFragment=function(t){var e,r,i,n=null,a=0,s=this.bufferPadding,o=this.fragments;return Object.keys(o).forEach((function(l){var u=o[l];u&&nt(u)&&(r=u.body.start-s,i=u.body.end+s,t>=r&&t<=i&&(e=Math.min(t-r,i-t),a<=e&&(n=u.body,a=e)))})),n},e.getState=function(t){var e=at(t),r=this.fragments[e];return r?r.buffered?nt(r)?tt.PARTIAL:tt.OK:r.backtrack?tt.BACKTRACKED:tt.APPENDING:tt.NOT_LOADED},e.backtrack=function(t,e){var r=at(t),i=this.fragments[r];if(!i||i.backtrack)return null;var n=i.backtrack=e||i.loaded;return i.loaded=null,n},e.getBacktrackData=function(t){var e=at(t),r=this.fragments[e];if(r){var i,n=r.backtrack;if(null!=n&&null!==(i=n.payload)&&void 0!==i&&i.byteLength)return n;this.removeFragment(t)}return null},e.isTimeBuffered=function(t,e,r){for(var i,n,a=0;a=i&&e<=n)return!0;if(e<=i)return!1}return!1},e.onFragLoaded=function(t,e){var r=e.frag,i=e.part;if("initSegment"!==r.sn&&!r.bitrateTest&&!i){var n=at(r);this.fragments[n]={body:r,loaded:e,backtrack:null,buffered:!1,range:Object.create(null)}}},e.onBufferAppended=function(t,e){var r=this,i=e.frag,n=e.part,a=e.timeRanges;if(i.type===k.b.MAIN)if(this.activeFragment=i,n){var s=this.activeParts;s||(this.activeParts=s=[]),s.push(n)}else this.activeParts=null;this.timeRanges=a,Object.keys(a).forEach((function(t){var e=a[t];if(r.detectEvictedFragments(t,e),!n)for(var s=0;st&&i.removeFragment(s)}}))},e.removeFragment=function(t){var e=at(t);t.stats.loaded=0,t.clearElementaryStreamInfo(),delete this.fragments[e]},e.removeAllFragments=function(){this.fragments=Object.create(null),this.activeFragment=null,this.activeParts=null},t}();function nt(t){var e,r;return t.buffered&&((null===(e=t.range.video)||void 0===e?void 0:e.partial)||(null===(r=t.range.audio)||void 0===r?void 0:r.partial))}function at(t){return t.type+"_"+t.level+"_"+t.urlId+"_"+t.sn}var st=function(){function t(){this._boundTick=void 0,this._tickTimer=null,this._tickInterval=null,this._tickCallCount=0,this._boundTick=this.tick.bind(this)}var e=t.prototype;return e.destroy=function(){this.onHandlerDestroying(),this.onHandlerDestroyed()},e.onHandlerDestroying=function(){this.clearNextTick(),this.clearInterval()},e.onHandlerDestroyed=function(){},e.hasInterval=function(){return!!this._tickInterval},e.hasNextTick=function(){return!!this._tickTimer},e.setInterval=function(t){return!this._tickInterval&&(this._tickInterval=self.setInterval(this._boundTick,t),!0)},e.clearInterval=function(){return!!this._tickInterval&&(self.clearInterval(this._tickInterval),this._tickInterval=null,!0)},e.clearNextTick=function(){return!!this._tickTimer&&(self.clearTimeout(this._tickTimer),this._tickTimer=null,!0)},e.tick=function(){this._tickCallCount++,1===this._tickCallCount&&(this.doTick(),this._tickCallCount>1&&this.tickImmediate(),this._tickCallCount=0)},e.tickImmediate=function(){this.clearNextTick(),this._tickTimer=self.setTimeout(this._boundTick,0)},e.doTick=function(){},t}(),ot={length:0,start:function(){return 0},end:function(){return 0}},lt=function(){function t(){}return t.isBuffered=function(e,r){try{if(e)for(var i=t.getBuffered(e),n=0;n=i.start(n)&&r<=i.end(n))return!0}catch(t){}return!1},t.bufferInfo=function(e,r,i){try{if(e){var n,a=t.getBuffered(e),s=[];for(n=0;ns&&(i[a-1].end=t[n].end):i.push(t[n])}else i.push(t[n])}else i=t;for(var o,l=0,u=e,h=e,d=0;d=c&&er.startCC||t&&t.cc0)r=n+1;else{if(!(s<0))return a;i=n-1}}return null}};function pt(t,e,r,i){void 0===r&&(r=0),void 0===i&&(i=0);var n=null;if(t?n=e[t.sn-e[0].sn+1]||null:0===r&&0===e[0].start&&(n=e[0]),n&&0===mt(r,i,n))return n;var a=vt.search(e,mt.bind(null,r,i));return a||n}function mt(t,e,r){void 0===t&&(t=0),void 0===e&&(e=0);var i=Math.min(e,r.duration+(r.deltaPTS?r.deltaPTS:0));return r.start+r.duration-i<=t?1:r.start-i>t&&r.start?-1:0}function yt(t,e,r){var i=1e3*Math.min(e,r.duration+(r.deltaPTS?r.deltaPTS:0));return(r.endProgramDateTime||0)-i>t}function Tt(t){var e="function"==typeof Map?new Map:void 0;return(Tt=function(t){if(null===t||(r=t,-1===Function.toString.call(r).indexOf("[native code]")))return t;var r;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,i)}function i(){return bt(t,arguments,Lt(this).constructor)}return i.prototype=Object.create(t.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),St(i,t)})(t)}function bt(t,e,r){return(bt=Et()?Reflect.construct:function(t,e,r){var i=[null];i.push.apply(i,e);var n=new(Function.bind.apply(t,i));return r&&St(n,r.prototype),n}).apply(null,arguments)}function Et(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}function St(t,e){return(St=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function Lt(t){return(Lt=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var At=Math.pow(2,17),Rt=function(){function t(t){this.config=void 0,this.loader=null,this.partLoadTimeout=-1,this.config=t}var e=t.prototype;return e.destroy=function(){this.loader&&(this.loader.destroy(),this.loader=null)},e.abort=function(){this.loader&&this.loader.abort()},e.load=function(t,e){var r=this,i=t.url;if(!i)return Promise.reject(new kt({type:s.b.NETWORK_ERROR,details:s.a.FRAG_LOAD_ERROR,fatal:!1,frag:t,networkDetails:null},"Fragment does not have a "+(i?"part list":"url")));this.abort();var n=this.config,a=n.fLoader,o=n.loader;return new Promise((function(i,l){r.loader&&r.loader.destroy();var u=r.loader=t.loader=a?new a(n):new o(n),h=Dt(t),d={timeout:n.fragLoadingTimeOut,maxRetry:0,retryDelay:0,maxRetryDelay:n.fragLoadingMaxRetryTimeout,highWaterMark:At};t.stats=u.stats,u.load(h,d,{onSuccess:function(e,n,a,s){r.resetLoader(t,u),i({frag:t,part:null,payload:e.data,networkDetails:s})},onError:function(e,i,n){r.resetLoader(t,u),l(new kt({type:s.b.NETWORK_ERROR,details:s.a.FRAG_LOAD_ERROR,fatal:!1,frag:t,response:e,networkDetails:n}))},onAbort:function(e,i,n){r.resetLoader(t,u),l(new kt({type:s.b.NETWORK_ERROR,details:s.a.INTERNAL_ABORTED,fatal:!1,frag:t,networkDetails:n}))},onTimeout:function(e,i,n){r.resetLoader(t,u),l(new kt({type:s.b.NETWORK_ERROR,details:s.a.FRAG_LOAD_TIMEOUT,fatal:!1,frag:t,networkDetails:n}))},onProgress:function(r,i,n,a){e&&e({frag:t,part:null,payload:n,networkDetails:a})}})}))},e.loadPart=function(t,e,r){var i=this;this.abort();var n=this.config,a=n.fLoader,o=n.loader;return new Promise((function(l,u){i.loader&&i.loader.destroy();var h=i.loader=t.loader=a?new a(n):new o(n),d=Dt(t,e),c={timeout:n.fragLoadingTimeOut,maxRetry:0,retryDelay:0,maxRetryDelay:n.fragLoadingMaxRetryTimeout,highWaterMark:At};e.stats=h.stats,h.load(d,c,{onSuccess:function(n,a,s,o){i.resetLoader(t,h),i.updateStatsFromPart(t,e);var u={frag:t,part:e,payload:n.data,networkDetails:o};r(u),l(u)},onError:function(r,n,a){i.resetLoader(t,h),u(new kt({type:s.b.NETWORK_ERROR,details:s.a.FRAG_LOAD_ERROR,fatal:!1,frag:t,part:e,response:r,networkDetails:a}))},onAbort:function(r,n,a){t.stats.aborted=e.stats.aborted,i.resetLoader(t,h),u(new kt({type:s.b.NETWORK_ERROR,details:s.a.INTERNAL_ABORTED,fatal:!1,frag:t,part:e,networkDetails:a}))},onTimeout:function(r,n,a){i.resetLoader(t,h),u(new kt({type:s.b.NETWORK_ERROR,details:s.a.FRAG_LOAD_TIMEOUT,fatal:!1,frag:t,part:e,networkDetails:a}))}})}))},e.updateStatsFromPart=function(t,e){var r=t.stats,i=e.stats,n=i.total;if(r.loaded+=i.loaded,n){var a=Math.round(t.duration/e.duration),s=Math.min(Math.round(r.loaded/n),a),o=(a-s)*Math.round(r.loaded/s);r.total=r.loaded+o}else r.total=Math.max(r.loaded,r.total);var l=r.loading,u=i.loading;l.start?l.first+=u.first-u.start:(l.start=u.start,l.first=u.first),l.end=u.end},e.resetLoader=function(t,e){t.loader=null,this.loader===e&&(self.clearTimeout(this.partLoadTimeout),this.loader=null),e.destroy()},t}();function Dt(t,e){void 0===e&&(e=null);var r=e||t,i={frag:t,part:e,responseType:"arraybuffer",url:r.url,headers:{},rangeStart:0,rangeEnd:0},a=r.byteRangeStartOffset,s=r.byteRangeEndOffset;return Object(n.a)(a)&&Object(n.a)(s)&&(i.rangeStart=a,i.rangeEnd=s),i}var kt=function(t){var e,r;function i(e){for(var r,i=arguments.length,n=new Array(i>1?i-1:0),a=1;a=e.endSN&&!t.nextStart){var n=e.partList;if(null!=n&&n.length){var a=n[n.length-1];return lt.isBuffered(this.media,a.start+a.duration/2)}var s=i.getState(r);return s===tt.PARTIAL||s===tt.OK}return!1},c.onMediaAttached=function(t,e){var r=this.media=this.mediaBuffer=e.media;this.onvseeking=this.onMediaSeeking.bind(this),this.onvended=this.onMediaEnded.bind(this),r.addEventListener("seeking",this.onvseeking),r.addEventListener("ended",this.onvended);var i=this.config;this.levels&&i.autoStartLoad&&this.state===Ot&&this.startLoad(i.startPosition)},c.onMediaDetaching=function(){var t=this.media;null!=t&&t.ended&&(this.log("MSE detaching and video ended, reset startPosition"),this.startPosition=this.lastCurrentTime=0),t&&(t.removeEventListener("seeking",this.onvseeking),t.removeEventListener("ended",this.onvended),this.onvseeking=this.onvended=null),this.media=this.mediaBuffer=null,this.loadedmetadata=!1,this.fragmentTracker.removeAllFragments(),this.stopLoad()},c.onMediaSeeking=function(){var t=this.config,e=this.fragCurrent,r=this.media,i=this.mediaBuffer,a=this.state,s=r?r.currentTime:0,o=lt.bufferInfo(i||r,s,t.maxBufferHole);if(this.log("media seeking to "+(Object(n.a)(s)?s.toFixed(3):s)+", state: "+a),a===Kt)this.resetLoadingState();else if(e&&!o.len){var l=t.maxFragLookUpTolerance,u=e.start-l,h=s>e.start+e.duration+l;(s0&&s&&s.key&&s.iv&&"AES-128"===s.method){var o=self.performance.now();return e.decrypter.webCryptoDecrypt(new Uint8Array(n),s.key.buffer,s.iv.buffer).then((function(e){var n=self.performance.now();return i.trigger(a.a.FRAG_DECRYPTED,{frag:t,payload:e,stats:{tstart:o,tdecrypt:n}}),r.payload=e,r}))}return r})).then((function(r){var i=e.fragCurrent,n=e.hls,s=e.levels;if(!s)throw new Error("init load aborted, missing levels");s[t.level].details;var o=t.stats;e.state=xt,e.fragLoadError=0,t.data=new Uint8Array(r.payload),o.parsing.start=o.buffering.start=self.performance.now(),o.parsing.end=o.buffering.end=self.performance.now(),r.frag===i&&n.trigger(a.a.FRAG_BUFFERED,{stats:o,frag:i,part:null,id:t.type}),e.tick()})).catch((function(r){e.warn(r),e.resetFragmentLoading(t)}))},c.fragContextChanged=function(t){var e=this.fragCurrent;return!t||!e||t.level!==e.level||t.sn!==e.sn||t.urlId!==e.urlId},c.fragBufferedComplete=function(t,e){var r=this.mediaBuffer?this.mediaBuffer:this.media;this.log("Buffered "+t.type+" sn: "+t.sn+(e?" part: "+e.index:"")+" of "+("[stream-controller]"===this.logPrefix?"level":"track")+" "+t.level+" "+It.toString(lt.getBuffered(r))),this.state=xt,this.tick()},c._handleFragmentLoadComplete=function(t){var e=this.transmuxer;if(e){var r=t.frag,i=t.part,n=t.partsLoaded,a=!n||0===n.length||n.some((function(t){return!t})),s=new ut(r.level,r.sn,r.stats.chunkCount+1,0,i?i.index:-1,!a);e.flush(s)}},c._handleFragmentLoadProgress=function(t){},c._doFragLoad=function(t,e,r,i){var s=this;if(void 0===r&&(r=null),!this.levels)throw new Error("frag load aborted, missing levels");if(r=Math.max(t.start,r||0),this.config.lowLatencyMode&&e){var o=e.partList;if(o&&i){r>t.end&&e.fragmentHint&&(t=e.fragmentHint);var l=this.getNextPart(o,t,r);if(l>-1){var u=o[l];return this.log("Loading part sn: "+t.sn+" p: "+u.index+" cc: "+t.cc+" of playlist ["+e.startSN+"-"+e.endSN+"] parts [0-"+l+"-"+(o.length-1)+"] "+("[stream-controller]"===this.logPrefix?"level":"track")+": "+t.level+", target: "+parseFloat(r.toFixed(3))),this.nextLoadPosition=u.start+u.duration,this.state=Mt,this.hls.trigger(a.a.FRAG_LOADING,{frag:t,part:o[l],targetBufferTime:r}),this.doFragPartsLoad(t,o,l,i).catch((function(t){return s.handleFragLoadError(t)}))}if(!t.url||this.loadedEndOfParts(o,r))return Promise.resolve(null)}}return this.log("Loading fragment "+t.sn+" cc: "+t.cc+" "+(e?"of ["+e.startSN+"-"+e.endSN+"] ":"")+("[stream-controller]"===this.logPrefix?"level":"track")+": "+t.level+", target: "+parseFloat(r.toFixed(3))),Object(n.a)(t.sn)&&!this.bitrateTest&&(this.nextLoadPosition=t.start+t.duration),this.state=Mt,this.hls.trigger(a.a.FRAG_LOADING,{frag:t,targetBufferTime:r}),this.fragmentLoader.load(t,i).catch((function(t){return s.handleFragLoadError(t)}))},c.doFragPartsLoad=function(t,e,r,i){var n=this;return new Promise((function(s,o){var l=[];!function r(u){var h=e[u];n.fragmentLoader.loadPart(t,h,i).then((function(i){l[h.index]=i;var o=i.part;n.hls.trigger(a.a.FRAG_LOADED,i);var d=e[u+1];if(!d||d.fragment!==t)return s({frag:t,part:o,partsLoaded:l});r(u+1)})).catch(o)}(r)}))},c.handleFragLoadError=function(t){var e=t.data;return e&&e.details===s.a.INTERNAL_ABORTED?this.handleFragLoadAborted(e.frag,e.part):this.hls.trigger(a.a.ERROR,e),null},c._handleTransmuxerFlush=function(t){var e=this.getCurrentContext(t);if(e&&this.state===Ut){var r=e.frag,i=e.part,n=e.level,a=self.performance.now();r.stats.parsing.end=a,i&&(i.stats.parsing.end=a),this.updateLevelTiming(r,i,n,t.partial)}else this.fragCurrent||(this.state=xt)},c.getCurrentContext=function(t){var e=this.levels,r=t.level,i=t.sn,n=t.part;if(!e||!e[r])return this.warn("Levels object was unset while buffering fragment "+i+" of level "+r+". The current chunk will not be buffered."),null;var a=e[r],s=n>-1?function(t,e,r){if(!t||!t.details)return null;var i=t.details.partList;if(i)for(var n=i.length;n--;){var a=i[n];if(a.index===r&&a.fragment.sn===e)return a}return null}(a,i,n):null,o=s?s.fragment:function(t,e,r){if(!t||!t.details)return null;var i=t.details,n=i.fragments[e-i.startSN];return n||((n=i.fragmentHint)&&n.sn===e?n:ea&&this.flushMainBuffer(s,t.start)}else this.flushMainBuffer(0,t.start)},c.getFwdBufferInfo=function(t,e){var r=this.config,i=this.getLoadPosition();if(!Object(n.a)(i))return null;var a=lt.bufferInfo(t,i,r.maxBufferHole);if(0===a.len&&void 0!==a.nextStart){var s=this.fragmentTracker.getBufferedFrag(i,e);if(s&&a.nextStart=r&&(e.maxMaxBufferLength/=2,this.warn("Reduce max buffer length to "+e.maxMaxBufferLength+"s"),!0)},c.getNextFragment=function(t,e){var r,i,n=e.fragments,a=n.length;if(!a)return null;var s,o=this.config,l=n[0].start;if(e.live){var u=o.initialLiveManifestSize;if(a-1&&rr.start&&r.loaded},c.getInitialLiveFragment=function(t,e){var r=this.fragPrevious,i=null;if(r){if(t.hasProgramDateTime&&(this.log("Live playlist, switching playlist, load frag with same PDT: "+r.programDateTime),i=function(t,e,r){if(null===e||!Array.isArray(t)||!t.length||!Object(n.a)(e))return null;if(e<(t[0].programDateTime||0))return null;if(e>=(t[t.length-1].endProgramDateTime||0))return null;r=r||0;for(var i=0;i=t.startSN&&a<=t.endSN){var s=e[a-t.startSN];r.cc===s.cc&&(i=s,this.log("Live playlist, switching playlist, load frag with next SN: "+i.sn))}i||(i=function(t,e){return vt.search(t,(function(t){return t.cce?-1:0}))}(e,r.cc))&&this.log("Live playlist, switching playlist, load frag with same CC: "+i.sn)}}else{var o=this.hls.liveSyncPosition;null!==o&&(i=this.getFragmentAtPosition(o,this.bitrateTest?t.fragmentEnd:t.edge,t))}return i},c.getFragmentAtPosition=function(t,e,r){var i,n=this.config,a=this.fragPrevious,s=r.fragments,o=r.endSN,l=r.fragmentHint,u=n.maxFragLookUpTolerance,h=!!(n.lowLatencyMode&&r.partList&&l);(h&&l&&!this.bitrateTest&&(s=s.concat(l),o=l.sn),te-u?0:u):i=s[s.length-1];if(i){var d=i.sn-r.startSN,c=a&&i.level===a.level,f=s[d+1];if(this.fragmentTracker.getState(i)===tt.BACKTRACKED){i=null;for(var g=d;s[g]&&this.fragmentTracker.getState(s[g])===tt.BACKTRACKED;)i=a?s[g--]:s[--g];i||(i=f)}else a&&i.sn===a.sn&&!h&&c&&(i.sn=a-e.maxFragLookUpTolerance&&n<=s;if(null!==i&&r.duration>i&&(n"+t.startSN+" prev-sn: "+(a?a.sn:"na")+" fragments: "+o),d}return l},c.waitForCdnTuneIn=function(t){return t.live&&t.canBlockReload&&t.tuneInGoal>Math.max(t.partHoldBack,3*t.partTarget)},c.setStartPosition=function(t,e){var r=this.startPosition;if(r"+t))}}])&&Ct(u.prototype,h),d&&Ct(u,d),i}(st);function Yt(){return self.MediaSource||self.WebKitMediaSource}function qt(){return self.SourceBuffer||self.WebKitSourceBuffer}var Xt=r(18),zt=r(10),Qt=r(14),$t=Yt()||{isTypeSupported:function(){return!1}},Jt=function(){function t(t,e,r,i){var n=this;this.hls=void 0,this.id=void 0,this.observer=void 0,this.frag=null,this.part=null,this.worker=void 0,this.onwmsg=void 0,this.transmuxer=null,this.onTransmuxComplete=void 0,this.onFlush=void 0,this.hls=t,this.id=e,this.onTransmuxComplete=r,this.onFlush=i;var l=t.config,u=function(e,r){(r=r||{}).frag=n.frag,r.id=n.id,t.trigger(e,r)};this.observer=new Qt.EventEmitter,this.observer.on(a.a.FRAG_DECRYPTED,u),this.observer.on(a.a.ERROR,u);var h={mp4:$t.isTypeSupported("video/mp4"),mpeg:$t.isTypeSupported("audio/mpeg"),mp3:$t.isTypeSupported('audio/mp4; codecs="mp3"')},d=navigator.vendor;if(l.enableWorker&&"undefined"!=typeof Worker){var c;o.b.log("demuxing in webworker");try{c=this.worker=Xt(19),this.onwmsg=this.onWorkerMessage.bind(this),c.addEventListener("message",this.onwmsg),c.onerror=function(e){t.trigger(a.a.ERROR,{type:s.b.OTHER_ERROR,details:s.a.INTERNAL_EXCEPTION,fatal:!0,event:"demuxerWorker",error:new Error(e.message+" ("+e.filename+":"+e.lineno+")")})},c.postMessage({cmd:"init",typeSupported:h,vendor:d,id:e,config:JSON.stringify(l)})}catch(t){o.b.warn("Error in worker:",t),o.b.error("Error while initializing DemuxerWorker, fallback to inline"),c&&self.URL.revokeObjectURL(c.objectURL),this.transmuxer=new zt.c(this.observer,h,l,d,e),this.worker=null}}else this.transmuxer=new zt.c(this.observer,h,l,d,e)}var e=t.prototype;return e.destroy=function(){var t=this.worker;if(t)t.removeEventListener("message",this.onwmsg),t.terminate(),this.worker=null;else{var e=this.transmuxer;e&&(e.destroy(),this.transmuxer=null)}var r=this.observer;r&&r.removeAllListeners(),this.observer=null},e.push=function(t,e,r,i,n,a,s,l,u,h){var d,c,f=this;u.transmuxing.start=self.performance.now();var g=this.transmuxer,v=this.worker,p=a?a.start:n.start,m=n.decryptdata,y=this.frag,T=!(y&&n.cc===y.cc),b=!(y&&u.level===y.level),E=y?u.sn-y.sn:-1,S=this.part?u.part-this.part.index:1,L=!b&&(1===E||0===E&&1===S),A=self.performance.now();(b||E||0===n.stats.parsing.start)&&(n.stats.parsing.start=A),!a||!S&&L||(a.stats.parsing.start=A);var R=!(y&&(null===(d=n.initSegment)||void 0===d?void 0:d.url)===(null===(c=y.initSegment)||void 0===c?void 0:c.url)),D=new zt.b(T,L,l,b,p,R);if(!L||T||R){o.b.log("[transmuxer-interface, "+n.type+"]: Starting new transmux session for sn: "+u.sn+" p: "+u.part+" level: "+u.level+" id: "+u.id+"\n discontinuity: "+T+"\n trackSwitch: "+b+"\n contiguous: "+L+"\n accurateTimeOffset: "+l+"\n timeOffset: "+p+"\n initSegmentChange: "+R);var k=new zt.a(r,i,e,s,h);this.configureTransmuxer(k)}if(this.frag=n,this.part=a,v)v.postMessage({cmd:"demux",data:t,decryptdata:m,chunkMeta:u,state:D},t instanceof ArrayBuffer?[t]:[]);else if(g){var _=g.push(t,m,u,D);Object(zt.d)(_)?_.then((function(t){f.handleTransmuxComplete(t)})):this.handleTransmuxComplete(_)}},e.flush=function(t){var e=this;t.transmuxing.start=self.performance.now();var r=this.transmuxer,i=this.worker;if(i)i.postMessage({cmd:"flush",chunkMeta:t});else if(r){var n=r.flush(t);Object(zt.d)(n)?n.then((function(r){e.handleFlushResult(r,t)})):this.handleFlushResult(n,t)}},e.handleFlushResult=function(t,e){var r=this;t.forEach((function(t){r.handleTransmuxComplete(t)})),this.onFlush(e)},e.onWorkerMessage=function(t){var e=t.data,r=this.hls;switch(e.event){case"init":self.URL.revokeObjectURL(this.worker.objectURL);break;case"transmuxComplete":this.handleTransmuxComplete(e.data);break;case"flush":this.onFlush(e.data);break;default:e.data=e.data||{},e.data.frag=this.frag,e.data.id=this.id,r.trigger(e.event,e.data)}},e.configureTransmuxer=function(t){var e=this.worker,r=this.transmuxer;e?e.postMessage({cmd:"configure",config:t}):r&&r.configure(t)},e.handleTransmuxComplete=function(t){t.chunkMeta.transmuxing.end=self.performance.now(),this.onTransmuxComplete(t)},t}(),Zt=function(){function t(t,e,r,i){this.config=void 0,this.media=void 0,this.fragmentTracker=void 0,this.hls=void 0,this.nudgeRetry=0,this.stallReported=!1,this.stalled=null,this.moved=!1,this.seeking=!1,this.config=t,this.media=e,this.fragmentTracker=r,this.hls=i}var e=t.prototype;return e.destroy=function(){this.hls=this.fragmentTracker=this.media=null},e.poll=function(t){var e=this.config,r=this.media,i=this.stalled,n=r.currentTime,a=r.seeking,s=this.seeking&&!a,l=!this.seeking&&a;if(this.seeking=a,n===t){if((l||s)&&(this.stalled=null),!r.paused&&!r.ended&&0!==r.playbackRate&<.getBuffered(r).length){var u=lt.bufferInfo(r,n,0),h=u.len>0,d=u.nextStart||0;if(h||d){if(a){var c=u.len>2,f=!d||d-n>2&&!this.fragmentTracker.getPartialFragment(n);if(c||f)return;this.moved=!1}if(!this.moved&&null!==this.stalled){var g,v=Math.max(d,u.start||0)-n,p=this.hls.levels?this.hls.levels[this.hls.currentLevel]:null,m=(null==p||null===(g=p.details)||void 0===g?void 0:g.live)?2*p.details.targetduration:2;if(v>0&&v<=m)return void this._trySkipBufferHole(null)}var y=self.performance.now();if(null!==i){var T=y-i;!a&&T>=250&&this._reportStall(u.len);var b=lt.bufferInfo(r,n,e.maxBufferHole);this._tryFixBufferStall(b,T)}else this.stalled=y}}}else if(this.moved=!0,null!==i){if(this.stallReported){var E=self.performance.now()-i;o.b.warn("playback not stuck anymore @"+n+", after "+Math.round(E)+"ms"),this.stallReported=!1}this.stalled=null,this.nudgeRetry=0}},e._tryFixBufferStall=function(t,e){var r=this.config,i=this.fragmentTracker,n=this.media.currentTime,a=i.getPartialFragment(n);if(a&&this._trySkipBufferHole(a))return;t.len>r.maxBufferHole&&e>1e3*r.highBufferWatchdogPeriod&&(o.b.warn("Trying to nudge playhead over buffer-hole"),this.stalled=null,this._tryNudgeBuffer())},e._reportStall=function(t){var e=this.hls,r=this.media;this.stallReported||(this.stallReported=!0,o.b.warn("Playback stalling at @"+r.currentTime+" due to low buffer (buffer="+t+")"),e.trigger(a.a.ERROR,{type:s.b.MEDIA_ERROR,details:s.a.BUFFER_STALLED_ERROR,fatal:!1,buffer:t}))},e._trySkipBufferHole=function(t){for(var e=this.config,r=this.hls,i=this.media,n=i.currentTime,l=0,u=lt.getBuffered(i),h=0;h=l&&n0&&-1===t&&(this.log("Override startPosition with lastCurrentTime @"+e.toFixed(3)),t=e),this.state=xt,this.nextLoadPosition=this.startPosition=this.lastCurrentTime=t,this.tick()}else this._forceStartLoad=!0,this.state=Ot},c.stopLoad=function(){this._forceStartLoad=!1,t.prototype.stopLoad.call(this)},c.doTick=function(){switch(this.state){case xt:this.doTickIdle();break;case Vt:var t,e=this.levels,r=this.level,i=null==e||null===(t=e[r])||void 0===t?void 0:t.details;if(i&&(!i.live||this.levelLastLoaded===this.level)){if(this.waitForCdnTuneIn(i))break;this.state=xt;break}break;case Ft:var n,a=self.performance.now(),s=this.retryDate;(!s||a>=s||null!==(n=this.media)&&void 0!==n&&n.seeking)&&(this.log("retryDate reached, switch back to IDLE state"),this.state=xt)}this.onTickEnd()},c.onTickEnd=function(){t.prototype.onTickEnd.call(this),this.checkBuffer(),this.checkFragmentChanged()},c.doTickIdle=function(){var t,e,r=this.hls,i=this.levelLastLoaded,n=this.levels,s=this.media,o=r.config,l=r.nextLoadLevel;if(null!==i&&(s||!this.startFragRequested&&o.startFragPrefetch)&&(!this.altAudio||!this.audioOnly)&&n&&n[l]){var h=n[l];this.level=r.nextLoadLevel=l;var d=h.details;if(!d||this.state===Vt||d.live&&this.levelLastLoaded!==l)this.state=Vt;else{var c=this.getFwdBufferInfo(this.mediaBuffer?this.mediaBuffer:s,k.b.MAIN);if(null!==c)if(!(c.len>=this.getMaxBufferLength(h.maxBitrate))){if(this._streamEnded(c,d)){var f={};return this.altAudio&&(f.type="video"),this.hls.trigger(a.a.BUFFER_EOS,f),void(this.state=Kt)}var g=c.end,v=this.getNextFragment(g,d);if(this.couldBacktrack&&!this.fragPrevious&&v&&"initSegment"!==v.sn){var p=v.sn-d.startSN;p>1&&(v=d.fragments[p-1],this.fragmentTracker.removeFragment(v))}if(v&&this.fragmentTracker.getState(v)===tt.OK&&this.nextLoadPosition>g){var m=this.audioOnly&&!this.altAudio?u.a.AUDIO:u.a.VIDEO;this.afterBufferFlushed(s,m,k.b.MAIN),v=this.getNextFragment(this.nextLoadPosition,d)}v&&(!v.initSegment||v.initSegment.data||this.bitrateTest||(v=v.initSegment),"identity"!==(null===(t=v.decryptdata)||void 0===t?void 0:t.keyFormat)||null!==(e=v.decryptdata)&&void 0!==e&&e.key?this.loadFragment(v,d,g):this.loadKey(v,d))}}}},c.loadFragment=function(e,r,i){var n,a=this.fragmentTracker.getState(e);if(this.fragCurrent=e,a===tt.BACKTRACKED){var s=this.fragmentTracker.getBacktrackData(e);if(s)return this._handleFragmentLoadProgress(s),void this._handleFragmentLoadComplete(s);a=tt.NOT_LOADED}a===tt.NOT_LOADED||a===tt.PARTIAL?"initSegment"===e.sn?this._loadInitSegment(e):this.bitrateTest?(e.bitrateTest=!0,this.log("Fragment "+e.sn+" of level "+e.level+" is being downloaded to test bitrate and will not be buffered"),this._loadBitrateTestFrag(e)):(this.startFragRequested=!0,t.prototype.loadFragment.call(this,e,r,i)):a===tt.APPENDING?this.reduceMaxBufferLength(e.duration)&&this.fragmentTracker.removeFragment(e):0===(null===(n=this.media)||void 0===n?void 0:n.buffered.length)&&this.fragmentTracker.removeAllFragments()},c.getAppendedFrag=function(t){var e=this.fragmentTracker.getAppendedFrag(t,k.b.MAIN);return e&&"fragment"in e?e.fragment:e},c.getBufferedFrag=function(t){return this.fragmentTracker.getBufferedFrag(t,k.b.MAIN)},c.followingBufferedFrag=function(t){return t?this.getBufferedFrag(t.end+.5):null},c.immediateLevelSwitch=function(){this.abortCurrentFrag(),this.flushMainBuffer(0,Number.POSITIVE_INFINITY)},c.nextLevelSwitch=function(){var t=this.levels,e=this.media;if(null!=e&&e.readyState){var r,i=this.getAppendedFrag(e.currentTime);if(i&&i.start>1&&this.flushMainBuffer(0,i.start-1),!e.paused&&t){var n=t[this.hls.nextLoadLevel],a=this.fragLastKbps;r=a&&this.fragCurrent?this.fragCurrent.duration*n.maxBitrate/(1e3*a)+1:0}else r=0;var s=this.getBufferedFrag(e.currentTime+r);if(s){var o=this.followingBufferedFrag(s);if(o){this.abortCurrentFrag();var l=o.maxStartPTS?o.maxStartPTS:o.start,u=o.duration,h=Math.max(s.end,l+Math.min(Math.max(u-this.config.maxFragLookUpTolerance,.5*u),.75*u));this.flushMainBuffer(h,Number.POSITIVE_INFINITY)}}}},c.abortCurrentFrag=function(){var t=this.fragCurrent;this.fragCurrent=null,null!=t&&t.loader&&t.loader.abort(),this.state===Pt&&(this.state=xt),this.nextLoadPosition=this.getLoadPosition()},c.flushMainBuffer=function(e,r){t.prototype.flushMainBuffer.call(this,e,r,this.altAudio?"video":null)},c.onMediaAttached=function(e,r){t.prototype.onMediaAttached.call(this,e,r);var i=r.media;this.onvplaying=this.onMediaPlaying.bind(this),this.onvseeked=this.onMediaSeeked.bind(this),i.addEventListener("playing",this.onvplaying),i.addEventListener("seeked",this.onvseeked),this.gapController=new Zt(this.config,i,this.fragmentTracker,this.hls)},c.onMediaDetaching=function(){var e=this.media;e&&(e.removeEventListener("playing",this.onvplaying),e.removeEventListener("seeked",this.onvseeked),this.onvplaying=this.onvseeked=null,this.videoBuffer=null),this.fragPlaying=null,this.gapController&&(this.gapController.destroy(),this.gapController=null),t.prototype.onMediaDetaching.call(this)},c.onMediaPlaying=function(){this.tick()},c.onMediaSeeked=function(){var t=this.media,e=t?t.currentTime:null;Object(n.a)(e)&&this.log("Media seeked to "+e.toFixed(3)),this.tick()},c.onManifestLoading=function(){this.log("Trigger BUFFER_RESET"),this.hls.trigger(a.a.BUFFER_RESET,void 0),this.fragmentTracker.removeAllFragments(),this.couldBacktrack=this.stalled=!1,this.startPosition=this.lastCurrentTime=0,this.fragPlaying=null},c.onManifestParsed=function(t,e){var r,i,n,a=!1,s=!1;e.levels.forEach((function(t){(r=t.audioCodec)&&(-1!==r.indexOf("mp4a.40.2")&&(a=!0),-1!==r.indexOf("mp4a.40.5")&&(s=!0))})),this.audioCodecSwitch=a&&s&&!("function"==typeof(null==(n=qt())||null===(i=n.prototype)||void 0===i?void 0:i.changeType)),this.audioCodecSwitch&&this.log("Both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC"),this.levels=e.levels,this.startFragRequested=!1},c.onLevelLoading=function(t,e){var r=this.levels;if(r&&this.state===xt){var i=r[e.level];(!i.details||i.details.live&&this.levelLastLoaded!==e.level||this.waitForCdnTuneIn(i.details))&&(this.state=Vt)}},c.onLevelLoaded=function(t,e){var r,i=this.levels,n=e.level,s=e.details,o=s.totalduration;if(i){this.log("Level "+n+" loaded ["+s.startSN+","+s.endSN+"], cc ["+s.startCC+", "+s.endCC+"] duration:"+o);var l=this.fragCurrent;!l||this.state!==Mt&&this.state!==Ft||l.level!==e.level&&l.loader&&(this.state=xt,l.loader.abort());var u=i[n],h=0;if(s.live||null!==(r=u.details)&&void 0!==r&&r.live){if(s.fragments[0]||(s.deltaUpdateFailed=!0),s.deltaUpdateFailed)return;h=this.alignPlaylists(s,u.details)}if(u.details=s,this.levelLastLoaded=n,this.hls.trigger(a.a.LEVEL_UPDATED,{details:s,level:n}),this.state===Vt){if(this.waitForCdnTuneIn(s))return;this.state=xt}this.startFragRequested?s.live&&this.synchronizeToLiveEdge(s):this.setStartPosition(s,h),this.tick()}else this.warn("Levels were reset while loading level "+n)},c._handleFragmentLoadProgress=function(t){var e,r=t.frag,i=t.part,n=t.payload,a=this.levels;if(a){var s=a[r.level],o=s.details;if(o){var l=s.videoCodec,u=o.PTSKnown||!o.live,h=null===(e=r.initSegment)||void 0===e?void 0:e.data,d=this._getAudioCodec(s),c=this.transmuxer=this.transmuxer||new Jt(this.hls,k.b.MAIN,this._handleTransmuxComplete.bind(this),this._handleTransmuxerFlush.bind(this)),f=i?i.index:-1,g=-1!==f,v=new ut(r.level,r.sn,r.stats.chunkCount,n.byteLength,f,g),p=this.initPTS[r.cc];c.push(n,h,d,l,r,i,o.totalduration,u,v,p)}else this.warn("Dropping fragment "+r.sn+" of level "+r.level+" after level details were reset")}else this.warn("Levels were reset while fragment load was in progress. Fragment "+r.sn+" of level "+r.level+" will not be buffered")},c.onAudioTrackSwitching=function(t,e){var r=this.altAudio,i=!!e.url,n=e.id;if(!i){if(this.mediaBuffer!==this.media){this.log("Switching on main audio, use media.buffered to schedule main fragment loading"),this.mediaBuffer=this.media;var s=this.fragCurrent;null!=s&&s.loader&&(this.log("Switching to main audio track, cancel main fragment load"),s.loader.abort()),this.resetTransmuxer(),this.resetLoadingState()}else this.audioOnly&&this.resetTransmuxer();var o=this.hls;r&&o.trigger(a.a.BUFFER_FLUSHING,{startOffset:0,endOffset:Number.POSITIVE_INFINITY,type:"audio"}),o.trigger(a.a.AUDIO_TRACK_SWITCHED,{id:n})}},c.onAudioTrackSwitched=function(t,e){var r=e.id,i=!!this.hls.audioTracks[r].url;if(i){var n=this.videoBuffer;n&&this.mediaBuffer!==n&&(this.log("Switching on alternate audio, use video.buffered to schedule main fragment loading"),this.mediaBuffer=n)}this.altAudio=i,this.tick()},c.onBufferCreated=function(t,e){var r,i,n=e.tracks,a=!1;for(var s in n){var o=n[s];if("main"===o.id){if(i=s,r=o,"video"===s){var l=n[s];l&&(this.videoBuffer=l.buffer)}}else a=!0}a&&r?(this.log("Alternate track found, use "+i+".buffered to schedule main fragment loading"),this.mediaBuffer=r.buffer):this.mediaBuffer=this.media},c.onFragBuffered=function(t,e){var r=e.frag,i=e.part;if(!r||r.type===k.b.MAIN){if(this.fragContextChanged(r))return this.warn("Fragment "+r.sn+(i?" p: "+i.index:"")+" of level "+r.level+" finished buffering, but was aborted. state: "+this.state),void(this.state===Bt&&(this.state=xt));var n=i?i.stats:r.stats;this.fragLastKbps=Math.round(8*n.total/(n.buffering.end-n.loading.first)),"initSegment"!==r.sn&&(this.fragPrevious=r),this.fragBufferedComplete(r,i)}},c.onError=function(t,e){switch(e.details){case s.a.FRAG_LOAD_ERROR:case s.a.FRAG_LOAD_TIMEOUT:case s.a.KEY_LOAD_ERROR:case s.a.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(k.b.MAIN,e);break;case s.a.LEVEL_LOAD_ERROR:case s.a.LEVEL_LOAD_TIMEOUT:this.state!==jt&&(e.fatal?(this.warn(""+e.details),this.state=jt):e.levelRetry||this.state!==Vt||(this.state=xt));break;case s.a.BUFFER_FULL_ERROR:if("main"===e.parent&&(this.state===Ut||this.state===Bt)){var r=!0,i=this.getFwdBufferInfo(this.media,k.b.MAIN);i&&i.len>.5&&(r=!this.reduceMaxBufferLength(i.len)),r&&(this.warn("buffer full error also media.currentTime is not buffered, flush main"),this.immediateLevelSwitch()),this.resetLoadingState()}}},c.checkBuffer=function(){var t=this.media,e=this.gapController;if(t&&e&&t.readyState){var r=lt.getBuffered(t);!this.loadedmetadata&&r.length?(this.loadedmetadata=!0,this.seekToStartPos()):e.poll(this.lastCurrentTime),this.lastCurrentTime=t.currentTime}},c.onFragLoadEmergencyAborted=function(){this.state=xt,this.loadedmetadata||(this.startFragRequested=!1,this.nextLoadPosition=this.startPosition),this.tickImmediate()},c.onBufferFlushed=function(t,e){var r=e.type;if(r!==u.a.AUDIO||this.audioOnly&&!this.altAudio){var i=(r===u.a.VIDEO?this.videoBuffer:this.mediaBuffer)||this.media;this.afterBufferFlushed(i,r,k.b.MAIN)}},c.onLevelsUpdated=function(t,e){this.levels=e.levels},c.swapAudioCodec=function(){this.audioCodecSwap=!this.audioCodecSwap},c.seekToStartPos=function(){var t=this.media,e=t.currentTime,r=this.startPosition;if(r>=0&&e0&&(n1&&!1===t.seeking){var r=t.currentTime;if(lt.isBuffered(t,r)?e=this.getAppendedFrag(r):lt.isBuffered(t,r+.1)&&(e=this.getAppendedFrag(r+.1)),e){var i=this.fragPlaying,n=e.level;i&&e.sn===i.sn&&i.level===n&&e.urlId===i.urlId||(this.hls.trigger(a.a.FRAG_CHANGED,{frag:e}),i&&i.level===n||this.hls.trigger(a.a.LEVEL_SWITCHED,{level:n}),this.fragPlaying=e)}}},l=i,(h=[{key:"nextLevel",get:function(){var t=this.nextBufferedFrag;return t?t.level:-1}},{key:"currentLevel",get:function(){var t=this.media;if(t){var e=this.getAppendedFrag(t.currentTime);if(e)return e.level}return-1}},{key:"nextBufferedFrag",get:function(){var t=this.media;if(t){var e=this.getAppendedFrag(t.currentTime);return this.followingBufferedFrag(e)}return null}},{key:"forceStartLoad",get:function(){return this._forceStartLoad}}])&&te(l.prototype,h),d&&te(l,d),i}(Wt),ie=function(){function t(t,e,r){void 0===e&&(e=0),void 0===r&&(r=0),this.halfLife=void 0,this.alpha_=void 0,this.estimate_=void 0,this.totalWeight_=void 0,this.halfLife=t,this.alpha_=t?Math.exp(Math.log(.5)/t):0,this.estimate_=e,this.totalWeight_=r}var e=t.prototype;return e.sample=function(t,e){var r=Math.pow(this.alpha_,t);this.estimate_=e*(1-r)+r*this.estimate_,this.totalWeight_+=t},e.getTotalWeight=function(){return this.totalWeight_},e.getEstimate=function(){if(this.alpha_){var t=1-Math.pow(this.alpha_,this.totalWeight_);if(t)return this.estimate_/t}return this.estimate_},t}(),ne=function(){function t(t,e,r){this.defaultEstimate_=void 0,this.minWeight_=void 0,this.minDelayMs_=void 0,this.slow_=void 0,this.fast_=void 0,this.defaultEstimate_=r,this.minWeight_=.001,this.minDelayMs_=50,this.slow_=new ie(t),this.fast_=new ie(e)}var e=t.prototype;return e.update=function(t,e){var r=this.slow_,i=this.fast_;this.slow_.halfLife!==t&&(this.slow_=new ie(t,r.getEstimate(),r.getTotalWeight())),this.fast_.halfLife!==e&&(this.fast_=new ie(e,i.getEstimate(),i.getTotalWeight()))},e.sample=function(t,e){var r=(t=Math.max(t,this.minDelayMs_))/1e3,i=8*e/r;this.fast_.sample(r,i),this.slow_.sample(r,i)},e.canEstimate=function(){var t=this.fast_;return t&&t.getTotalWeight()>=this.minWeight_},e.getEstimate=function(){return this.canEstimate()?Math.min(this.fast_.getEstimate(),this.slow_.getEstimate()):this.defaultEstimate_},e.destroy=function(){},t}();function ae(t,e){for(var r=0;r=2*h/c||y<=b)){var E,S=Number.POSITIVE_INFINITY;for(E=t.level-1;E>g;E--){if((S=h*f[E].maxBitrate/(6.4*m))=y)){var L=this.bwEstimator.getEstimate();o.b.warn("Fragment "+t.sn+(e?" part "+e.index:"")+" of level "+t.level+" is loading too slowly and will cause an underbuffer; aborting and switching to level "+E+"\n Current BW estimate: "+(Object(n.a)(L)?(L/1024).toFixed(3):"Unknown")+" Kb/s\n Estimated load time for current fragment: "+y.toFixed(3)+" s\n Estimated load time for the next fragment: "+S.toFixed(3)+" s\n Time to underbuffer: "+b.toFixed(3)+" s"),r.nextLoadLevel=E,this.bwEstimator.sample(d,u.loaded),this.clearTimer(),t.loader&&(this.fragCurrent=this.partCurrent=null,t.loader.abort()),r.trigger(a.a.FRAG_LOAD_EMERGENCY_ABORTED,{frag:t,part:e,stats:u})}}}}}},l.onFragLoaded=function(t,e){var r=e.frag,i=e.part;if(r.type===k.b.MAIN&&Object(n.a)(r.sn)){var s=i?i.stats:r.stats,o=i?i.duration:r.duration;if(this.clearTimer(),this.lastLoadedFragLevel=r.level,this._nextAutoLevel=-1,this.hls.config.abrMaxWithRealBitrate){var l=this.hls.levels[r.level],u=(l.loaded?l.loaded.bytes:0)+s.loaded,h=(l.loaded?l.loaded.duration:0)+o;l.loaded={bytes:u,duration:h},l.realBitrate=Math.round(8*u/h)}if(r.bitrateTest){var d={stats:s,frag:r,part:i,id:r.type};this.onFragBuffered(a.a.FRAG_BUFFERED,d),r.bitrateTest=!1}}},l.onFragBuffered=function(t,e){var r=e.frag,i=e.part,n=i?i.stats:r.stats;if(!n.aborted&&r.type===k.b.MAIN&&"initSegment"!==r.sn){var a=n.parsing.end-n.loading.start;this.bwEstimator.sample(a,n.loaded),n.bwEstimate=this.bwEstimator.getEstimate(),r.bitrateTest?this.bitrateTestDelay=a/1e3:this.bitrateTestDelay=0}},l.onError=function(t,e){switch(e.details){case s.a.FRAG_LOAD_ERROR:case s.a.FRAG_LOAD_TIMEOUT:this.clearTimer()}},l.clearTimer=function(){self.clearInterval(this.timer),this.timer=void 0},l.getNextABRAutoLevel=function(){var t=this.fragCurrent,e=this.partCurrent,r=this.hls,i=r.maxAutoLevel,n=r.config,a=r.minAutoLevel,s=r.media,l=e?e.duration:t?t.duration:0,u=s?s.currentTime:0,h=s&&0!==s.playbackRate?Math.abs(s.playbackRate):1,d=this.bwEstimator?this.bwEstimator.getEstimate():n.abrEwmaDefaultEstimate,c=(lt.bufferInfo(s,u,n.maxBufferHole).end-u)/h,f=this.findBestLevel(d,a,i,c,n.abrBandWidthFactor,n.abrBandWidthUpFactor);if(f>=0)return f;o.b.trace((c?"rebuffering expected":"buffer is empty")+", finding optimal quality level");var g=l?Math.min(l,n.maxStarvationDelay):n.maxStarvationDelay,v=n.abrBandWidthFactor,p=n.abrBandWidthUpFactor;if(!c){var m=this.bitrateTestDelay;if(m)g=(l?Math.min(l,n.maxLoadingDelay):n.maxLoadingDelay)-m,o.b.trace("bitrate test took "+Math.round(1e3*m)+"ms, set first fragment max fetchDuration to "+Math.round(1e3*g)+" ms"),v=p=1}return f=this.findBestLevel(d,a,i,c+g,v,p),Math.max(f,0)},l.findBestLevel=function(t,e,r,i,n,a){for(var s,l=this.fragCurrent,u=this.partCurrent,h=this.lastLoadedFragLevel,d=this.hls.levels,c=d[h],f=!(null==c||null===(s=c.details)||void 0===s||!s.live),g=null==c?void 0:c.codecSet,v=u?u.duration:l?l.duration:0,p=r;p>=e;p--){var m=d[p];if(m&&(!g||m.codecSet===g)){var y=m.details,T=(u?null==y?void 0:y.partTarget:null==y?void 0:y.averagetargetduration)||v,b=void 0;b=p<=h?n*t:a*t;var E=d[p].maxBitrate,S=E*T/b;if(o.b.trace("level/adjustedbw/bitrate/avgDuration/maxFetchDuration/fetchDuration: "+p+"/"+Math.round(b)+"/"+E+"/"+T+"/"+i+"/"+S),b>E&&(!S||f&&!this.bitrateTestDelay||S0&&-1===t?(this.log("Override startPosition with lastCurrentTime @"+e.toFixed(3)),this.state=xt):(this.loadedmetadata=!1,this.state=Nt),this.nextLoadPosition=this.startPosition=this.lastCurrentTime=t,this.tick()},l.doTick=function(){switch(this.state){case xt:this.doTickIdle();break;case Nt:var e,r=this.levels,i=this.trackId,n=null==r||null===(e=r[i])||void 0===e?void 0:e.details;if(n){if(this.waitForCdnTuneIn(n))break;this.state=Ht}break;case Ft:var a,s=performance.now(),l=this.retryDate;(!l||s>=l||null!==(a=this.media)&&void 0!==a&&a.seeking)&&(this.log("RetryDate reached, switch back to IDLE state"),this.state=xt);break;case Ht:var u=this.waitingData;if(u){var h=u.frag,d=u.part,c=u.cache,f=u.complete;if(void 0!==this.initPTS[h.cc]){this.waitingData=null,this.waitingVideoCC=-1,this.state=Mt;var g={frag:h,part:d,payload:c.flush(),networkDetails:null};this._handleFragmentLoadProgress(g),f&&t.prototype._handleFragmentLoadComplete.call(this,g)}else if(this.videoTrackCC!==this.waitingVideoCC)o.b.log("Waiting fragment cc ("+h.cc+") cancelled because video is at cc "+this.videoTrackCC),this.clearWaitingFragment();else{var v=this.getLoadPosition(),p=lt.bufferInfo(this.mediaBuffer,v,this.config.maxBufferHole);mt(p.end,this.config.maxFragLookUpTolerance,h)<0&&(o.b.log("Waiting fragment cc ("+h.cc+") @ "+h.start+" cancelled because another fragment at "+p.end+" is needed"),this.clearWaitingFragment())}}else this.state=xt}this.onTickEnd()},l.clearWaitingFragment=function(){var t=this.waitingData;t&&(this.fragmentTracker.removeFragment(t.frag),this.waitingData=null,this.waitingVideoCC=-1,this.state=xt)},l.onTickEnd=function(){var t=this.media;if(t&&t.readyState){var e=(this.mediaBuffer?this.mediaBuffer:t).buffered;!this.loadedmetadata&&e.length&&(this.loadedmetadata=!0),this.lastCurrentTime=t.currentTime}},l.doTickIdle=function(){var t,e,r=this.hls,i=this.levels,n=this.media,s=this.trackId,o=r.config;if(i&&i[s]&&(n||!this.startFragRequested&&o.startFragPrefetch)){var l=i[s].details;if(!l||l.live&&this.levelLastLoaded!==s||this.waitForCdnTuneIn(l))this.state=Nt;else{this.bufferFlushed&&(this.bufferFlushed=!1,this.afterBufferFlushed(this.mediaBuffer?this.mediaBuffer:this.media,u.a.AUDIO,k.b.AUDIO));var h=this.getFwdBufferInfo(this.mediaBuffer?this.mediaBuffer:this.media,k.b.AUDIO);if(null!==h){var d=h.len,c=this.getMaxBufferLength(),f=this.audioSwitch;if(!(d>=c)||f){if(!f&&this._streamEnded(h,l))return r.trigger(a.a.BUFFER_EOS,{type:"audio"}),void(this.state=Kt);var g=l.fragments[0].start,v=h.end;if(f){var p=this.getLoadPosition();v=p,l.PTSKnown&&pg||h.nextStart)&&(this.log("Alt audio track ahead of main track, seek to start of alt audio track"),n.currentTime=g+.05)}var m=this.getNextFragment(v,l);m?"identity"!==(null===(t=m.decryptdata)||void 0===t?void 0:t.keyFormat)||null!==(e=m.decryptdata)&&void 0!==e&&e.key?this.loadFragment(m,l,v):this.loadKey(m,l):this.bufferFlushed=!0}}}}},l.getMaxBufferLength=function(){var e=t.prototype.getMaxBufferLength.call(this),r=this.getFwdBufferInfo(this.videoBuffer?this.videoBuffer:this.media,k.b.MAIN);return null===r?e:Math.max(e,r.len)},l.onMediaDetaching=function(){this.videoBuffer=null,t.prototype.onMediaDetaching.call(this)},l.onAudioTracksUpdated=function(t,e){var r=e.audioTracks;this.resetTransmuxer(),this.levels=r.map((function(t){return new j(t)}))},l.onAudioTrackSwitching=function(t,e){var r=!!e.url;this.trackId=e.id;var i=this.fragCurrent;null!=i&&i.loader&&i.loader.abort(),this.fragCurrent=null,this.clearWaitingFragment(),r?this.setInterval(100):this.resetTransmuxer(),r?(this.audioSwitch=!0,this.state=xt):this.state=Ot,this.tick()},l.onManifestLoading=function(){this.mainDetails=null,this.fragmentTracker.removeAllFragments(),this.startPosition=this.lastCurrentTime=0,this.bufferFlushed=!1},l.onLevelLoaded=function(t,e){this.mainDetails=e.details},l.onAudioTrackLoaded=function(t,e){var r,i=this.levels,n=e.details,a=e.id;if(i){this.log("Track "+a+" loaded ["+n.startSN+","+n.endSN+"],duration:"+n.totalduration);var s=i[a],o=0;if(n.live||null!==(r=s.details)&&void 0!==r&&r.live){var l=this.mainDetails;if(n.fragments[0]||(n.deltaUpdateFailed=!0),n.deltaUpdateFailed||!l)return;!s.details&&n.hasProgramDateTime&&l.hasProgramDateTime?(gt(n,l),o=n.fragments[0].start):o=this.alignPlaylists(n,s.details)}s.details=n,this.levelLastLoaded=a,this.startFragRequested||!this.mainDetails&&n.live||this.setStartPosition(s.details,o),this.state!==Nt||this.waitForCdnTuneIn(n)||(this.state=xt),this.tick()}else this.warn("Audio tracks were reset while loading level "+a)},l._handleFragmentLoadProgress=function(t){var e,r=t.frag,i=t.part,n=t.payload,a=this.config,s=this.trackId,l=this.levels;if(l){var u=l[s],h=u.details,d=a.defaultAudioCodec||u.audioCodec||"mp4a.40.2",c=this.transmuxer;c||(c=this.transmuxer=new Jt(this.hls,k.b.AUDIO,this._handleTransmuxComplete.bind(this),this._handleTransmuxerFlush.bind(this)));var f=this.initPTS[r.cc],g=null===(e=r.initSegment)||void 0===e?void 0:e.data;if(void 0!==f){var v=i?i.index:-1,p=-1!==v,m=new ut(r.level,r.sn,r.stats.chunkCount,n.byteLength,v,p);c.push(n,g,d,"",r,i,h.totalduration,!1,m,f)}else{o.b.log("Unknown video PTS for cc "+r.cc+", waiting for video PTS before demuxing audio frag "+r.sn+" of ["+h.startSN+" ,"+h.endSN+"],track "+s),(this.waitingData=this.waitingData||{frag:r,part:i,cache:new oe.a,complete:!1}).cache.push(new Uint8Array(n)),this.waitingVideoCC=this.videoTrackCC,this.state=Ht}}else this.warn("Audio tracks were reset while fragment load was in progress. Fragment "+r.sn+" of level "+r.level+" will not be buffered")},l._handleFragmentLoadComplete=function(e){this.waitingData?this.waitingData.complete=!0:t.prototype._handleFragmentLoadComplete.call(this,e)},l.onBufferReset=function(){this.mediaBuffer=this.videoBuffer=null,this.loadedmetadata=!1},l.onBufferCreated=function(t,e){var r=e.tracks.audio;r&&(this.mediaBuffer=r.buffer),e.tracks.video&&(this.videoBuffer=e.tracks.video.buffer)},l.onFragBuffered=function(t,e){var r=e.frag,i=e.part;r.type===k.b.AUDIO&&(this.fragContextChanged(r)?this.warn("Fragment "+r.sn+(i?" p: "+i.index:"")+" of level "+r.level+" finished buffering, but was aborted. state: "+this.state+", audioSwitch: "+this.audioSwitch):("initSegment"!==r.sn&&(this.fragPrevious=r,this.audioSwitch&&(this.audioSwitch=!1,this.hls.trigger(a.a.AUDIO_TRACK_SWITCHED,{id:this.trackId}))),this.fragBufferedComplete(r,i)))},l.onError=function(e,r){switch(r.details){case s.a.FRAG_LOAD_ERROR:case s.a.FRAG_LOAD_TIMEOUT:case s.a.KEY_LOAD_ERROR:case s.a.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(k.b.AUDIO,r);break;case s.a.AUDIO_TRACK_LOAD_ERROR:case s.a.AUDIO_TRACK_LOAD_TIMEOUT:this.state!==jt&&this.state!==Ot&&(this.state=r.fatal?jt:xt,this.warn(r.details+" while loading frag, switching to "+this.state+" state"));break;case s.a.BUFFER_FULL_ERROR:if("audio"===r.parent&&(this.state===Ut||this.state===Bt)){var i=!0,n=this.getFwdBufferInfo(this.mediaBuffer,k.b.AUDIO);n&&n.len>.5&&(i=!this.reduceMaxBufferLength(n.len)),i&&(this.warn("Buffer full error also media.currentTime is not buffered, flush audio buffer"),this.fragCurrent=null,t.prototype.flushMainBuffer.call(this,0,Number.POSITIVE_INFINITY,"audio")),this.resetLoadingState()}}},l.onBufferFlushed=function(t,e){e.type===u.a.AUDIO&&(this.bufferFlushed=!0)},l._handleTransmuxComplete=function(t){var e,r="audio",i=this.hls,n=t.remuxResult,s=t.chunkMeta,o=this.getCurrentContext(s);if(!o)return this.warn("The loading context changed while buffering fragment "+s.sn+" of level "+s.level+". This chunk will not be buffered."),void this.resetLiveStartWhenNotLoaded(s.level);var l=o.frag,h=o.part,d=n.audio,c=n.text,f=n.id3,g=n.initSegment;if(!this.fragContextChanged(l)){if(this.state=Ut,this.audioSwitch&&d&&this.completeAudioSwitch(),null!=g&&g.tracks&&(this._bufferInitSegment(g.tracks,l,s),i.trigger(a.a.FRAG_PARSING_INIT_SEGMENT,{frag:l,id:r,tracks:g.tracks})),d){var v=d.startPTS,p=d.endPTS,m=d.startDTS,y=d.endDTS;h&&(h.elementaryStreams[u.a.AUDIO]={startPTS:v,endPTS:p,startDTS:m,endDTS:y}),l.setElementaryStreamInfo(u.a.AUDIO,v,p,m,y),this.bufferFragmentData(d,l,h,s)}if(null!=f&&null!==(e=f.samples)&&void 0!==e&&e.length){var T=le({frag:l,id:r},f);i.trigger(a.a.FRAG_PARSING_METADATA,T)}if(c){var b=le({frag:l,id:r},c);i.trigger(a.a.FRAG_PARSING_USERDATA,b)}}},l._bufferInitSegment=function(t,e,r){if(this.state===Ut){t.video&&delete t.video;var i=t.audio;if(i){i.levelCodec=i.codec,i.id="audio",this.log("Init audio buffer, container:"+i.container+", codecs[parsed]=["+i.codec+"]"),this.hls.trigger(a.a.BUFFER_CODECS,t);var n=i.initSegment;if(null!=n&&n.byteLength){var s={type:"audio",frag:e,part:null,chunkMeta:r,parent:e.type,data:n};this.hls.trigger(a.a.BUFFER_APPENDING,s)}this.tick()}}},l.loadFragment=function(e,r,i){var a=this.fragmentTracker.getState(e);this.fragCurrent=e,(this.audioSwitch||a===tt.NOT_LOADED||a===tt.PARTIAL)&&("initSegment"===e.sn?this._loadInitSegment(e):r.live&&!Object(n.a)(this.initPTS[e.cc])?(this.log("Waiting for video PTS in continuity counter "+e.cc+" of live stream before loading audio fragment "+e.sn+" of level "+this.trackId),this.state=Ht):(this.startFragRequested=!0,t.prototype.loadFragment.call(this,e,r,i)))},l.completeAudioSwitch=function(){var e=this.hls,r=this.media,i=this.trackId;r&&(this.log("Switching audio track : flushing all audio"),t.prototype.flushMainBuffer.call(this,0,Number.POSITIVE_INFINITY,"audio")),this.audioSwitch=!1,e.trigger(a.a.AUDIO_TRACK_SWITCHED,{id:i})},i}(Wt);function de(t,e){for(var r=0;r=e.length)this.warn("Invalid id passed to audio-track controller");else{this.clearTimer();var r=e[this.trackId];this.log("Now switching to audio-track index "+t);var i=e[t],n=i.id,s=i.groupId,o=void 0===s?"":s,l=i.name,u=i.type,h=i.url;if(this.trackId=t,this.trackName=l,this.selectDefaultTrack=!1,this.hls.trigger(a.a.AUDIO_TRACK_SWITCHING,{id:n,groupId:o,name:l,type:u,url:h}),!i.details||i.details.live){var d=this.switchParams(i.url,null==r?void 0:r.details);this.loadPlaylist(d)}}},u.selectInitialTrack=function(){this.tracksInGroup;var t=this.trackName,e=this.findTrackId(t)||this.findTrackId();-1!==e?this.setAudioTrack(e):(this.warn("No track found for running audio group-ID: "+this.groupId),this.hls.trigger(a.a.ERROR,{type:s.b.MEDIA_ERROR,details:s.a.AUDIO_TRACK_LOAD_ERROR,fatal:!0}))},u.findTrackId=function(t){for(var e=this.tracksInGroup,r=0;r=n[o].start&&s<=n[o].end){a=n[o];break}var l=r.start+r.duration;a?a.end=l:(a={start:s,end:l},n.push(a)),this.fragmentTracker.fragBuffered(r)}}},l.onBufferFlushing=function(t,e){var r=e.startOffset,i=e.endOffset;if(0===r&&i!==Number.POSITIVE_INFINITY){var n=this.currentTrackId,a=this.levels;if(!a.length||!a[n]||!a[n].details)return;var s=i-a[n].details.targetduration;if(s<=0)return;e.endOffsetSubtitles=Math.max(0,s),this.tracksBuffered.forEach((function(t){for(var e=0;e=s.length||n!==a)&&o){if(this.mediaBuffer=this.mediaBufferTimeRanges,i.live||null!==(r=o.details)&&void 0!==r&&r.live){var l=this.mainDetails;if(i.deltaUpdateFailed||!l)return;var u=l.fragments[0];if(o.details)0===this.alignPlaylists(i,o.details)&&u&&z(i,u.start);else i.hasProgramDateTime&&l.hasProgramDateTime?gt(i,l):u&&z(i,u.start)}if(o.details=i,this.levelLastLoaded=n,this.tick(),i.live&&!this.fragCurrent&&this.media&&this.state===xt)pt(null,i.fragments,this.media.currentTime,0)||(this.warn("Subtitle playlist not aligned with playback"),o.details=void 0)}}},l._handleFragmentLoadComplete=function(t){var e=t.frag,r=t.payload,i=e.decryptdata,n=this.hls;if(!this.fragContextChanged(e)&&r&&r.byteLength>0&&i&&i.key&&i.iv&&"AES-128"===i.method){var s=performance.now();this.decrypter.webCryptoDecrypt(new Uint8Array(r),i.key.buffer,i.iv.buffer).then((function(t){var r=performance.now();n.trigger(a.a.FRAG_DECRYPTED,{frag:e,payload:t,stats:{tstart:s,tdecrypt:r}})}))}},l.doTick=function(){if(this.media){if(this.state===xt){var t,e=this.currentTrackId,r=this.levels;if(!r.length||!r[e]||!r[e].details)return;var i=r[e].details,n=i.targetduration,a=this.config,s=this.media,o=lt.bufferedInfo(this.mediaBufferTimeRanges,s.currentTime-n,a.maxBufferHole),l=o.end;if(o.len>this.getMaxBufferLength()+n)return;var u,h=i.fragments,d=h.length,c=i.edge,f=this.fragPrevious;if(l-1&&(this.subtitleTrack=this.queuedDefaultTrack,this.queuedDefaultTrack=-1),this.useTextTrackPolling=!(this.media.textTracks&&"onchange"in this.media.textTracks),this.useTextTrackPolling?this.pollTrackChange(500):this.media.textTracks.addEventListener("change",this.asyncPollTrackChange))},l.pollTrackChange=function(t){self.clearInterval(this.subtitlePollingInterval),this.subtitlePollingInterval=self.setInterval(this.trackChangeListener,t)},l.onMediaDetaching=function(){this.media&&(self.clearInterval(this.subtitlePollingInterval),this.useTextTrackPolling||this.media.textTracks.removeEventListener("change",this.asyncPollTrackChange),this.trackId>-1&&(this.queuedDefaultTrack=this.trackId),Te(this.media.textTracks).forEach((function(t){x(t)})),this.subtitleTrack=-1,this.media=null)},l.onManifestLoading=function(){this.tracks=[],this.groupId=null,this.tracksInGroup=[],this.trackId=-1,this.selectDefaultTrack=!0},l.onManifestParsed=function(t,e){this.tracks=e.subtitleTracks},l.onSubtitleTrackLoaded=function(t,e){var r=e.id,i=e.details,n=this.trackId,a=this.tracksInGroup[n];if(a){var s=a.details;a.details=e.details,this.log("subtitle track "+r+" loaded ["+i.startSN+"-"+i.endSN+"]"),r===this.trackId&&(this.retryCount=0,this.playlistLoaded(r,e,s))}else this.warn("Invalid subtitle track id "+r)},l.onLevelLoading=function(t,e){this.switchLevel(e.level)},l.onLevelSwitching=function(t,e){this.switchLevel(e.level)},l.switchLevel=function(t){var e=this.hls.levels[t];if(null!=e&&e.textGroupIds){var r=e.textGroupIds[e.urlId];if(this.groupId!==r){var i=this.tracksInGroup?this.tracksInGroup[this.trackId]:void 0,n=this.tracks.filter((function(t){return!r||t.groupId===r}));this.tracksInGroup=n;var s=this.findTrackId(null==i?void 0:i.name)||this.findTrackId();this.groupId=r;var o={subtitleTracks:n};this.log("Updating subtitle tracks, "+n.length+' track(s) found in "'+r+'" group-id'),this.hls.trigger(a.a.SUBTITLE_TRACKS_UPDATED,o),-1!==s&&this.setSubtitleTrack(s,i)}}},l.findTrackId=function(t){for(var e=this.tracksInGroup,r=0;r=i.length)){this.clearTimer();var n=i[t];if(this.log("Switching to subtitle track "+t),this.trackId=t,n){var s=n.id,o=n.groupId,l=void 0===o?"":o,u=n.name,h=n.type,d=n.url;this.hls.trigger(a.a.SUBTITLE_TRACK_SWITCH,{id:s,groupId:l,name:u,type:h,url:d});var c=this.switchParams(n.url,null==e?void 0:e.details);this.loadPlaylist(c)}else this.hls.trigger(a.a.SUBTITLE_TRACK_SWITCH,{id:t})}}else this.queuedDefaultTrack=t},l.onTextTracksChanged=function(){if(this.useTextTrackPolling||self.clearInterval(this.subtitlePollingInterval),this.media&&this.hls.config.renderTextTracksNatively){for(var t=-1,e=Te(this.media.textTracks),r=0;r0||Object.keys(this.pendingTracks).length>0},e.destroy=function(){this.unregisterListeners(),this.details=null},e.registerListeners=function(){var t=this.hls;t.on(a.a.MEDIA_ATTACHING,this.onMediaAttaching,this),t.on(a.a.MEDIA_DETACHING,this.onMediaDetaching,this),t.on(a.a.MANIFEST_PARSED,this.onManifestParsed,this),t.on(a.a.BUFFER_RESET,this.onBufferReset,this),t.on(a.a.BUFFER_APPENDING,this.onBufferAppending,this),t.on(a.a.BUFFER_CODECS,this.onBufferCodecs,this),t.on(a.a.BUFFER_EOS,this.onBufferEos,this),t.on(a.a.BUFFER_FLUSHING,this.onBufferFlushing,this),t.on(a.a.LEVEL_UPDATED,this.onLevelUpdated,this),t.on(a.a.FRAG_PARSED,this.onFragParsed,this),t.on(a.a.FRAG_CHANGED,this.onFragChanged,this)},e.unregisterListeners=function(){var t=this.hls;t.off(a.a.MEDIA_ATTACHING,this.onMediaAttaching,this),t.off(a.a.MEDIA_DETACHING,this.onMediaDetaching,this),t.off(a.a.MANIFEST_PARSED,this.onManifestParsed,this),t.off(a.a.BUFFER_RESET,this.onBufferReset,this),t.off(a.a.BUFFER_APPENDING,this.onBufferAppending,this),t.off(a.a.BUFFER_CODECS,this.onBufferCodecs,this),t.off(a.a.BUFFER_EOS,this.onBufferEos,this),t.off(a.a.BUFFER_FLUSHING,this.onBufferFlushing,this),t.off(a.a.LEVEL_UPDATED,this.onLevelUpdated,this),t.off(a.a.FRAG_PARSED,this.onFragParsed,this),t.off(a.a.FRAG_CHANGED,this.onFragChanged,this)},e._initSourceBuffer=function(){this.sourceBuffer={},this.operationQueue=new Se(this.sourceBuffer),this.listeners={audio:[],video:[],audiovideo:[]}},e.onManifestParsed=function(t,e){var r=2;(e.audio&&!e.video||!e.altAudio)&&(r=1),this.bufferCodecEventsExpected=this._bufferCodecEventsTotal=r,this.details=null,o.b.log(this.bufferCodecEventsExpected+" bufferCodec event(s) expected")},e.onMediaAttaching=function(t,e){var r=this.media=e.media;if(r&&Le){var i=this.mediaSource=new Le;i.addEventListener("sourceopen",this._onMediaSourceOpen),i.addEventListener("sourceended",this._onMediaSourceEnded),i.addEventListener("sourceclose",this._onMediaSourceClose),r.src=self.URL.createObjectURL(i),this._objectUrl=r.src}},e.onMediaDetaching=function(){var t=this.media,e=this.mediaSource,r=this._objectUrl;if(e){if(o.b.log("[buffer-controller]: media source detaching"),"open"===e.readyState)try{e.endOfStream()}catch(t){o.b.warn("[buffer-controller]: onMediaDetaching: "+t.message+" while calling endOfStream")}this.onBufferReset(),e.removeEventListener("sourceopen",this._onMediaSourceOpen),e.removeEventListener("sourceended",this._onMediaSourceEnded),e.removeEventListener("sourceclose",this._onMediaSourceClose),t&&(r&&self.URL.revokeObjectURL(r),t.src===r?(t.removeAttribute("src"),t.load()):o.b.warn("[buffer-controller]: media.src was changed by a third party - skip cleanup")),this.mediaSource=null,this.media=null,this._objectUrl=null,this.bufferCodecEventsExpected=this._bufferCodecEventsTotal,this.pendingTracks={},this.tracks={}}this.hls.trigger(a.a.MEDIA_DETACHED,void 0)},e.onBufferReset=function(){var t=this;this.getSourceBufferTypes().forEach((function(e){var r=t.sourceBuffer[e];try{r&&(t.removeBufferListeners(e),t.mediaSource&&t.mediaSource.removeSourceBuffer(r),t.sourceBuffer[e]=void 0)}catch(t){o.b.warn("[buffer-controller]: Failed to reset the "+e+" buffer",t)}})),this._initSourceBuffer()},e.onBufferCodecs=function(t,e){var r=this,i=this.getSourceBufferTypes().length;Object.keys(e).forEach((function(t){if(i){var n=r.tracks[t];if(n&&"function"==typeof n.buffer.changeType){var a=e[t],s=a.codec,o=a.levelCodec,l=a.container;if((n.levelCodec||n.codec).replace(Ae,"$1")!==(o||s).replace(Ae,"$1")){var u=l+";codecs="+(o||s);r.appendChangeType(t,u)}}}else r.pendingTracks[t]=e[t]})),i||(this.bufferCodecEventsExpected=Math.max(this.bufferCodecEventsExpected-1,0),this.mediaSource&&"open"===this.mediaSource.readyState&&this.checkPendingTracks())},e.appendChangeType=function(t,e){var r=this,i=this.operationQueue,n={execute:function(){var n=r.sourceBuffer[t];n&&(o.b.log("[buffer-controller]: changing "+t+" sourceBuffer type to "+e),n.changeType(e)),i.shiftAndExecuteNext(t)},onStart:function(){},onComplete:function(){},onError:function(e){o.b.warn("[buffer-controller]: Failed to change "+t+" SourceBuffer type",e)}};i.append(n,t)},e.onBufferAppending=function(t,e){var r=this,i=this.hls,n=this.operationQueue,l=this.tracks,u=e.data,h=e.type,d=e.frag,c=e.part,f=e.chunkMeta,g=f.buffering[h],v=self.performance.now();g.start=v;var p=d.stats.buffering,m=c?c.stats.buffering:null;0===p.start&&(p.start=v),m&&0===m.start&&(m.start=v);var y=l.audio,T="audio"===h&&1===f.id&&"audio/mpeg"===(null==y?void 0:y.container),b={execute:function(){if(g.executeStart=self.performance.now(),T){var t=r.sourceBuffer[h];if(t){var e=d.start-t.timestampOffset;Math.abs(e)>=.1&&(o.b.log("[buffer-controller]: Updating audio SourceBuffer timestampOffset to "+d.start+" (delta: "+e+") sn: "+d.sn+")"),t.timestampOffset=d.start)}}r.appendExecutor(u,h)},onStart:function(){},onComplete:function(){var t=self.performance.now();g.executeEnd=g.end=t,0===p.first&&(p.first=t),m&&0===m.first&&(m.first=t);var e=r.sourceBuffer,i={};for(var n in e)i[n]=lt.getBuffered(e[n]);r.appendError=0,r.hls.trigger(a.a.BUFFER_APPENDED,{type:h,frag:d,part:c,chunkMeta:f,parent:d.type,timeRanges:i})},onError:function(t){o.b.error("[buffer-controller]: Error encountered while trying to append to the "+h+" SourceBuffer",t);var e={type:s.b.MEDIA_ERROR,parent:d.type,details:s.a.BUFFER_APPEND_ERROR,err:t,fatal:!1};t.code===DOMException.QUOTA_EXCEEDED_ERR?e.details=s.a.BUFFER_FULL_ERROR:(r.appendError++,e.details=s.a.BUFFER_APPEND_ERROR,r.appendError>i.config.appendErrorMaxRetry&&(o.b.error("[buffer-controller]: Failed "+i.config.appendErrorMaxRetry+" times to append segment in sourceBuffer"),e.fatal=!0)),i.trigger(a.a.ERROR,e)}};n.append(b,h)},e.onBufferFlushing=function(t,e){var r=this,i=this.operationQueue,n=function(t){return{execute:r.removeExecutor.bind(r,t,e.startOffset,e.endOffset),onStart:function(){},onComplete:function(){r.hls.trigger(a.a.BUFFER_FLUSHED,{type:t})},onError:function(e){o.b.warn("[buffer-controller]: Failed to remove from "+t+" SourceBuffer",e)}}};e.type?i.append(n(e.type),e.type):this.getSourceBufferTypes().forEach((function(t){i.append(n(t),t)}))},e.onFragParsed=function(t,e){var r=this,i=e.frag,n=e.part,s=[],l=n?n.elementaryStreams:i.elementaryStreams;l[u.a.AUDIOVIDEO]?s.push("audiovideo"):(l[u.a.AUDIO]&&s.push("audio"),l[u.a.VIDEO]&&s.push("video"));0===s.length&&o.b.warn("Fragments must have at least one ElementaryStreamType set. type: "+i.type+" level: "+i.level+" sn: "+i.sn),this.blockBuffers((function(){var t=self.performance.now();i.stats.buffering.end=t,n&&(n.stats.buffering.end=t);var e=n?n.stats:i.stats;r.hls.trigger(a.a.FRAG_BUFFERED,{frag:i,part:n,stats:e,id:i.type})}),s)},e.onFragChanged=function(t,e){this.flushBackBuffer()},e.onBufferEos=function(t,e){var r=this;this.getSourceBufferTypes().reduce((function(t,i){var n=r.sourceBuffer[i];return e.type&&e.type!==i||n&&!n.ended&&(n.ended=!0,o.b.log("[buffer-controller]: "+i+" sourceBuffer now EOS")),t&&!(n&&!n.ended)}),!0)&&this.blockBuffers((function(){var t=r.mediaSource;t&&"open"===t.readyState&&t.endOfStream()}))},e.onLevelUpdated=function(t,e){var r=e.details;r.fragments.length&&(this.details=r,this.getSourceBufferTypes().length?this.blockBuffers(this.updateMediaElementDuration.bind(this)):this.updateMediaElementDuration())},e.flushBackBuffer=function(){var t=this.hls,e=this.details,r=this.media,i=this.sourceBuffer;if(r&&null!==e){var s=this.getSourceBufferTypes();if(s.length){var o=e.live&&null!==t.config.liveBackBufferLength?t.config.liveBackBufferLength:t.config.backBufferLength;if(Object(n.a)(o)&&!(o<0)){var l=r.currentTime,u=e.levelTargetDuration,h=Math.max(o,u),d=Math.floor(l/u)*u-h;s.forEach((function(r){var n=i[r];if(n){var s=lt.getBuffered(n);s.length>0&&d>s.start(0)&&(t.trigger(a.a.BACK_BUFFER_REACHED,{bufferEnd:d}),e.live&&t.trigger(a.a.LIVE_BACK_BUFFER_REACHED,{bufferEnd:d}),t.trigger(a.a.BUFFER_FLUSHING,{startOffset:0,endOffset:d,type:r}))}}))}}}},e.updateMediaElementDuration=function(){if(this.details&&this.media&&this.mediaSource&&"open"===this.mediaSource.readyState){var t=this.details,e=this.hls,r=this.media,i=this.mediaSource,a=t.fragments[0].start+t.totalduration,s=r.duration,l=Object(n.a)(i.duration)?i.duration:0;t.live&&e.config.liveDurationInfinity?(o.b.log("[buffer-controller]: Media Source duration is set to Infinity"),i.duration=1/0,this.updateSeekableRange(t)):(a>l&&a>s||!Object(n.a)(s))&&(o.b.log("[buffer-controller]: Updating Media Source duration to "+a.toFixed(3)),i.duration=a)}},e.updateSeekableRange=function(t){var e=this.mediaSource,r=t.fragments;if(r.length&&t.live&&null!=e&&e.setLiveSeekableRange){var i=Math.max(0,r[0].start),n=Math.max(i,i+t.totalduration);e.setLiveSeekableRange(i,n)}},e.checkPendingTracks=function(){var t=this.bufferCodecEventsExpected,e=this.operationQueue,r=this.pendingTracks,i=Object.keys(r).length;if(i&&!t||2===i){this.createSourceBuffers(r),this.pendingTracks={};var n=this.getSourceBufferTypes();if(0===n.length)return void this.hls.trigger(a.a.ERROR,{type:s.b.MEDIA_ERROR,details:s.a.BUFFER_INCOMPATIBLE_CODECS_ERROR,fatal:!0,reason:"could not create source buffer for media codec(s)"});n.forEach((function(t){e.executeNext(t)}))}},e.createSourceBuffers=function(t){var e=this.sourceBuffer,r=this.mediaSource;if(!r)throw Error("createSourceBuffers called when mediaSource was null");var i=0;for(var n in t)if(!e[n]){var l=t[n];if(!l)throw Error("source buffer exists for track "+n+", however track does not");var u=l.levelCodec||l.codec,h=l.container+";codecs="+u;o.b.log("[buffer-controller]: creating sourceBuffer("+h+")");try{var d=e[n]=r.addSourceBuffer(h),c=n;this.addBufferListener(c,"updatestart",this._onSBUpdateStart),this.addBufferListener(c,"updateend",this._onSBUpdateEnd),this.addBufferListener(c,"error",this._onSBUpdateError),this.tracks[n]={buffer:d,codec:u,container:l.container,levelCodec:l.levelCodec,id:l.id},i++}catch(t){o.b.error("[buffer-controller]: error while trying to add sourceBuffer: "+t.message),this.hls.trigger(a.a.ERROR,{type:s.b.MEDIA_ERROR,details:s.a.BUFFER_ADD_CODEC_ERROR,fatal:!1,error:t,mimeType:h})}}i&&this.hls.trigger(a.a.BUFFER_CREATED,{tracks:this.tracks})},e._onSBUpdateStart=function(t){this.operationQueue.current(t).onStart()},e._onSBUpdateEnd=function(t){var e=this.operationQueue;e.current(t).onComplete(),e.shiftAndExecuteNext(t)},e._onSBUpdateError=function(t,e){o.b.error("[buffer-controller]: "+t+" SourceBuffer error",e),this.hls.trigger(a.a.ERROR,{type:s.b.MEDIA_ERROR,details:s.a.BUFFER_APPENDING_ERROR,fatal:!1});var r=this.operationQueue.current(t);r&&r.onError(e)},e.removeExecutor=function(t,e,r){var i=this.media,a=this.mediaSource,s=this.operationQueue,l=this.sourceBuffer[t];if(!i||!a||!l)return o.b.warn("[buffer-controller]: Attempting to remove from the "+t+" SourceBuffer, but it does not exist"),void s.shiftAndExecuteNext(t);var u=Object(n.a)(i.duration)?i.duration:1/0,h=Object(n.a)(a.duration)?a.duration:1/0,d=Math.max(0,e),c=Math.min(r,u,h);c>d?(o.b.log("[buffer-controller]: Removing ["+d+","+c+"] from the "+t+" SourceBuffer"),l.remove(d,c)):s.shiftAndExecuteNext(t)},e.appendExecutor=function(t,e){var r=this.operationQueue,i=this.sourceBuffer[e];if(!i)return o.b.warn("[buffer-controller]: Attempting to append to the "+e+" SourceBuffer, but it does not exist"),void r.shiftAndExecuteNext(e);i.ended=!1,i.appendBuffer(t)},e.blockBuffers=function(t,e){var r=this;if(void 0===e&&(e=this.getSourceBufferTypes()),!e.length)return o.b.log("[buffer-controller]: Blocking operation requested, but no SourceBuffers exist"),void Promise.resolve(t);var i=this.operationQueue,n=e.map((function(t){return i.appendBlocker(t)}));Promise.all(n).then((function(){t(),e.forEach((function(t){var e=r.sourceBuffer[t];e&&e.updating||i.shiftAndExecuteNext(t)}))}))},e.getSourceBufferTypes=function(){return Object.keys(this.sourceBuffer)},e.addBufferListener=function(t,e,r){var i=this.sourceBuffer[t];if(i){var n=r.bind(this,t);this.listeners[t].push({event:e,listener:n}),i.addEventListener(e,n)}},e.removeBufferListeners=function(t){var e=this.sourceBuffer[t];e&&this.listeners[t].forEach((function(t){e.removeEventListener(t.event,t.listener)}))},t}(),De={42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,128:174,129:176,130:189,131:191,132:8482,133:162,134:163,135:9834,136:224,137:32,138:232,139:226,140:234,141:238,142:244,143:251,144:193,145:201,146:211,147:218,148:220,149:252,150:8216,151:161,152:42,153:8217,154:9473,155:169,156:8480,157:8226,158:8220,159:8221,160:192,161:194,162:199,163:200,164:202,165:203,166:235,167:206,168:207,169:239,170:212,171:217,172:249,173:219,174:171,175:187,176:195,177:227,178:205,179:204,180:236,181:210,182:242,183:213,184:245,185:123,186:125,187:92,188:94,189:95,190:124,191:8764,192:196,193:228,194:214,195:246,196:223,197:165,198:164,199:9475,200:197,201:229,202:216,203:248,204:9487,205:9491,206:9495,207:9499},ke=function(t){var e=t;return De.hasOwnProperty(t)&&(e=De[t]),String.fromCharCode(e)},_e={17:1,18:3,21:5,22:7,23:9,16:11,19:12,20:14},Ie={17:2,18:4,21:6,22:8,23:10,19:13,20:15},Ce={25:1,26:3,29:5,30:7,31:9,24:11,27:12,28:14},we={25:2,26:4,29:6,30:8,31:10,27:13,28:15},Oe=["white","green","blue","cyan","red","yellow","magenta","black","transparent"];!function(t){t[t.ERROR=0]="ERROR",t[t.TEXT=1]="TEXT",t[t.WARNING=2]="WARNING",t[t.INFO=2]="INFO",t[t.DEBUG=3]="DEBUG",t[t.DATA=3]="DATA"}(be||(be={}));var xe=function(){function t(){this.time=null,this.verboseLevel=be.ERROR}return t.prototype.log=function(t,e){this.verboseLevel>=t&&o.b.log(this.time+" ["+t+"] "+e)},t}(),Pe=function(t){for(var e=[],r=0;r100&&(this.logger.log(be.DEBUG,"Too large cursor position "+this.pos),this.pos=100)},e.moveCursor=function(t){var e=this.pos+t;if(t>1)for(var r=this.pos+1;r=144&&this.backSpace();var e=ke(t);this.pos>=100?this.logger.log(be.ERROR,"Cannot insert "+t.toString(16)+" ("+e+") at position "+this.pos+". Skipping it!"):(this.chars[this.pos].setChar(e,this.currPenState),this.moveCursor(1))},e.clearFromPos=function(t){var e;for(e=t;e<100;e++)this.chars[e].reset()},e.clear=function(){this.clearFromPos(0),this.pos=0,this.currPenState.reset()},e.clearToEndOfRow=function(){this.clearFromPos(this.pos)},e.getTextString=function(){for(var t=[],e=!0,r=0;r<100;r++){var i=this.chars[r].uchar;" "!==i&&(e=!1),t.push(i)}return e?"":t.join("")},e.setPenStyles=function(t){this.currPenState.setStyles(t),this.chars[this.pos].setPenState(this.currPenState)},t}(),Ue=function(){function t(t){this.rows=void 0,this.currRow=void 0,this.nrRollUpRows=void 0,this.lastOutputScreen=void 0,this.logger=void 0,this.rows=[];for(var e=0;e<15;e++)this.rows.push(new Ne(t));this.logger=t,this.currRow=14,this.nrRollUpRows=null,this.lastOutputScreen=null,this.reset()}var e=t.prototype;return e.reset=function(){for(var t=0;t<15;t++)this.rows[t].clear();this.currRow=14},e.equals=function(t){for(var e=!0,r=0;r<15;r++)if(!this.rows[r].equals(t.rows[r])){e=!1;break}return e},e.copy=function(t){for(var e=0;e<15;e++)this.rows[e].copy(t.rows[e])},e.isEmpty=function(){for(var t=!0,e=0;e<15;e++)if(!this.rows[e].isEmpty()){t=!1;break}return t},e.backSpace=function(){this.rows[this.currRow].backSpace()},e.clearToEndOfRow=function(){this.rows[this.currRow].clearToEndOfRow()},e.insertChar=function(t){this.rows[this.currRow].insertChar(t)},e.setPen=function(t){this.rows[this.currRow].setPenStyles(t)},e.moveCursor=function(t){this.rows[this.currRow].moveCursor(t)},e.setCursor=function(t){this.logger.log(be.INFO,"setCursor: "+t),this.rows[this.currRow].setCursor(t)},e.setPAC=function(t){this.logger.log(be.INFO,"pacData = "+JSON.stringify(t));var e=t.row-1;if(this.nrRollUpRows&&e0&&(r=t?"["+e.join(" | ")+"]":e.join("\n")),r},e.getTextAndFormat=function(){return this.rows},t}(),Be=function(){function t(t,e,r){this.chNr=void 0,this.outputFilter=void 0,this.mode=void 0,this.verbose=void 0,this.displayedMemory=void 0,this.nonDisplayedMemory=void 0,this.lastOutputScreen=void 0,this.currRollUpRow=void 0,this.writeScreen=void 0,this.cueStartTime=void 0,this.logger=void 0,this.chNr=t,this.outputFilter=e,this.mode=null,this.verbose=0,this.displayedMemory=new Ue(r),this.nonDisplayedMemory=new Ue(r),this.lastOutputScreen=new Ue(r),this.currRollUpRow=this.displayedMemory.rows[14],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null,this.logger=r}var e=t.prototype;return e.reset=function(){this.mode=null,this.displayedMemory.reset(),this.nonDisplayedMemory.reset(),this.lastOutputScreen.reset(),this.outputFilter.reset(),this.currRollUpRow=this.displayedMemory.rows[14],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null},e.getHandler=function(){return this.outputFilter},e.setHandler=function(t){this.outputFilter=t},e.setPAC=function(t){this.writeScreen.setPAC(t)},e.setBkgData=function(t){this.writeScreen.setBkgData(t)},e.setMode=function(t){t!==this.mode&&(this.mode=t,this.logger.log(be.INFO,"MODE="+t),"MODE_POP-ON"===this.mode?this.writeScreen=this.nonDisplayedMemory:(this.writeScreen=this.displayedMemory,this.writeScreen.reset()),"MODE_ROLL-UP"!==this.mode&&(this.displayedMemory.nrRollUpRows=null,this.nonDisplayedMemory.nrRollUpRows=null),this.mode=t)},e.insertChars=function(t){for(var e=0;e=46,e.italics)e.foreground="white";else{var r=Math.floor(t/2)-16;e.foreground=["white","green","blue","cyan","red","yellow","magenta"][r]}this.logger.log(be.INFO,"MIDROW: "+JSON.stringify(e)),this.writeScreen.setPen(e)},e.outputDataUpdate=function(t){void 0===t&&(t=!1);var e=this.logger.time;null!==e&&this.outputFilter&&(null!==this.cueStartTime||this.displayedMemory.isEmpty()?this.displayedMemory.equals(this.lastOutputScreen)||(this.outputFilter.newCue(this.cueStartTime,e,this.lastOutputScreen),t&&this.outputFilter.dispatchCue&&this.outputFilter.dispatchCue(),this.cueStartTime=this.displayedMemory.isEmpty()?null:e):this.cueStartTime=e,this.lastOutputScreen.copy(this.displayedMemory))},e.cueSplitAtTime=function(t){this.outputFilter&&(this.displayedMemory.isEmpty()||(this.outputFilter.newCue&&this.outputFilter.newCue(this.cueStartTime,t,this.displayedMemory),this.cueStartTime=t))},t}();function Ge(t,e,r){r.a=t,r.b=e}function Ke(t,e,r){return r.a===t&&r.b===e}var je=function(){function t(t,e,r){this.channels=void 0,this.currentChannel=0,this.cmdHistory=void 0,this.logger=void 0;var i=new xe;this.channels=[null,new Be(t,e,i),new Be(t+1,r,i)],this.cmdHistory={a:null,b:null},this.logger=i}var e=t.prototype;return e.getHandler=function(t){return this.channels[t].getHandler()},e.setHandler=function(t,e){this.channels[t].setHandler(e)},e.addData=function(t,e){var r,i,n,a=!1;this.logger.time=t;for(var s=0;s ("+Pe([i,n])+")"),(r=this.parseCmd(i,n))||(r=this.parseMidrow(i,n)),r||(r=this.parsePAC(i,n)),r||(r=this.parseBackgroundAttributes(i,n)),!r&&(a=this.parseChars(i,n))){var o=this.currentChannel;if(o&&o>0)this.channels[o].insertChars(a);else this.logger.log(be.WARNING,"No channel found yet. TEXT-MODE?")}r||a||this.logger.log(be.WARNING,"Couldn't parse cleaned data "+Pe([i,n])+" orig: "+Pe([e[s],e[s+1]]))}},e.parseCmd=function(t,e){var r=this.cmdHistory;if(!((20===t||28===t||21===t||29===t)&&e>=32&&e<=47)&&!((23===t||31===t)&&e>=33&&e<=35))return!1;if(Ke(t,e,r))return Ge(null,null,r),this.logger.log(be.DEBUG,"Repeated command ("+Pe([t,e])+") is dropped"),!0;var i=20===t||21===t||23===t?1:2,n=this.channels[i];return 20===t||21===t||28===t||29===t?32===e?n.ccRCL():33===e?n.ccBS():34===e?n.ccAOF():35===e?n.ccAON():36===e?n.ccDER():37===e?n.ccRU(2):38===e?n.ccRU(3):39===e?n.ccRU(4):40===e?n.ccFON():41===e?n.ccRDC():42===e?n.ccTR():43===e?n.ccRTD():44===e?n.ccEDM():45===e?n.ccCR():46===e?n.ccENM():47===e&&n.ccEOC():n.ccTO(e-32),Ge(t,e,r),this.currentChannel=i,!0},e.parseMidrow=function(t,e){var r=0;if((17===t||25===t)&&e>=32&&e<=47){if((r=17===t?1:2)!==this.currentChannel)return this.logger.log(be.ERROR,"Mismatch channel in midrow parsing"),!1;var i=this.channels[r];return!!i&&(i.ccMIDROW(e),this.logger.log(be.DEBUG,"MIDROW ("+Pe([t,e])+")"),!0)}return!1},e.parsePAC=function(t,e){var r,i=this.cmdHistory;if(!((t>=17&&t<=23||t>=25&&t<=31)&&e>=64&&e<=127)&&!((16===t||24===t)&&e>=64&&e<=95))return!1;if(Ke(t,e,i))return Ge(null,null,i),!0;var n=t<=23?1:2;r=e>=64&&e<=95?1===n?_e[t]:Ce[t]:1===n?Ie[t]:we[t];var a=this.channels[n];return!!a&&(a.setPAC(this.interpretPAC(r,e)),Ge(t,e,i),this.currentChannel=n,!0)},e.interpretPAC=function(t,e){var r,i={color:null,italics:!1,indent:null,underline:!1,row:t};return r=e>95?e-96:e-64,i.underline=1==(1&r),r<=13?i.color=["white","green","blue","cyan","red","yellow","magenta","white"][Math.floor(r/2)]:r<=15?(i.italics=!0,i.color="white"):i.indent=4*Math.floor((r-16)/2),i},e.parseChars=function(t,e){var r,i,n=null,a=null;(t>=25?(r=2,a=t-8):(r=1,a=t),a>=17&&a<=19)?(i=17===a?e+80:18===a?e+112:e+144,this.logger.log(be.INFO,"Special char '"+ke(i)+"' in channel "+r),n=[i]):t>=32&&t<=127&&(n=0===e?[t]:[t,e]);if(n){var s=Pe(n);this.logger.log(be.DEBUG,"Char codes = "+s.join(",")),Ge(t,e,this.cmdHistory)}return n},e.parseBackgroundAttributes=function(t,e){var r;if(!((16===t||24===t)&&e>=32&&e<=47)&&!((23===t||31===t)&&e>=45&&e<=47))return!1;var i={};16===t||24===t?(r=Math.floor((e-32)/2),i.background=Oe[r],e%2==1&&(i.background=i.background+"_semi")):45===e?i.background="transparent":(i.foreground="black",47===e&&(i.underline=!0));var n=t<=23?1:2;return this.channels[n].setBkgData(i),Ge(t,e,this.cmdHistory),!0},e.reset=function(){for(var t=0;tt)&&(this.startTime=t),this.endTime=e,this.screen=r,this.timelineController.createCaptionsTrack(this.trackName)},e.reset=function(){this.cueRanges=[],this.startTime=null},t}(),Ve=function(){if("undefined"!=typeof self&&self.VTTCue)return self.VTTCue;var t=["","lr","rl"],e=["start","middle","end","left","right"];function r(t,e){if("string"!=typeof e)return!1;if(!Array.isArray(t))return!1;var r=e.toLowerCase();return!!~t.indexOf(r)&&r}function i(t){return r(e,t)}function n(t){for(var e=arguments.length,r=new Array(e>1?e-1:0),i=1;i100)throw new Error("Position must be between 0 and 100.");T=t,this.hasBeenReset=!0}})),Object.defineProperty(o,"positionAlign",n({},l,{get:function(){return b},set:function(t){var e=i(t);if(!e)throw new SyntaxError("An invalid or illegal string was specified.");b=e,this.hasBeenReset=!0}})),Object.defineProperty(o,"size",n({},l,{get:function(){return E},set:function(t){if(t<0||t>100)throw new Error("Size must be between 0 and 100.");E=t,this.hasBeenReset=!0}})),Object.defineProperty(o,"align",n({},l,{get:function(){return S},set:function(t){var e=i(t);if(!e)throw new SyntaxError("An invalid or illegal string was specified.");S=e,this.hasBeenReset=!0}})),o.displayState=void 0}return a.prototype.getCueAsHTML=function(){return self.WebVTT.convertCueToDOMTree(self,this.text)},a}(),We=function(){function t(){}return t.prototype.decode=function(t,e){if(!t)return"";if("string"!=typeof t)throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(t))},t}();function Ye(t){function e(t,e,r,i){return 3600*(0|t)+60*(0|e)+(0|r)+parseFloat(i||0)}var r=t.match(/^(?:(\d+):)?(\d{2}):(\d{2})(\.\d+)?/);return r?parseFloat(r[2])>59?e(r[2],r[3],0,r[4]):e(r[1],r[2],r[3],r[4]):null}var qe=function(){function t(){this.values=Object.create(null)}var e=t.prototype;return e.set=function(t,e){this.get(t)||""===e||(this.values[t]=e)},e.get=function(t,e,r){return r?this.has(t)?this.values[t]:e[r]:this.has(t)?this.values[t]:e},e.has=function(t){return t in this.values},e.alt=function(t,e,r){for(var i=0;i=0&&r<=100)return this.set(t,r),!0}return!1},t}();function Xe(t,e,r,i){var n=i?t.split(i):[t];for(var a in n)if("string"==typeof n[a]){var s=n[a].split(r);if(2===s.length)e(s[0],s[1])}}var ze=new Ve(0,0,""),Qe="middle"===ze.align?"middle":"center";function $e(t,e,r){var i=t;function n(){var e=Ye(t);if(null===e)throw new Error("Malformed timestamp: "+i);return t=t.replace(/^[^\sa-zA-Z-]+/,""),e}function a(){t=t.replace(/^\s+/,"")}if(a(),e.startTime=n(),a(),"--\x3e"!==t.substr(0,3))throw new Error("Malformed time stamp (time stamps must be separated by '--\x3e'): "+i);t=t.substr(3),a(),e.endTime=n(),a(),function(t,e){var i=new qe;Xe(t,(function(t,e){var n;switch(t){case"region":for(var a=r.length-1;a>=0;a--)if(r[a].id===e){i.set(t,r[a].region);break}break;case"vertical":i.alt(t,e,["rl","lr"]);break;case"line":n=e.split(","),i.integer(t,n[0]),i.percent(t,n[0])&&i.set("snapToLines",!1),i.alt(t,n[0],["auto"]),2===n.length&&i.alt("lineAlign",n[1],["start",Qe,"end"]);break;case"position":n=e.split(","),i.percent(t,n[0]),2===n.length&&i.alt("positionAlign",n[1],["start",Qe,"end","line-left","line-right","auto"]);break;case"size":i.percent(t,e);break;case"align":i.alt(t,e,["start",Qe,"end","left","right"])}}),/:/,/\s/),e.region=i.get("region",null),e.vertical=i.get("vertical","");var n=i.get("line","auto");"auto"===n&&-1===ze.line&&(n=-1),e.line=n,e.lineAlign=i.get("lineAlign","start"),e.snapToLines=i.get("snapToLines",!0),e.size=i.get("size",100),e.align=i.get("align",Qe);var a=i.get("position","auto");"auto"===a&&50===ze.position&&(a="start"===e.align||"left"===e.align?0:"end"===e.align||"right"===e.align?100:50),e.position=a}(t,e)}function Je(t){return t.replace(//gi,"\n")}var Ze=function(){function t(){this.state="INITIAL",this.buffer="",this.decoder=new We,this.regionList=[],this.cue=null,this.oncue=void 0,this.onparsingerror=void 0,this.onflush=void 0}var e=t.prototype;return e.parse=function(t){var e=this;function r(){var t=e.buffer,r=0;for(t=Je(t);r>>0).toString()};function ar(t,e,r){return nr(t.toString())+nr(e.toString())+nr(r)}function sr(t,e,r,i,a,s,o,l){var u,h=new Ze,d=Object(M.f)(new Uint8Array(t)).trim().replace(rr,"\n").split("\n"),c=[],f=Object(tr.a)(e,r),g="00:00.000",v=0,p=0,m=!0,y=!1;h.oncue=function(t){var e=i[a],r=i.ccOffset,n=(v-f)/9e4;if(null!=e&&e.new&&(void 0!==p?r=i.ccOffset=e.start:function(t,e,r){var i=t[e],n=t[i.prevCC];if(!n||!n.new&&i.new)return t.ccOffset=t.presentationOffset=i.start,void(i.new=!1);for(;null!==(a=n)&&void 0!==a&&a.new;){var a;t.ccOffset+=i.start-n.start,i.new=!1,n=t[(i=n).prevCC]}t.presentationOffset=r}(i,a,n)),n&&(r=n-i.presentationOffset),y){var o=t.endTime-t.startTime,l=Object(er.b)(9e4*(t.startTime+r-p),9e4*s)/9e4;t.startTime=l,t.endTime=l+o}var u=t.text.trim();t.text=decodeURIComponent(encodeURIComponent(u)),t.id||(t.id=ar(t.startTime,t.endTime,u)),t.endTime>0&&c.push(t)},h.onparsingerror=function(t){u=t},h.onflush=function(){u?l(u):o(c)},d.forEach((function(t){if(m){if(ir(t,"X-TIMESTAMP-MAP=")){m=!1,y=!0,t.substr(16).split(",").forEach((function(t){ir(t,"LOCAL:")?g=t.substr(6):ir(t,"MPEGTS:")&&(v=parseInt(t.substr(7)))}));try{p=function(t){var e=parseInt(t.substr(-3)),r=parseInt(t.substr(-6,2)),i=parseInt(t.substr(-9,2)),a=t.length>9?parseInt(t.substr(0,t.indexOf(":"))):0;if(!(Object(n.a)(e)&&Object(n.a)(r)&&Object(n.a)(i)&&Object(n.a)(a)))throw Error("Malformed X-TIMESTAMP-MAP: Local:"+t);return e+=1e3*r,e+=6e4*i,e+=36e5*a}(g)/1e3}catch(t){y=!1,u=t}return}""===t&&(m=!1)}h.parse(t+"\n")})),h.flush()}function or(){return(or=Object.assign||function(t){for(var e=1;e=0&&(c[0]=Math.min(c[0],e),c[1]=Math.max(c[1],r),h=!0,f/(r-e)>.5))return}if(h||n.push([e,r]),this.config.renderTextTracksNatively){var g=this.captionsTracks[t];this.Cues.newCue(g,e,r,i)}else{var v=this.Cues.newCue(null,e,r,i);this.hls.trigger(a.a.CUES_PARSED,{type:"captions",cues:v,track:t})}},e.onInitPtsFound=function(t,e){var r=this,i=e.frag,n=e.id,s=e.initPTS,o=e.timescale,l=this.unparsedVttFrags;"main"===n&&(this.initPTS[i.cc]=s,this.timescale[i.cc]=o),l.length&&(this.unparsedVttFrags=[],l.forEach((function(t){r.onFragLoaded(a.a.FRAG_LOADED,t)})))},e.getExistingTrack=function(t){var e=this.media;if(e)for(var r=0;r0&&this.mediaWidth>0){var t=this.hls.levels;if(t.length){var e=this.hls;e.autoLevelCapping=this.getMaxLevel(t.length-1),e.autoLevelCapping>this.autoLevelCapping&&this.streamController&&this.streamController.nextLevelSwitch(),this.autoLevelCapping=e.autoLevelCapping}}},n.getMaxLevel=function(e){var r=this,i=this.hls.levels;if(!i.length)return-1;var n=i.filter((function(i,n){return t.isLevelAllowed(n,r.restrictedLevels)&&n<=e}));return this.clientRect=null,t.getMaxLevelByMediaSize(n,this.mediaWidth,this.mediaHeight)},n.startCapping=function(){this.timer||(this.autoLevelCapping=Number.POSITIVE_INFINITY,this.hls.firstLevel=this.getMaxLevel(this.firstLevel),self.clearInterval(this.timer),this.timer=self.setInterval(this.detectPlayerSize.bind(this),1e3),this.detectPlayerSize())},n.stopCapping=function(){this.restrictedLevels=[],this.firstLevel=-1,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.timer&&(self.clearInterval(this.timer),this.timer=void 0)},n.getDimensions=function(){if(this.clientRect)return this.clientRect;var t=this.media,e={width:0,height:0};if(t){var r=t.getBoundingClientRect();e.width=r.width,e.height=r.height,e.width||e.height||(e.width=r.right-r.left||t.width||0,e.height=r.bottom-r.top||t.height||0)}return this.clientRect=e,e},t.isLevelAllowed=function(t,e){return void 0===e&&(e=[]),-1===e.indexOf(t)},t.getMaxLevelByMediaSize=function(t,e,r){if(!t||!t.length)return-1;for(var i,n,a=t.length-1,s=0;s=e||o.height>=r)&&(i=o,!(n=t[s+1])||i.width!==n.width||i.height!==n.height)){a=s;break}}return a},e=t,i=[{key:"contentScaleFactor",get:function(){var t=1;try{t=self.devicePixelRatio}catch(t){}return t}}],(r=[{key:"mediaWidth",get:function(){return this.getDimensions().width*t.contentScaleFactor}},{key:"mediaHeight",get:function(){return this.getDimensions().height*t.contentScaleFactor}}])&&Tr(e.prototype,r),i&&Tr(e,i),t}(),Sr=function(){function t(t){this.hls=void 0,this.isVideoPlaybackQualityAvailable=!1,this.timer=void 0,this.media=null,this.lastTime=void 0,this.lastDroppedFrames=0,this.lastDecodedFrames=0,this.streamController=void 0,this.hls=t,this.registerListeners()}var e=t.prototype;return e.setStreamController=function(t){this.streamController=t},e.registerListeners=function(){this.hls.on(a.a.MEDIA_ATTACHING,this.onMediaAttaching,this)},e.unregisterListeners=function(){this.hls.off(a.a.MEDIA_ATTACHING,this.onMediaAttaching)},e.destroy=function(){this.timer&&clearInterval(this.timer),this.unregisterListeners(),this.isVideoPlaybackQualityAvailable=!1,this.media=null},e.onMediaAttaching=function(t,e){var r=this.hls.config;if(r.capLevelOnFPSDrop){var i=e.media instanceof self.HTMLVideoElement?e.media:null;this.media=i,i&&"function"==typeof i.getVideoPlaybackQuality&&(this.isVideoPlaybackQualityAvailable=!0),self.clearInterval(this.timer),this.timer=self.setInterval(this.checkFPSInterval.bind(this),r.fpsDroppedMonitoringPeriod)}},e.checkFPS=function(t,e,r){var i=performance.now();if(e){if(this.lastTime){var n=i-this.lastTime,s=r-this.lastDroppedFrames,l=e-this.lastDecodedFrames,u=1e3*s/n,h=this.hls;if(h.trigger(a.a.FPS_DROP,{currentDropped:s,currentDecoded:l,totalDroppedFrames:r}),u>0&&s>h.config.fpsDroppedMonitoringThreshold*l){var d=h.currentLevel;o.b.warn("drop FPS ratio greater than max allowed value for currentLevel: "+d),d>0&&(-1===h.autoLevelCapping||h.autoLevelCapping>=d)&&(d-=1,h.trigger(a.a.FPS_DROP_LEVEL_CAPPING,{level:d,droppedLevel:h.currentLevel}),h.autoLevelCapping=d,this.streamController.nextLevelSwitch())}}this.lastTime=i,this.lastDroppedFrames=r,this.lastDecodedFrames=e}},e.checkFPSInterval=function(){var t=this.media;if(t)if(this.isVideoPlaybackQualityAvailable){var e=t.getVideoPlaybackQuality();this.checkFPS(t,e.totalVideoFrames,e.droppedVideoFrames)}else this.checkFPS(t,t.webkitDecodedFrameCount,t.webkitDroppedFrameCount)},t}();!function(t){t.WIDEVINE="com.widevine.alpha",t.PLAYREADY="com.microsoft.playready"}(br||(br={}));var Lr="undefined"!=typeof self&&self.navigator&&self.navigator.requestMediaKeySystemAccess?self.navigator.requestMediaKeySystemAccess.bind(self.navigator):null;function Ar(t,e){for(var r=0;r3)return void this.hls.trigger(a.a.ERROR,{type:s.b.KEY_SYSTEM_ERROR,details:s.a.KEY_SYSTEM_LICENSE_REQUEST_FAILED,fatal:!0});var u=3-this._requestLicenseFailureCount+1;o.b.warn("Retrying license request, "+u+" attempts left"),this._requestLicense(r,i)}}},n._generateLicenseRequestChallenge=function(t,e){switch(t.mediaKeySystemDomain){case br.WIDEVINE:return e}throw new Error("unsupported key-system: "+t.mediaKeySystemDomain)},n._requestLicense=function(t,e){o.b.log("Requesting content license for key-system");var r=this._mediaKeysList[0];if(!r)return o.b.error("Fatal error: Media is encrypted but no key-system access has been obtained yet"),void this.hls.trigger(a.a.ERROR,{type:s.b.KEY_SYSTEM_ERROR,details:s.a.KEY_SYSTEM_NO_ACCESS,fatal:!0});try{var i=this.getLicenseServerUrl(r.mediaKeySystemDomain),n=this._createLicenseXhr(i,t,e);o.b.log("Sending license request to URL: "+i);var l=this._generateLicenseRequestChallenge(r,t);n.send(l)}catch(t){o.b.error("Failure requesting DRM license: "+t),this.hls.trigger(a.a.ERROR,{type:s.b.KEY_SYSTEM_ERROR,details:s.a.KEY_SYSTEM_LICENSE_REQUEST_FAILED,fatal:!0})}},n.onMediaAttached=function(t,e){if(this._emeEnabled){var r=e.media;this._media=r,r.addEventListener("encrypted",this._onMediaEncrypted)}},n.onMediaDetached=function(){var t=this._media,e=this._mediaKeysList;t&&(t.removeEventListener("encrypted",this._onMediaEncrypted),this._media=null,this._mediaKeysList=[],Promise.all(e.map((function(t){if(t.mediaKeysSession)return t.mediaKeysSession.close().catch((function(){}))}))).then((function(){return t.setMediaKeys(null)})).catch((function(){})))},n.onManifestParsed=function(t,e){if(this._emeEnabled){var r=e.levels.map((function(t){return t.audioCodec})).filter((function(t){return!!t})),i=e.levels.map((function(t){return t.videoCodec})).filter((function(t){return!!t}));this._attemptKeySystemAccess(br.WIDEVINE,r,i)}},e=t,(r=[{key:"requestMediaKeySystemAccess",get:function(){if(!this._requestMediaKeySystemAccess)throw new Error("No requestMediaKeySystemAccess function configured");return this._requestMediaKeySystemAccess}}])&&Ar(e.prototype,r),i&&Ar(e,i),t}();function Ir(t,e){for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function Or(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,i=new Array(e);r-1?n+1:i.levels.length;e=i.levels.slice(0,a)}for(var s,o=wr(e);!(s=o()).done;){var l=s.value;l.bitrate>r&&(r=l.bitrate)}return r>0?r:NaN},e.getBufferLength=function(t){var e=this.hls.media,r=t===Rr.AUDIO?this.audioBuffer:this.videoBuffer;return r&&e?1e3*lt.bufferInfo(r,e.currentTime,this.config.maxBufferHole).len:NaN},e.createPlaylistLoader=function(){var t=this.config.pLoader,e=this.applyPlaylistData,r=t||this.config.loader;return function(){function t(t){this.loader=void 0,this.loader=new r(t)}var i=t.prototype;return i.destroy=function(){this.loader.destroy()},i.abort=function(){this.loader.abort()},i.load=function(t,r,i){e(t),this.loader.load(t,r,i)},Cr(t,[{key:"stats",get:function(){return this.loader.stats}},{key:"context",get:function(){return this.loader.context}}]),t}()},e.createFragmentLoader=function(){var t=this.config.fLoader,e=this.applyFragmentData,r=t||this.config.loader;return function(){function t(t){this.loader=void 0,this.loader=new r(t)}var i=t.prototype;return i.destroy=function(){this.loader.destroy()},i.abort=function(){this.loader.abort()},i.load=function(t,r,i){e(t),this.loader.load(t,r,i)},Cr(t,[{key:"stats",get:function(){return this.loader.stats}},{key:"context",get:function(){return this.loader.context}}]),t}()},t.uuid=function(){var t=URL.createObjectURL(new Blob),e=t.toString();return URL.revokeObjectURL(t),e.substr(e.lastIndexOf("/")+1)},t.serialize=function(t){for(var e,r=[],i=function(t){return!Number.isNaN(t)&&null!=t&&""!==t&&!1!==t},n=function(t){return Math.round(t)},a=function(t){return 100*n(t/100)},s={br:n,d:n,bl:a,dl:a,mtp:a,nor:function(t){return encodeURIComponent(t)},rtp:a,tb:n},o=wr(Object.keys(t||{}).sort());!(e=o()).done;){var l=e.value,u=t[l];if(i(u)&&!("v"===l&&1===u||"pr"==l&&1===u)){var h=s[l];h&&(u=h(u));var d=typeof u,c=void 0;c="ot"===l||"sf"===l||"st"===l?l+"="+u:"boolean"===d?l:"number"===d?l+"="+u:l+"="+JSON.stringify(u),r.push(c)}}return r.join(",")},t.toHeaders=function(e){for(var r={},i=["Object","Request","Session","Status"],n=[{},{},{},{}],a={br:0,d:0,ot:0,tb:0,bl:1,dl:1,mtp:1,nor:1,nrr:1,su:1,cid:2,pr:2,sf:2,sid:2,st:2,v:2,bs:3,rtp:3},s=0,o=Object.keys(e);s=2)if(self.clearTimeout(this.requestTimeout),0===r.loading.first&&(r.loading.first=Math.max(self.performance.now(),r.loading.start)),4===i){e.onreadystatechange=null,e.onprogress=null;var a=e.status;if(a>=200&&a<300){var s,l;if(r.loading.end=Math.max(self.performance.now(),r.loading.first),l="arraybuffer"===t.responseType?(s=e.response).byteLength:(s=e.responseText).length,r.loaded=r.total=l,!this.callbacks)return;var u=this.callbacks.onProgress;if(u&&u(r,t,s,e),!this.callbacks)return;var h={url:e.responseURL,data:s};this.callbacks.onSuccess(h,r,t,e)}else r.retry>=n.maxRetry||a>=400&&a<499?(o.b.error(a+" while loading "+t.url),this.callbacks.onError({code:a,text:e.statusText},t,e)):(o.b.warn(a+" while loading "+t.url+", retrying in "+this.retryDelay+"..."),this.abortInternal(),this.loader=null,self.clearTimeout(this.retryTimeout),this.retryTimeout=self.setTimeout(this.loadInternal.bind(this),this.retryDelay),this.retryDelay=Math.min(2*this.retryDelay,n.maxRetryDelay),r.retry++)}else self.clearTimeout(this.requestTimeout),this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),n.timeout)}},e.loadtimeout=function(){o.b.warn("timeout while loading "+this.context.url);var t=this.callbacks;t&&(this.abortInternal(),t.onTimeout(this.stats,this.context,this.loader))},e.loadprogress=function(t){var e=this.stats;e.loaded=t.loaded,t.lengthComputable&&(e.total=t.total)},e.getCacheAge=function(){var t=null;if(this.loader&&Fr.test(this.loader.getAllResponseHeaders())){var e=this.loader.getResponseHeader("age");t=e?parseFloat(e):null}return t},t}();function Ur(t){var e="function"==typeof Map?new Map:void 0;return(Ur=function(t){if(null===t||(r=t,-1===Function.toString.call(r).indexOf("[native code]")))return t;var r;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,i)}function i(){return Br(t,arguments,jr(this).constructor)}return i.prototype=Object.create(t.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),Kr(i,t)})(t)}function Br(t,e,r){return(Br=Gr()?Reflect.construct:function(t,e,r){var i=[null];i.push.apply(i,e);var n=new(Function.bind.apply(t,i));return r&&Kr(n,r.prototype),n}).apply(null,arguments)}function Gr(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}function Kr(t,e){return(Kr=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function jr(t){return(jr=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function Hr(){return(Hr=Object.assign||function(t){for(var e=1;e=i&&n(e,r,a.flush(),t)):n(e,r,l,t),o()})).catch((function(){return Promise.reject()}))}()},t}();function Wr(t,e){return new self.Request(t.url,e)}var Yr=function(t){var e,r;function i(e,r,i){var n;return(n=t.call(this,e)||this).code=void 0,n.details=void 0,n.code=r,n.details=i,n}return r=t,(e=i).prototype=Object.create(r.prototype),e.prototype.constructor=e,Kr(e,r),i}(Ur(Error)),qr=Vr,Xr=/\s/;function zr(){return(zr=Object.assign||function(t){for(var e=1;e=16?o--:o++;var f=Je(l.trim()),g=ar(e,r,f);t&&t.cues&&t.cues.getCueById(g)||((a=new h(e,r,f)).id=g,a.line=d+1,a.align="left",a.position=10+Math.min(80,10*Math.floor(8*o/32)),u.push(a))}return t&&u.length&&(u.sort((function(t,e){return"auto"===t.line||"auto"===e.line?0:t.line>8&&e.line>8?e.line-t.line:t.line-e.line})),u.forEach((function(e){return O(t,e)}))),u}},enableCEA708Captions:!0,enableWebVTT:!0,enableIMSC1:!0,captionsTextTrack1Label:"English",captionsTextTrack1LanguageCode:"en",captionsTextTrack2Label:"Spanish",captionsTextTrack2LanguageCode:"es",captionsTextTrack3Label:"Unknown CC",captionsTextTrack3LanguageCode:"",captionsTextTrack4Label:"Unknown CC",captionsTextTrack4LanguageCode:"",renderTextTracksNatively:!0}),{},{subtitleStreamController:pe,subtitleTrackController:Ee,timelineController:mr,audioStreamController:he,audioTrackController:fe,emeController:_r,cmcdController:Pr});function ti(t){var e=t.loader;e!==qr&&e!==Nr?(o.b.log("[config]: Custom loader detected, cannot enable progressive streaming"),t.progressive=!1):function(){if(self.fetch&&self.AbortController&&self.ReadableStream&&self.Request)try{return new self.ReadableStream({}),!0}catch(t){}return!1}()&&(t.loader=qr,t.progressive=!0,t.enableSoftwareAES=!0,o.b.log("[config]: Progressive streaming enabled, using FetchLoader"))}function ei(t,e){for(var r=0;re)return i;return 0}},{key:"maxAutoLevel",get:function(){var t=this.levels,e=this.autoLevelCapping;return-1===e&&t&&t.length?t.length-1:e}},{key:"nextAutoLevel",get:function(){return Math.min(Math.max(this.abrController.nextAutoLevel,this.minAutoLevel),this.maxAutoLevel)},set:function(t){this.abrController.nextAutoLevel=Math.max(this.minAutoLevel,t)}},{key:"audioTracks",get:function(){var t=this.audioTrackController;return t?t.audioTracks:[]}},{key:"audioTrack",get:function(){var t=this.audioTrackController;return t?t.audioTrack:-1},set:function(t){var e=this.audioTrackController;e&&(e.audioTrack=t)}},{key:"subtitleTracks",get:function(){var t=this.subtitleTrackController;return t?t.subtitleTracks:[]}},{key:"subtitleTrack",get:function(){var t=this.subtitleTrackController;return t?t.subtitleTrack:-1},set:function(t){var e=this.subtitleTrackController;e&&(e.subtitleTrack=t)}},{key:"media",get:function(){return this._media}},{key:"subtitleDisplay",get:function(){var t=this.subtitleTrackController;return!!t&&t.subtitleDisplay},set:function(t){var e=this.subtitleTrackController;e&&(e.subtitleDisplay=t)}},{key:"lowLatencyMode",get:function(){return this.config.lowLatencyMode},set:function(t){this.config.lowLatencyMode=t}},{key:"liveSyncPosition",get:function(){return this.latencyController.liveSyncPosition}},{key:"latency",get:function(){return this.latencyController.latency}},{key:"maxLatency",get:function(){return this.latencyController.maxLatency}},{key:"targetLatency",get:function(){return this.latencyController.targetLatency}},{key:"drift",get:function(){return this.latencyController.drift}},{key:"forceStartLoad",get:function(){return this.streamController.forceStartLoad}}])&&ei(e.prototype,r),n&&ei(e,n),t}();ri.defaultConfig=void 0}]).default})); \ No newline at end of file diff --git a/core/LightTube/wwwroot/js/lt-video/player-desktop.js b/core/LightTube/wwwroot/js/lt-video/player-desktop.js new file mode 100644 index 00000000..400b196a --- /dev/null +++ b/core/LightTube/wwwroot/js/lt-video/player-desktop.js @@ -0,0 +1,735 @@ +class Player { + constructor(query, info, sources, externalPlayer, externalPlayerType) { + // vars + this.externalPlayerType = externalPlayerType ?? "html5"; + this.muted = false; + this.info = info; + this.sources = sources; + this.__videoElement = document.querySelector(query); + this.__videoElement.removeAttribute("controls"); + this.__externalPlayer = externalPlayer; + + // container + const container = document.createElement("div"); + container.classList.add("player"); + this.__videoElement.parentElement.appendChild(container); + container.appendChild(this.__videoElement); + this.container = container; + if (info.embed) { + this.container.classList.add("embed"); + this.__videoElement.classList.remove("embed"); + } + + // default source + switch (this.externalPlayerType) { + case "html5": + for (let source of sources) { + if (source.height <= 720) { + this.__videoElement.src = source.src; + break; + } + } + break; + case "hls.js": + for (let level = this.__externalPlayer.levels.length - 1; level >= 0; level--) { + if (this.__externalPlayer.levels[level].height <= 720) { + this.__externalPlayer.currentLevel = level; + break; + } + } + break; + case "shaka": + let variants = this.__externalPlayer.getVariantTracks(); + for (let variant = variants.length - 1; variant >= 0; variant--) { + let v = variants[variant]; + if (v.height <= 720) { + this.__externalPlayer.selectVariantTrack(v, true); + break; + } + } + break; + } + + // controls + const createButton = (tag, icon) => { + const b = document.createElement(tag); + b.classList.add("player-button"); + if (icon !== "") + b.innerHTML = ``; + return b; + } + + this.controls = { + play: createButton("div", "play-fill"), + pause: createButton("div", "pause-fill"), + volume: createButton("div", "volume-up-fill"), + time: document.createElement("span"), + skipToLive: createButton("div", "skip-forward-fill"), + div: document.createElement("div"), + settings: createButton("div", "gear-fill"), + embed: createButton("a", ""), + pip: createButton("div", "pip"), + fullscreen: createButton("div", "fullscreen") + } + + if (!info.live) this.controls.skipToLive.style.display = "none" + + const controlHolder = document.createElement("div"); + controlHolder.classList.add("player-controls"); + + this.controls.embed.innerHTML = "lt"; + this.controls.embed.setAttribute("target", "_blank"); + this.controls.embed.setAttribute("href", "/watch?v=" + info.id); + if (!info.embed) this.controls.embed.style.display = "none"; + + const els = [ + document.createElement("div"), + document.createElement("div"), + ] + for (const padding of els) + padding.classList.add("player-controls-padding"); + + controlHolder.appendChild(els[0]); + for (const control of Object.values(this.controls)) { + controlHolder.appendChild(control); + } + controlHolder.appendChild(els[1]); + container.appendChild(controlHolder); + + this.controls.play.onclick = () => this.togglePlayPause(); + this.controls.pause.onclick = () => this.togglePlayPause(); + this.controls.volume.onclick = e => this.mute(e); + this.controls.volume.classList.add("player-volume"); + this.controls.fullscreen.onclick = () => this.fullscreen(); + this.controls.skipToLive.onclick = () => this.skipToLive(); + + if (document.pictureInPictureEnabled === true) + this.controls.pip.onclick = () => this.pip(); + else + this.controls.pip.style.display = "none"; + + let vol = null; + if (localStorage !== undefined) + vol = localStorage?.getItem("ltvideo.volume"); + let volumeRange = document.createElement("input"); + volumeRange.oninput = e => this.setVolume(e); + volumeRange.setAttribute("min", "0"); + volumeRange.setAttribute("max", "1"); + volumeRange.setAttribute("step", "0.01"); + volumeRange.setAttribute("value", vol ?? "1"); + volumeRange.setAttribute("type", "range"); + if (vol != null) + this.setVolume({target: {value: Number(vol)}}); + this.controls.volume.appendChild(volumeRange); + + this.controls.div.classList.add("player-button-divider") + + // playback bar + this.playbackBar = { + bg: document.createElement("div"), + played: document.createElement("div"), + buffered: document.createElement("div"), + hover: document.createElement("div"), + sb: document.createElement("div"), + sbC: document.createElement("div"), + hoverText: document.createElement("span") + } + this.playbackBar.bg.classList.add("player-playback-bar"); + this.playbackBar.bg.classList.add("player-playback-bar-bg"); + this.playbackBar.played.classList.add("player-playback-bar"); + this.playbackBar.played.classList.add("player-playback-bar-fg"); + this.playbackBar.buffered.classList.add("player-playback-bar"); + this.playbackBar.buffered.classList.add("player-playback-bar-buffer"); + this.playbackBar.bg.appendChild(this.playbackBar.buffered); + this.playbackBar.bg.appendChild(this.playbackBar.played); + + this.playbackBar.hover.classList.add("player-playback-bar-hover"); + if (!this.info.live) { + this.playbackBar.sb.classList.add("player-storyboard-image"); + this.playbackBar.sbC.classList.add("player-storyboard-image-container"); + this.playbackBar.sb.style.backgroundImage = `url("/proxy/storyboard/${info.id}")`; + this.playbackBar.sbC.appendChild(this.playbackBar.sb); + } else { + this.playbackBar.sb.remove(); + } + + let playbackBarContainer = document.createElement("div"); + playbackBarContainer.classList.add("player-playback-bar-container") + this.playbackBar.bg.onclick = e => { + this.playbackBarSeek(e) + } + this.playbackBar.bg.ondragover = e => { + this.playbackBarSeek(e) + } + this.playbackBar.bg.onmouseenter = () => { + this.playbackBar.hover.style.display = "block"; + } + this.playbackBar.bg.onmouseleave = () => { + this.playbackBar.hover.style.display = "none"; + } + this.playbackBar.bg.onmousemove = e => { + this.moveHover(e) + } + playbackBarContainer.appendChild(this.playbackBar.bg); + this.playbackBar.hover.appendChild(this.playbackBar.sbC) + this.playbackBar.hover.appendChild(this.playbackBar.hoverText) + playbackBarContainer.appendChild(this.playbackBar.hover); + container.appendChild(playbackBarContainer); + + // title + this.titleElement = document.createElement("div"); + this.titleElement.classList.add("player-title"); + this.titleElement.innerText = info.title; + container.appendChild(this.titleElement); + if (!info.embed) + this.titleElement.style.display = "none"; + + // events + container.onfullscreenchange = () => { + if (!document.fullscreenElement) { + this.controls.fullscreen.querySelector("i").setAttribute("class", "bi bi-fullscreen"); + if (!info.embed) + this.titleElement.style.display = "none"; + } else { + this.titleElement.style.display = "block"; + this.controls.fullscreen.querySelector("i").setAttribute("class", "bi bi-fullscreen-exit"); + } + } + const updatePlayButtons = () => { + if (this.__videoElement.paused) { + this.controls.pause.style.display = "none"; + this.controls.play.style.display = "block"; + } else { + this.controls.pause.style.display = "block"; + this.controls.play.style.display = "none"; + } + } + this.__videoElement.onplay = () => updatePlayButtons(); + this.__videoElement.onpause = () => updatePlayButtons(); + updatePlayButtons(); + this.__videoElement.onclick = () => this.togglePlayPause(); + this.__videoElement.ondblclick = () => this.fullscreen(); + this.container.onkeydown = e => this.keyboardHandler(e); + + this.container.onmousemove = () => { + let d = new Date(); + d.setSeconds(d.getSeconds() + 3); + this.controlsDisappearTimeout = d.getTime(); + } + + switch (this.externalPlayerType) { + case "shaka": + externalPlayer.addEventListener("variantchanged", () => { + this.updateMenu(); + }); + externalPlayer.addEventListener('error', this.fallbackFromShaka); + break; + case "hls.js": + // uhhhhhh... + break; + } + + // menu + this.controls.settings.onclick = e => this.menuButtonClick(e); + this.controls.settings.setAttribute("data-action", "toggle"); + this.controls.settings.querySelector("i").setAttribute("data-action", "toggle"); + this.updateMenu(sources); + + // buffering + this.bufferingScreen = document.createElement("div"); + this.bufferingScreen.classList.add("player-buffering"); + this.container.appendChild(this.bufferingScreen); + + let bufferingSpinner = document.createElement("img"); + bufferingSpinner.classList.add("player-buffering-spinner"); + bufferingSpinner.src = "/img/spinner.gif"; + this.bufferingScreen.appendChild(bufferingSpinner); + + setInterval(() => this.update(), 100); + } + + togglePlayPause() { + if (this.__videoElement.paused) + this.__videoElement.play(); + else + this.__videoElement.pause(); + } + + updateMenu() { + const makeButton = (label, action, icon) => { + const b = document.createElement("div"); + //todo: yes fix this + b.innerHTML = `${label}`; + b.onclick = e => this.menuButtonClick(e); + b.setAttribute("data-action", action) + b.classList.add("player-menu-item") + return b; + } + + const makeMenu = (id, buttons) => { + const menu = document.createElement("div"); + menu.id = id; + for (const button of buttons) { + menu.appendChild(makeButton(button.label, button.action, button.icon)); + } + return menu; + } + + if (this.menuElement) { + this.menuElement.remove(); + this.menuElement = undefined; + } + this.menuElement = document.createElement("div"); + this.menuElement.classList.add("player-menu"); + this.menuElement.appendChild(makeMenu("menu-main", [ + { + icon: "sliders", + label: "Quality", + action: "menu res" + }, + { + icon: "badge-cc", + label: "Subtitles", + action: "menu sub" + }, + { + icon: "speedometer2", + label: "Speed", + action: "menu speed" + } + ])) + const resButtons = [ + { + icon: "arrow-left", + label: "Back", + action: "menu main" + } + ] + + switch (this.externalPlayerType) { + case "html5": + for (const index in this.sources) { + resButtons.push({ + icon: this.sources[index].src === this.__videoElement.src ? "check2" : "", + label: this.sources[index].label, + action: "videosrc " + index + }); + } + break; + case "shaka": + resButtons.pop(); + let tracks = this.__externalPlayer.getVariantTracks(); + for (const index in tracks) { + if (tracks[index].audioId === 2) + resButtons.unshift({ + icon: tracks[index].active ? "check2" : "", + label: tracks[index].height + "p", + action: "shakavariant " + index + }); + } + resButtons.unshift({ + icon: this.__externalPlayer.getConfiguration().abr.enabled ? "check2" : "", + label: "Auto", + action: "shakavariant -1" + }); + resButtons.unshift( + { + icon: "arrow-left", + label: "Back", + action: "menu main" + }); + break; + case "hls.js": + resButtons.pop(); + for (const level in this.__externalPlayer.levels) { + resButtons.unshift({ + icon: level === this.__externalPlayer.currentLevel ? "check2" : "", + label: this.__externalPlayer.levels[level].height + "p", + action: "hlslevel " + level + }); + } + resButtons.unshift( + { + icon: -1 === this.__externalPlayer.currentLevel ? "check2" : "", + label: "Auto", + action: "hlslevel -1" + }); + resButtons.unshift( + { + icon: "arrow-left", + label: "Back", + action: "menu main" + }); + break; + } + this.menuElement.appendChild(makeMenu("menu-res", resButtons)); + const subButtons = [ + { + icon: "arrow-left", + label: "Back", + action: "menu main" + } + ] + + for (let index = 0; index < this.__videoElement.textTracks.length; index++) { + if (this.__videoElement.textTracks[index].label.includes("Shaka Player")) continue; + subButtons.push({ + icon: this.__videoElement.textTracks[index].mode === "showing" ? "check2" : "", + label: this.__videoElement.textTracks[index].label, + action: "texttrack " + index + }); + } + this.menuElement.appendChild(makeMenu("menu-sub", subButtons)); + this.menuElement.appendChild(makeMenu("menu-speed", [ + { + icon: "arrow-left", + label: "Back", + action: "menu main" + }, + { + icon: this.__videoElement.playbackRate === 0.25 ? "check2" : "", + label: "0.25", + action: "speed 0.25" + }, + { + icon: this.__videoElement.playbackRate === 0.50 ? "check2" : "", + label: "0.50", + action: "speed 0.5" + }, + { + icon: this.__videoElement.playbackRate === 0.75 ? "check2" : "", + label: "0.75", + action: "speed 0.75" + }, + { + icon: this.__videoElement.playbackRate === 1 ? "check2" : "", + label: "Normal", + action: "speed 1" + }, + { + icon: this.__videoElement.playbackRate === 1.25 ? "check2" : "", + label: "1.25", + action: "speed 1.25" + }, + { + icon: this.__videoElement.playbackRate === 1.50 ? "check2" : "", + label: "1.50", + action: "speed 1.5" + }, + { + icon: this.__videoElement.playbackRate === 1.75 ? "check2" : "", + label: "1.75", + action: "speed 1.75" + }, + { + icon: this.__videoElement.playbackRate === 2 ? "check2" : "", + label: "2", + action: "speed 2" + }, + ])) + + this.container.appendChild(this.menuElement); + for (const child of this.menuElement.children) { + if (child.tagName === "DIV") + child.style.display = "none"; + } + } + + openMenu(id) { + for (const child of this.menuElement.children) { + if (child.tagName === "DIV") + child.style.display = "none"; + } + try { + this.menuElement.querySelector("#menu-" + id).style.display = "block"; + } catch { + // intended + } + } + + menuButtonClick(e) { + let args = (e.target.getAttribute("data-action") ?? e.target.parentElement.getAttribute("data-action")).split(" "); + let command = args.shift(); + let closeMenu = true; + switch (command) { + case "toggle": + closeMenu = this.menuElement.clientHeight !== 0; + if (!closeMenu) + this.openMenu("main"); + break; + case "menu": + this.openMenu(args[0]); + closeMenu = false; + break; + case "speed": + this.__videoElement.playbackRate = Number.parseFloat(args[0]); + this.updateMenu(); + break; + case "texttrack": + let i = Number.parseFloat(args[0]); + for (let index = 0; index < this.__videoElement.textTracks.length; index++) { + this.__videoElement.textTracks[index].mode = "hidden"; + + } + this.__videoElement.textTracks[i].mode = "showing"; + this.updateMenu(); + break; + case "videosrc": + let time = this.__videoElement.currentTime; + let shouldPlay = !this.__videoElement.paused; + this.__videoElement.src = this.sources[Number.parseFloat(args[0])].src; + this.__videoElement.currentTime = time; + if (shouldPlay) + this.__videoElement.play(); + this.updateMenu(); + break; + case "shakavariant": + if (args[0] !== "-1") + this.__externalPlayer.selectVariantTrack(this.__externalPlayer.getVariantTracks()[Number.parseFloat(args[0])], true, 2) + this.__externalPlayer.configure({abr: {enabled: args[0] === "-1"}}) + break; + case "hlslevel": + this.__externalPlayer.nextLevel = Number.parseInt(args[0]); + break; + } + if (closeMenu) + this.openMenu(); + }; + + mute(e) { + if (e.target.tagName === "INPUT") return; + this.muted = !this.muted; + if (this.muted) { + this.controls.volume.querySelector("i").setAttribute("class", "bi bi-volume-mute-fill"); + this.__videoElement.volume = 0; + } else { + this.controls.volume.querySelector("i").setAttribute("class", "bi bi-volume-up-fill"); + this.__videoElement.volume = this.controls.volume.querySelector("input").value; + } + } + + fullscreen() { + if (!document.fullscreenElement) { + this.container.requestFullscreen(); + } else { + document.exitFullscreen(); + } + } + + pip() { + this.__videoElement.requestPictureInPicture(); + } + + timeUpdate() { + if (this.info.live) { + let timeBack = this.__videoElement.duration - this.__videoElement.currentTime; + this.controls.time.innerHTML = timeBack > 10 ? this.getTimeString(timeBack) : "LIVE"; + } else + this.controls.time.innerHTML = this.getTimeString(this.__videoElement.currentTime) + " / " + this.getTimeString(this.__videoElement.duration); + this.playbackBar.played.style.width = ((this.__videoElement.currentTime / this.__videoElement.duration) * 100) + "%"; + this.playbackBar.buffered.style.width = ((this.getLoadEnd() / this.__videoElement.duration) * 100) + "%"; + + if (this.controlsDisappearTimeout - Date.now() < 0 && !this.container.classList.contains("hide-controls") && !this.__videoElement.paused) + this.container.classList.add("hide-controls"); + + + if (this.controlsDisappearTimeout - Date.now() > 0 && this.container.classList.contains("hide-controls")) + this.container.classList.remove("hide-controls"); + + if (this.__videoElement.paused && this.container.classList.contains("hide-controls")) + this.container.classList.add("hide-controls"); + } + + setVolume(e) { + this.__videoElement.volume = e.target.value; + localStorage.setItem("ltvideo.volume", e.target.value); + } + + getLoadEnd() { + let longest = -1; + for (let i = 0; i < this.__videoElement.buffered.length; i++) { + const end = this.__videoElement.buffered.end(i); + if (end > longest) longest = end; + } + return longest; + } + + playbackBarSeek(e) { + let percentage = (e.offsetX / (this.playbackBar.bg.clientLeft + this.playbackBar.bg.clientWidth)); + this.playbackBar.played.style.width = (percentage * 100) + "%"; + this.__videoElement.currentTime = this.__videoElement.duration * percentage; + } + + moveHover(e) { + let percentage = (e.offsetX / (this.playbackBar.bg.clientLeft + this.playbackBar.bg.clientWidth)); + let rPercent = Math.round(percentage * 100); + + if (!this.info.live) { + this.playbackBar.sb.style.backgroundPositionX = `-${rPercent % 10 * 48}px`; + this.playbackBar.sb.style.backgroundPositionY = `-${Math.floor(rPercent / 10) * 27}px`; + } + + this.playbackBar.hover.style.top = (this.playbackBar.bg.getBoundingClientRect().y - 4 - this.playbackBar.hover.clientHeight) + 'px'; + this.playbackBar.hover.style.left = (e.clientX - this.playbackBar.hover.clientWidth / 2) + 'px'; + this.playbackBar.hoverText.innerText = this.getTimeString(this.__videoElement.duration * percentage); + } + + skipToLive() { + this.__videoElement.currentTime = this.__videoElement.duration; + } + + keyboardHandler(e) { + let pd = true; + if (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) return; + switch (e.code) { + case "Space": + this.togglePlayPause(); + break; + case "Digit1": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.1; + break; + case "Digit2": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.2; + break; + case "Digit3": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.3; + break; + case "Digit4": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.4; + break; + case "Digit5": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.5; + break; + case "Digit6": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.6; + break; + case "Digit7": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.7; + break; + case "Digit8": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.8; + break; + case "Digit9": + if (!this.info.live) + this.__videoElement.currentTime = this.__videoElement.duration * 0.9; + break; + case "Digit0": + if (!this.info.live) + this.__videoElement.currentTime = 0; + break; + case "ArrowLeft": + if (!this.info.live) + this.__videoElement.currentTime -= 5; + break; + case "ArrowRight": + if (!this.info.live) + this.__videoElement.currentTime += 5; + break; + case "ArrowUp": + if (!this.info.live) + this.__videoElement.volume += 0.1; + break; + case "ArrowDown": + if (!this.info.live) + this.__videoElement.volume -= 0.1; + break; + case "KeyF": + this.fullscreen(); + break; + case "KeyM": + this.mute({target: {tagName: ""}}); + break; + default: + pd = false; + break; + } + if (pd) e.preventDefault(); + } + + getTimeString(s) { + let res = s < 3600 ? new Date(s * 1000).toISOString().substr(14, 5) : new Date(s * 1000).toISOString().substr(11, 8); + if (res.startsWith("0")) + res = res.substr(1); + return res; + } + + update() { + this.timeUpdate(); + + if (this.info.live) { + let timeBack = Math.abs(this.__videoElement.currentTime - this.__videoElement.buffered.end(this.__videoElement.buffered.length - 1)); + this.bufferingScreen.style.display = timeBack < .1 ? "flex" : "none"; + } else { + switch (this.__videoElement.readyState) { + case 1: + this.bufferingScreen.style.display = "flex"; + break; + default: + this.bufferingScreen.style.display = "none"; + break; + } + } + } + + async fallbackFromShaka() { + if (this.externalPlayerType !== "shaka") return; + this.externalPlayerType = "html5"; + console.log("Shaka player crashed, falling back"); + let cTime = this.__videoElement.currentTime; + await this.__externalPlayer.detach(); + await this.__externalPlayer.destroy(); + this.__videoElement.src = this.sources[0].src; + this.__externalPlayer = undefined; + this.__videoElement.currentTime = cTime; + this.updateMenu(); + console.log("Fallback complete!"); + } +} + +const loadPlayerWithShaka = async (query, info, sources, manifestUri) => { + let player; + if (manifestUri !== undefined) { + shaka.polyfill.installAll(); + let shakaUsable = shaka.Player.isBrowserSupported(); + + if (shakaUsable) { + const video = document.querySelector(query); + player = new shaka.Player(video); + + try { + await player.load(manifestUri); + } catch (e) { + await player.destroy(); + return new Player(query, info, sources, undefined, "html5"); + } + } + } + + return new Player(query, info, sources, await player, "shaka"); +} + +const loadPlayerWithHls = (query, info, manifestUri) => { + return new Promise((res, rej) => { + let hls; + + const video = document.querySelector(query); + + if (Hls.isSupported()) { + hls = new Hls(); + hls.loadSource(manifestUri); + hls.attachMedia(video); + hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) { + res(new Player(query, info, [], hls, "hls.js")); + }); + } else + rej("You can't watch livestreams / premieres because hls.js is not supported in your browser.") + }) +} \ No newline at end of file diff --git a/core/LightTube/wwwroot/js/lt-video/player-mobile.js b/core/LightTube/wwwroot/js/lt-video/player-mobile.js new file mode 100644 index 00000000..f852453e --- /dev/null +++ b/core/LightTube/wwwroot/js/lt-video/player-mobile.js @@ -0,0 +1,292 @@ +class Player { + constructor(query, info, sources, externalPlayer, externalPlayerType) { + // vars + this.externalPlayerType = externalPlayerType ?? "html5"; + this.muted = false; + this.info = info; + this.sources = sources; + this.__videoElement = document.querySelector(query); + this.__videoElement.removeAttribute("controls"); + this.__externalPlayer = externalPlayer; + + // container + const container = document.createElement("div"); + container.classList.add("player"); + this.__videoElement.parentElement.appendChild(container); + container.appendChild(this.__videoElement); + this.container = container; + if (info.embed) { + this.container.classList.add("embed"); + this.__videoElement.classList.remove("embed"); + } + + // default source + switch (this.externalPlayerType) { + case "html5": + for (let source of sources) { + if (source.height <= 720) { + this.__videoElement.src = source.src; + break; + } + } + break; + case "hls.js": + for (let level = this.__externalPlayer.levels.length - 1; level >= 0; level--) { + if (this.__externalPlayer.levels[level].height <= 720) { + this.__externalPlayer.currentLevel = level; + break; + } + } + break; + case "shaka": + this.__externalPlayer.configure({abr: {enabled: false}}) + let variants = this.__externalPlayer.getVariantTracks(); + for (let variant = variants.length - 1; variant >= 0; variant--) { + let v = variants[variant]; + if (v.height <= 720) { + this.__externalPlayer.selectVariantTrack(v, true); + break; + } + } + break; + } + + // controls + const createButton = (tag, icon) => { + const b = document.createElement(tag); + b.classList.add("player-button"); + if (icon !== "") + b.innerHTML = ``; + return b; + } + + this.controls = { + container: document.createElement("div"), + play: createButton("div", "play-fill"), + fullscreen: createButton("div", "fullscreen"), + time: document.createElement("span"), + duration: document.createElement("span"), + } + + this.controls.container.classList.add("player-controls"); + this.controls.container.appendChild(this.controls.play); + this.controls.fullscreen.classList.replace("player-button", "player-tiny-button") + container.appendChild(this.controls.container); + + this.controls.play.onclick = () => this.togglePlayPause(); + this.controls.fullscreen.onclick = () => this.fullscreen(); + this.setVolume({target: {value: 1}}); + + // playback bar + this.playbackBar = { + bg: document.createElement("div"), + played: document.createElement("div"), + buffered: document.createElement("div") + } + this.playbackBar.bg.classList.add("player-playback-bar"); + this.playbackBar.bg.classList.add("player-playback-bar-bg"); + this.playbackBar.played.classList.add("player-playback-bar"); + this.playbackBar.played.classList.add("player-playback-bar-fg"); + this.playbackBar.buffered.classList.add("player-playback-bar"); + this.playbackBar.buffered.classList.add("player-playback-bar-buffer"); + this.playbackBar.bg.appendChild(this.playbackBar.buffered); + this.playbackBar.bg.appendChild(this.playbackBar.played); + + let playbackBarContainer = document.createElement("div"); + playbackBarContainer.classList.add("player-playback-bar-container") + this.playbackBar.bg.onclick = e => { + this.playbackBarSeek(e) + } + playbackBarContainer.appendChild(this.controls.time); + playbackBarContainer.appendChild(this.playbackBar.bg); + playbackBarContainer.appendChild(this.controls.duration); + playbackBarContainer.appendChild(this.controls.fullscreen); + container.appendChild(playbackBarContainer); + + + // events + container.onfullscreenchange = () => { + if (!document.fullscreenElement) { + this.controls.fullscreen.querySelector("i").setAttribute("class", "bi bi-fullscreen"); + } else { + this.controls.fullscreen.querySelector("i").setAttribute("class", "bi bi-fullscreen-exit"); + } + } + const updatePlayButtons = () => { + if (this.__videoElement.paused) { + this.controls.play.querySelector("i").classList.replace("bi-pause-fill", "bi-play-fill"); + } else { + this.controls.play.querySelector("i").classList.replace("bi-play-fill", "bi-pause-fill"); + } + } + this.__videoElement.onplay = () => updatePlayButtons(); + this.__videoElement.onpause = () => updatePlayButtons(); + updatePlayButtons(); + this.__videoElement.onclick = e => this.toggleControls(e); + this.controls.container.onclick = e => this.toggleControls(e); + this.__videoElement.onclick = e => this.toggleControls(e); + + switch (this.externalPlayerType) { + case "shaka": + externalPlayer.addEventListener("variantchanged", () => { + this.updateMenu(); + }); + externalPlayer.addEventListener('error', this.fallbackFromShaka); + break; + case "hls.js": + // uhhhhhh... + break; + } + + // buffering + this.bufferingScreen = document.createElement("div"); + this.bufferingScreen.classList.add("player-buffering"); + this.container.appendChild(this.bufferingScreen); + + let bufferingSpinner = document.createElement("img"); + bufferingSpinner.classList.add("player-buffering-spinner"); + bufferingSpinner.src = "/img/spinner.gif"; + this.bufferingScreen.appendChild(bufferingSpinner); + + setInterval(() => this.update(), 100); + } + + togglePlayPause(e) { + if (this.__videoElement.paused) + this.__videoElement.play(); + else + this.__videoElement.pause(); + } + + updateMenu() { + // todo: mobile resolution switching + } + + fullscreen() { + if (!document.fullscreenElement) { + this.container.requestFullscreen(); + } else { + document.exitFullscreen(); + } + } + + timeUpdate() { + if (this.info.live) { + let timeBack = this.__videoElement.duration - this.__videoElement.currentTime; + this.controls.time.innerHTML = timeBack > 10 ? this.getTimeString(timeBack) : "LIVE"; + } else { + this.controls.time.innerHTML = this.getTimeString(this.__videoElement.currentTime); + this.controls.duration.innerHTML = this.getTimeString(this.__videoElement.duration); + } + this.playbackBar.played.style.width = ((this.__videoElement.currentTime / this.__videoElement.duration) * 100) + "%"; + this.playbackBar.buffered.style.width = ((this.getLoadEnd() / this.__videoElement.duration) * 100) + "%"; + } + + setVolume(e) { + this.__videoElement.volume = 1; + localStorage.setItem("ltvideo.volume", 1); + } + + getLoadEnd() { + let longest = -1; + for (let i = 0; i < this.__videoElement.buffered.length; i++) { + const end = this.__videoElement.buffered.end(i); + if (end > longest) longest = end; + } + return longest; + } + + playbackBarSeek(e) { + let percentage = (e.offsetX / (this.playbackBar.bg.clientLeft + this.playbackBar.bg.clientWidth)); + this.playbackBar.played.style.width = (percentage * 100) + "%"; + this.__videoElement.currentTime = this.__videoElement.duration * percentage; + } + + getTimeString(s) { + let res = s < 3600 ? new Date(s * 1000).toISOString().substr(14, 5) : new Date(s * 1000).toISOString().substr(11, 8); + if (res.startsWith("0")) + res = res.substr(1); + return res; + } + + update() { + this.timeUpdate(); + + if (this.info.live) { + let timeBack = Math.abs(this.__videoElement.currentTime - this.__videoElement.buffered.end(this.__videoElement.buffered.length - 1)); + this.bufferingScreen.style.display = timeBack < .1 ? "flex" : "none"; + } else { + switch (this.__videoElement.readyState) { + case 1: + this.bufferingScreen.style.display = "flex"; + break; + default: + this.bufferingScreen.style.display = "none"; + break; + } + } + } + + async fallbackFromShaka() { + if (this.externalPlayerType !== "shaka") return; + this.externalPlayerType = "html5"; + console.log("Shaka player crashed, falling back"); + let cTime = this.__videoElement.currentTime; + await this.__externalPlayer.detach(); + await this.__externalPlayer.destroy(); + this.__videoElement.src = this.sources[0].src; + this.__externalPlayer = undefined; + this.__videoElement.currentTime = cTime; + this.updateMenu(); + console.log("Fallback complete!"); + } + + toggleControls(e) { + if (["DIV", "VIDEO"].includes(e.target.tagName)) + if (this.container.classList.contains("hide-controls")) { + this.container.classList.remove("hide-controls") + } else { + this.container.classList.add("hide-controls") + } + } +} + +const loadPlayerWithShaka = async (query, info, sources, manifestUri) => { + let player; + if (manifestUri !== undefined) { + shaka.polyfill.installAll(); + let shakaUsable = shaka.Player.isBrowserSupported(); + + if (shakaUsable) { + const video = document.querySelector(query); + player = new shaka.Player(video); + + try { + await player.load(manifestUri); + } catch (e) { + await player.destroy(); + return new Player(query, info, sources, undefined, "html5"); + } + } + } + + return new Player(query, info, sources, await player, "shaka"); +} + +const loadPlayerWithHls = (query, info, manifestUri) => { + return new Promise((res, rej) => { + let hls; + + const video = document.querySelector(query); + + if (Hls.isSupported()) { + hls = new Hls(); + hls.loadSource(manifestUri); + hls.attachMedia(video); + hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) { + res(new Player(query, info, [], hls, "hls.js")); + }); + } else + rej("You can't watch livestreams / premieres because hls.js is not supported in your browser.") + }) +} \ No newline at end of file diff --git a/core/LightTube/wwwroot/js/shaka-player/shaka-player.compiled.min.js b/core/LightTube/wwwroot/js/shaka-player/shaka-player.compiled.min.js new file mode 100644 index 00000000..29107cb9 --- /dev/null +++ b/core/LightTube/wwwroot/js/shaka-player/shaka-player.compiled.min.js @@ -0,0 +1,32 @@ +/* + @license + Shaka Player + Copyright 2016 Google LLC + SPDX-License-Identifier: Apache-2.0 +*/ +!function(){var e="undefined"!=typeof window?window:global,t={};if(function(e,t,n){var i;function r(e){var t=0;return function(){return t>>0)+"_",i=0;return function e(r){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new t(n+(r||"")+"_"+i++,r)}}),s("Symbol.iterator",function(e){if(e)return e;e=Symbol("Symbol.iterator");for(var t="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),n=0;nr&&(r=Math.max(r+i,0));r=r}}),s("Array.prototype.keys",function(e){return e||function(){return O(this,function(e){return e})}});var U="function"==typeof Object.assign?Object.assign:function(e,t){for(var n=1;ne||1342177279>>=1)&&(t+=t);return n}}),s("Object.values",function(e){return e||function(e){var t,n=[];for(t in e)L(e,t)&&n.push(e[t]);return n}}),s("Math.log2",function(e){return e||function(e){return Math.log(e)/Math.LN2}}),s("Object.entries",function(e){return e||function(e){var t,n=[];for(t in e)L(e,t)&&n.push([t,e[t]]);return n}});var F=this||self;function B(e,t){var n,i=e.split("."),r=F;i[0]in r||void 0===r.execScript||r.execScript("var "+i[0]);for(;i.length&&(n=i.shift());)i.length||void 0===t?r=r[n]&&r[n]!==Object.prototype[n]?r[n]:r[n]={}:r[n]=t} +/* + @license + Shaka Player + Copyright 2016 Google LLC + SPDX-License-Identifier: Apache-2.0 +*/ +function V(e){this.i=Math.exp(Math.log(.5)/e),this.h=this.g=0}function H(e,t,n){var i=Math.pow(e.i,t);n=n*(1-i)+i*e.g,isNaN(n)||(e.g=n,e.h+=t)}function K(e){return e.g/(1-Math.pow(e.i,e.h))}function G(){this.h=new V(2),this.i=new V(5),this.g=0}function q(){}function z(){}function X(){}function W(e,t){for(var n=[],i=1;ithis.g?e:Math.min(K(this.h),K(this.i))};var $=new Set;if(e.console&&e.console.log.bind){var J={},Q=(J[1]=console.error.bind(console),J[2]=console.warn.bind(console),J[3]=console.info.bind(console),J[4]=console.log.bind(console),J[5]=console.debug.bind(console),J[6]=console.debug.bind(console),J);X=Q[2],z=Q[1]}function Z(e,t){for(var n=[],i=l(e),r=i.next();!r.done;r=i.next())n.push(t(r.value));return n}var ee=function e(t){var n;return N(e,function(e){return 1==e.g&&(n=0),3!=e.g?n=n[e]}if(!e)return"";var n=oe(e);if(239==n[0]&&187==n[1]&&191==n[2])return fe(n);if(254==n[0]&&255==n[1])return he(n.subarray(2),!1);if(255==n[0]&&254==n[1])return he(n.subarray(2),!0);if(0==n[0]&&0==n[2])return he(e,!1);if(0==n[1]&&0==n[3])return he(e,!0);if(t(0)&&t(1)&&t(2)&&t(3))return fe(e);throw new le(2,2,2003)}function ge(e){return ae((new TextEncoder).encode(e))}function me(e,t){for(var n=new ArrayBuffer(2*e.length),i=new DataView(n),r=l(te(e)),a=r.next();!a.done;a=r.next())a=a.value,i.setUint16(2*a.ga,a.item.charCodeAt(0),t);return n}B("shaka.util.BufferUtils",ne),ne.toDataView=se,ne.toUint8=oe,ne.toArrayBuffer=ae,ne.equal=ie,le.prototype.toString=function(){return"shaka.util.Error "+JSON.stringify(this,null," ")},B("shaka.util.Error",le),le.Severity={RECOVERABLE:1,CRITICAL:2},le.Category={NETWORK:1,TEXT:2,MEDIA:3,MANIFEST:4,STREAMING:5,DRM:6,PLAYER:7,CAST:8,STORAGE:9,ADS:10},le.Code={UNSUPPORTED_SCHEME:1e3,BAD_HTTP_STATUS:1001,HTTP_ERROR:1002,TIMEOUT:1003,MALFORMED_DATA_URI:1004,REQUEST_FILTER_ERROR:1006,RESPONSE_FILTER_ERROR:1007,MALFORMED_TEST_URI:1008,UNEXPECTED_TEST_REQUEST:1009,ATTEMPTS_EXHAUSTED:1010,INVALID_TEXT_HEADER:2e3,INVALID_TEXT_CUE:2001,UNABLE_TO_DETECT_ENCODING:2003,BAD_ENCODING:2004,INVALID_XML:2005,INVALID_MP4_TTML:2007,INVALID_MP4_VTT:2008,UNABLE_TO_EXTRACT_CUE_START_TIME:2009,INVALID_MP4_CEA:2010,TEXT_COULD_NOT_GUESS_MIME_TYPE:2011,CANNOT_ADD_EXTERNAL_TEXT_TO_SRC_EQUALS:2012,TEXT_ONLY_WEBVTT_SRC_EQUALS:2013,MISSING_TEXT_PLUGIN:2014,BUFFER_READ_OUT_OF_BOUNDS:3e3,JS_INTEGER_OVERFLOW:3001,EBML_OVERFLOW:3002,EBML_BAD_FLOATING_POINT_SIZE:3003,MP4_SIDX_WRONG_BOX_TYPE:3004,MP4_SIDX_INVALID_TIMESCALE:3005,MP4_SIDX_TYPE_NOT_SUPPORTED:3006,WEBM_CUES_ELEMENT_MISSING:3007,WEBM_EBML_HEADER_ELEMENT_MISSING:3008,WEBM_SEGMENT_ELEMENT_MISSING:3009,WEBM_INFO_ELEMENT_MISSING:3010,WEBM_DURATION_ELEMENT_MISSING:3011,WEBM_CUE_TRACK_POSITIONS_ELEMENT_MISSING:3012,WEBM_CUE_TIME_ELEMENT_MISSING:3013,MEDIA_SOURCE_OPERATION_FAILED:3014,MEDIA_SOURCE_OPERATION_THREW:3015,VIDEO_ERROR:3016,QUOTA_EXCEEDED_ERROR:3017,TRANSMUXING_FAILED:3018,CONTENT_TRANSFORMATION_FAILED:3019,UNABLE_TO_GUESS_MANIFEST_TYPE:4e3,DASH_INVALID_XML:4001,DASH_NO_SEGMENT_INFO:4002,DASH_EMPTY_ADAPTATION_SET:4003,DASH_EMPTY_PERIOD:4004,DASH_WEBM_MISSING_INIT:4005,DASH_UNSUPPORTED_CONTAINER:4006,DASH_PSSH_BAD_ENCODING:4007,DASH_NO_COMMON_KEY_SYSTEM:4008,DASH_MULTIPLE_KEY_IDS_NOT_SUPPORTED:4009,DASH_CONFLICTING_KEY_IDS:4010,RESTRICTIONS_CANNOT_BE_MET:4012,HLS_PLAYLIST_HEADER_MISSING:4015,INVALID_HLS_TAG:4016,HLS_INVALID_PLAYLIST_HIERARCHY:4017,DASH_DUPLICATE_REPRESENTATION_ID:4018,HLS_MULTIPLE_MEDIA_INIT_SECTIONS_FOUND:4020,HLS_MASTER_PLAYLIST_NOT_PROVIDED:4022,HLS_REQUIRED_ATTRIBUTE_MISSING:4023,HLS_REQUIRED_TAG_MISSING:4024,HLS_COULD_NOT_GUESS_CODECS:4025,HLS_KEYFORMATS_NOT_SUPPORTED:4026,DASH_UNSUPPORTED_XLINK_ACTUATE:4027,DASH_XLINK_DEPTH_LIMIT:4028,HLS_COULD_NOT_PARSE_SEGMENT_START_TIME:4030,CONTENT_UNSUPPORTED_BY_BROWSER:4032,CANNOT_ADD_EXTERNAL_TEXT_TO_LIVE_STREAM:4033,HLS_AES_128_ENCRYPTION_NOT_SUPPORTED:4034,HLS_INTERNAL_SKIP_STREAM:4035,NO_VARIANTS:4036,PERIOD_FLATTENING_FAILED:4037,INCONSISTENT_DRM_ACROSS_PERIODS:4038,HLS_VARIABLE_NOT_FOUND:4039,STREAMING_ENGINE_STARTUP_INVALID_STATE:5006,NO_RECOGNIZED_KEY_SYSTEMS:6e3,REQUESTED_KEY_SYSTEM_CONFIG_UNAVAILABLE:6001,FAILED_TO_CREATE_CDM:6002,FAILED_TO_ATTACH_TO_VIDEO:6003,INVALID_SERVER_CERTIFICATE:6004,FAILED_TO_CREATE_SESSION:6005,FAILED_TO_GENERATE_LICENSE_REQUEST:6006,LICENSE_REQUEST_FAILED:6007,LICENSE_RESPONSE_REJECTED:6008,ENCRYPTED_CONTENT_WITHOUT_DRM_INFO:6010,NO_LICENSE_SERVER_GIVEN:6012,OFFLINE_SESSION_REMOVED:6013,EXPIRED:6014,SERVER_CERTIFICATE_REQUIRED:6015,INIT_DATA_TRANSFORM_ERROR:6016,LOAD_INTERRUPTED:7e3,OPERATION_ABORTED:7001,NO_VIDEO_ELEMENT:7002,OBJECT_DESTROYED:7003,CONTENT_NOT_LOADED:7004,CAST_API_UNAVAILABLE:8e3,NO_CAST_RECEIVERS:8001,ALREADY_CASTING:8002,UNEXPECTED_CAST_ERROR:8003,CAST_CANCELED_BY_USER:8004,CAST_CONNECTION_TIMED_OUT:8005,CAST_RECEIVER_APP_UNAVAILABLE:8006,STORAGE_NOT_SUPPORTED:9e3,INDEXED_DB_ERROR:9001,DEPRECATED_OPERATION_ABORTED:9002,REQUESTED_ITEM_NOT_FOUND:9003,MALFORMED_OFFLINE_URI:9004,CANNOT_STORE_LIVE_OFFLINE:9005,NO_INIT_DATA_FOR_OFFLINE:9007,LOCAL_PLAYER_INSTANCE_REQUIRED:9008,NEW_KEY_OPERATION_NOT_SUPPORTED:9011,KEY_NOT_FOUND:9012,MISSING_STORAGE_CELL:9013,STORAGE_LIMIT_REACHED:9014,DOWNLOAD_SIZE_CALLBACK_ERROR:9015,CS_IMA_SDK_MISSING:1e4,CS_AD_MANAGER_NOT_INITIALIZED:10001,SS_IMA_SDK_MISSING:10002,SS_AD_MANAGER_NOT_INITIALIZED:10003,CURRENT_DAI_REQUEST_NOT_FINISHED:10004},ce.prototype.value=function(){return null==this.g&&(this.g=this.h()),this.g},B("shaka.util.StringUtils",de),de.resetFromCharCode=function(){ve.g=void 0},de.toUTF16=me,de.toUTF8=ge,de.fromBytesAutoDetect=pe,de.fromUTF16=he,de.fromUTF8=fe;var ve=new ce(function(){function e(e){try{var t=new Uint8Array(e);return 0this.R.byteLength)throw be();var t=oe(this.R,this.g,e);return this.g+=e,t},i.skip=function(e){if(this.g+e>this.R.byteLength)throw be();this.g+=e},i.me=function(e){if(this.ge||e>this.R.byteLength)throw be();this.g=e},i.cc=function(){for(var e=this.g;this.pa()&&0!=this.R.getUint8(this.g);)this.g+=1;return e=oe(this.R,e,this.g-e),this.g+=1,fe(e)},B("shaka.util.DataViewReader",ye),ye.prototype.readTerminatedString=ye.prototype.cc,ye.prototype.seek=ye.prototype.seek,ye.prototype.rewind=ye.prototype.me,ye.prototype.skip=ye.prototype.skip,ye.prototype.readBytes=ye.prototype.bb,ye.prototype.readUint64=ye.prototype.Hb,ye.prototype.readInt32=ye.prototype.ke,ye.prototype.readUint32=ye.prototype.N,ye.prototype.readUint16=ye.prototype.Gb,ye.prototype.readUint8=ye.prototype.aa,ye.prototype.getLength=ye.prototype.Te,ye.prototype.getPosition=ye.prototype.$,ye.prototype.hasMoreData=ye.prototype.pa;var we=1;function Te(e,t){this.g=e,this.h=t}function xe(e,t){var n=new Te(4,0),i=Ae,r=i.g,a=n.h-r.h;(0<(n.g-r.g||a)?i.i:i.h)(i.g,n,e,t)}function Se(e,t,n,i){X([n,"has been deprecated and will be removed in",t,". We are currently at version",e,". Additional information:",i].join(" "))}function Ee(e,t,n,i){z([n,"has been deprecated and has been removed in",t,". We are now at version",e,". Additional information:",i].join(""))}ye.Endianness={BIG_ENDIAN:0,LITTLE_ENDIAN:we},Te.prototype.toString=function(){return"v"+this.g+"."+this.h};var Ae=null;function ke(e,t){return e.concat(t)}function Ie(){}function Me(e){return null!=e}function Ce(e){var t=Object.create(e.prototype||Object.prototype);try{var n=e.call(t);n||(xe("Factories requiring new","Factories should be plain functions"),n=t)}catch(t){xe("Factories requiring new","Factories should be plain functions"),n=new e}return n}function De(){this.i=[],this.h=[],this.g=!1}function Re(e){for(var t=_e(e);e.reader.pa()&&!e.parser.g;)e.parser.Kc(e.start+t,e.reader,e.partialOkay)}function Ne(e){for(var t=_e(e),n=e.reader.N(),i=(n=l(ee(n))).next();!i.done&&(e.parser.Kc(e.start+t,e.reader,e.partialOkay),!e.parser.g);i=n.next());}function Pe(e){return function(t){e(t.reader.bb(t.reader.R.byteLength-t.reader.$()))}}function Le(e){for(var t=0,n=(e=l(e)).next();!n.done;n=e.next())t=t<<8|n.value.charCodeAt(0);return t}function je(e){return String.fromCharCode(e>>24&255,e>>16&255,e>>8&255,255&e)}function _e(e){return 8+(e.has64BitSize?8:0)+(null!=e.flags?4:0)}(i=De.prototype).box=function(e,t){var n=Le(e);return this.i[n]=Oe,this.h[n]=t,this},i.T=function(e,t){var n=Le(e);return this.i[n]=Ue,this.h[n]=t,this},i.stop=function(){this.g=!0},i.parse=function(e,t,n){for(e=new ye(e,0),this.g=!1;e.pa()&&!this.g;)this.Kc(0,e,t,n)},i.Kc=function(e,t,n,i){var r=t.$();if(i&&r+8>t.R.byteLength)this.g=!0;else{var a=t.N(),o=t.N(),s=!1;switch(a){case 0:a=t.R.byteLength-r;break;case 1:if(i&&t.$()+8>t.R.byteLength)return void(this.g=!0);a=t.Hb(),s=!0}var u=this.h[o];if(u){var l=null,c=null;if(this.i[o]==Ue){if(i&&t.$()+4>t.R.byteLength)return void(this.g=!0);l=(c=t.N())>>>24,c&=16777215}o=r+a,n&&o>t.R.byteLength&&(o=t.R.byteLength),i&&o>t.R.byteLength?this.g=!0:u({parser:this,partialOkay:n||!1,version:l,flags:c,reader:t=new ye(t=0<(i=o-t.$())?t.bb(i):new Uint8Array(0),0),size:a,start:r+e,has64BitSize:s})}else t.skip(Math.min(r+a-t.$(),t.R.byteLength-t.$()))}},B("shaka.util.Mp4Parser",De),De.headerSize=_e,De.typeToString=je,De.allData=Pe,De.sampleDescription=Ne,De.children=Re,De.prototype.parseNext=De.prototype.Kc,De.prototype.parse=De.prototype.parse,De.prototype.stop=De.prototype.stop,De.prototype.fullBox=De.prototype.T,De.prototype.box=De.prototype.box;var Oe=0,Ue=1;function Fe(e){this.h=e,this.g=null}function Be(e){this.h=e,this.g=null}function Ve(){return!(!e.MediaSource||!MediaSource.isTypeSupported)}function He(e){return""!=Ye().canPlayType(e)}function Ke(){return We("Xbox One")}function Ge(){return We("Tizen")}function qe(){return We("CrKey")}function ze(){return!!navigator.vendor&&navigator.vendor.includes("Apple")&&!Ge()}function Xe(){if(!ze())return null;var e=navigator.userAgent.match(/Version\/(\d+)/);return e?parseInt(e[1],10):(e=navigator.userAgent.match(/OS (\d+)(?:_\d+)?/))?parseInt(e[1],10):null}function We(e){return(navigator.userAgent||"").includes(e)}function Ye(){return Je||($e||($e=new Be(function(){Je=null})),(Je=document.getElementsByTagName("video")[0]||document.getElementsByTagName("audio")[0])||(Je=document.createElement("video")),$e.V(1),Je)}Fe.prototype.V=function(t){var n=this;this.stop();var i=!0,r=null;return this.g=function(){e.clearTimeout(r),i=!1},r=e.setTimeout(function(){i&&n.h()},1e3*t),this},Fe.prototype.stop=function(){this.g&&(this.g(),this.g=null)},Be.prototype.hc=function(){return this.stop(),this.h(),this},Be.prototype.V=function(e){var t=this;return this.stop(),this.g=new Fe(function(){t.h()}).V(e),this},Be.prototype.Da=function(e){var t=this;return this.stop(),this.g=new Fe(function(){t.g.V(e),t.h()}).V(e),this},Be.prototype.stop=function(){this.g&&(this.g.stop(),this.g=null)},B("shaka.util.Timer",Be),Be.prototype.stop=Be.prototype.stop,Be.prototype.tickEvery=Be.prototype.Da,Be.prototype.tickAfter=Be.prototype.V,Be.prototype.tickNow=Be.prototype.hc;var $e=null,Je=null;function Qe(){}function Ze(e){return e=oe(e),e=ve.value()(e),btoa(e)}function et(e,t){t=null==t||t;var n=Ze(e).replace(/\+/g,"-").replace(/\//g,"_");return t?n:n.replace(/[=]*$/,"")}function tt(t){var n=e.atob(t.replace(/-/g,"+").replace(/_/g,"/"));t=new Uint8Array(n.length);for(var i=(n=l(te(n))).next();!i.done;i=n.next())t[(i=i.value).ga]=i.item.charCodeAt(0);return t}function nt(t){for(var n=t.length/2,i=new Uint8Array(n),r=(n=l(ee(n))).next();!r.done;r=n.next())i[r=r.value]=e.parseInt(t.substr(2*r,2),16);return i}function it(e){var t=oe(e);e="";for(var n=(t=l(t)).next();!n.done;n=t.next())1==(n=(n=n.value).toString(16)).length&&(n="0"+n),e+=n;return e}function rt(e){for(var t=[],n=0;n>32),e.setUint32(12,4294967295&n)):e.setUint32(0,n))}B("shaka.util.Uint8ArrayUtils",Qe),Qe.concat=rt,Qe.toHex=it,Qe.fromHex=nt,Qe.fromBase64=tt,Qe.toBase64=et,Qe.toStandardBase64=Ze,Qe.equal=function(e,t){return xe("shaka.util.Uint8ArrayUtils.equal","Please use shaka.util.BufferUtils.equal instead."),ie(e,t)};var st=new ce(function(){return new Uint8Array([0,0,0,80,115,105,110,102,0,0,0,12,102,114,109,97,0,0,0,0,0,0,0,20,115,99,104,109,0,0,0,0,99,101,110,99,0,1,0,0,0,0,0,40,115,99,104,105,0,0,0,32,116,101,110,99,0,0,0,0,0,0,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])});function ut(e,t){return!("number"!=typeof e||"number"!=typeof t||!isNaN(e)||!isNaN(t))||e===t}function lt(e,t){var n=e.indexOf(t);-1=r)return null;for(var a=-1,o=-1,s=0;st;t++)e.i.push(Ut())}function Ut(){for(var e=[],t=0;42>t;t++)e.push(null);return e}function Ft(e,t){Bt(e)&&(e.i[e.h][e.g]=new jt(t,e.C,e.s,e.m,e.u),e.g++)}function Bt(e){var t=e.g=n)i=7&n,e.h[i]&&(e.g=e.h[i]);else{if(136===n){n=Xt(t).value,t=null;for(var r=(n=l($t(e,n))).next();!r.done;r=n.next())(r=e.h[r.value]).isVisible()&&(t=Vt(r,i,e.i)),Ot(r);return t}if(137===n)for(t=Xt(t).value,n=(t=l($t(e,t))).next();!n.done;n=t.next())(n=e.h[n.value]).isVisible()||(n.j=i),n.l=!0;else{if(138===n){for(n=Xt(t).value,t=null,r=(n=l($t(e,n))).next();!r.done;r=n.next())(r=e.h[r.value]).isVisible()&&(t=Vt(r,i,e.i)),r.l=!1;return t}if(139===n){for(n=Xt(t).value,t=null,r=(n=l($t(e,n))).next();!r.done;r=n.next())(r=e.h[r.value]).isVisible()?t=Vt(r,i,e.i):r.j=i,r.l=!r.l;return t}if(140===n)return Jt(e,t=Xt(t).value,i);if(143===n)return i=Jt(e,255,i),Qt(e),i;if(144===n)t.skip(1),i=Xt(t).value,e.g&&(e.g.s=0<(128&i),e.g.C=0<(64&i));else if(145===n)i=Xt(t).value,n=Xt(t).value,t.skip(1),e.g&&(t=Zt((48&n)>>4,(12&n)>>2,3&n),e.g.u=Zt((48&i)>>4,(12&i)>>2,3&i),e.g.m=t);else if(146===n)i=Xt(t).value,t=Xt(t).value,e.g&&((e=e.g).h=15&i,e.g=63&t);else if(151===n)t.skip(1),t.skip(1),i=Xt(t).value,t.skip(1),e.g&&(e.g.H=3&i);else if(152<=n&&159>=n){if(n=(15&n)-8,!(r=null!==e.h[n])){var a=new _t;a.j=i,e.h[n]=a}i=Xt(t).value,Xt(t),Xt(t),a=Xt(t).value;var o=Xt(t).value;t=Xt(t).value,r&&0==(7&t)||((t=e.h[n]).h=0,t.g=0,t.C=!1,t.s=!1,t.u="white",t.m="black"),(t=e.h[n]).l=0<(32&i),t.I=1+(15&a),t.F=1+(63&o),e.g=e.h[n]}}}return null}zt.prototype.pa=function(){return this.gthis.h.length)throw new le(2,2,3e3);this.g+=e};var $t=function e(t,n){var i;return N(e,function(e){return 1==e.g&&(i=0),5!=e.g?8>i?1==(1&n)&&t.h[i]?w(e,i,5):e.v(5):e.v(0):(n>>=1,i++,e.v(2))})};function Jt(e,t,n){for(var i=null,r=(t=l($t(e,t))).next();!r.done;r=t.next()){r=r.value;var a=e.h[r];a.isVisible()&&(i=Vt(a,n,e.i)),e.h[r]=null}return i}function Qt(e){e.g=null,e.h=[null,null,null,null,null,null,null,null]}function Zt(e,t,n){var i={0:0,1:0,2:1,3:1};return tn[(e=i[e])<<2|(t=i[t])<<1|(n=i[n])]}var en=new Map([[32," "],[33," "],[37,"…"],[42,"Š"],[44,"Œ"],[48,"█"],[49,"‘"],[50,"’"],[51,"“"],[52,"”"],[53,"•"],[57,"™"],[58,"š"],[60,"œ"],[61,"℠"],[63,"Ÿ"],[118,"⅛"],[119,"⅜"],[120,"⅝"],[121,"⅞"],[122,"│"],[123,"┐"],[124,"└"],[125,"─"],[126,"┘"],[127,"┌"]]),tn="black blue green cyan red magenta yellow white".split(" ");function nn(e,t){this.i=[],this.g=1,this.h=0,this.C=e,this.u=t,this.j=this.m=!1,this.l="white",this.s="black",an(this)}function rn(e,t,n){return Nt(new ft(t,n,""),"CC"+(e.C<<1|e.u+1),e.i,t,n)}function an(e){un(e,0,15),e.g=1}function on(e,t,n){if(!(32>n||127=n)for(--i;0<=i;i--)e.i[t+i]=e.i[n+i].map(function(e){return e});else for(var r=0;r>3&1;0===n?e.m=i:e.s=i}if(n=e.u.get("CC"+(n<<1|(n?e.s:e.m)+1)),255===t.Ba&&255===t.Ta||!t.Ba&&!t.Ta||!Dn(t.Ba)||!Dn(t.Ta))return 45<=++e.l&&In(e),null;if(e.l=0,t.Ba&=127,t.Ta&=127,!t.Ba&&!t.Ta)return null;if(i=null,16==(112&t.Ba))e:{var r=t.Ba;if(i=t.Ta,n.m===(r<<8|i))n.m=null;else if(n.m=r<<8|i,16==(240&r)&&64==(192&i)){r=[11,11,1,2,3,4,12,13,14,15,5,6,7,8,9,10][(7&r)<<1|i>>5&1];var a=(30&i)>>1,o="white",s=!1;if(7>a?o=kn[a]:7===a&&(s=!0),i=1==(1&i),n.h!==En){if(a=n.g,n.h===Sn&&r!==a.g){var u=1+r-a.h;sn(a,u,1+a.g-a.h,a.h),un(a,0,u-1),un(a,r+1,15-r)}a.g=r,n.g.m=i,n.g.j=s,n.g.l=o,n.g.s="black"}}else if(17==(247&r)&&32==(240&i))n.g.m=!1,n.g.j=!1,n.g.l="white",on(n.g,ln,32),o=!1,"white_italics"===(r=kn[(14&i)>>1])&&(r="white",o=!0),n.g.m=1==(1&i),n.g.j=o,n.g.l=r;else if(16==(247&r)&&32==(240&i)||23==(247&r)&&45==(255&i))o="black",0==(7&r)&&(o=An[(14&i)>>1]),n.g.s=o;else if(17==(247&r)&&48==(240&i))on(n.g,cn,i);else if(18==(246&r)&&32==(224&i))on(n.g,1&r?fn:dn,i);else if(20==(246&r)&&32==(240&i)){switch(i=t.pts,r=null,t.Ta){case 32:bn(n);break;case 33:(n=n.g).i[n.g].pop();break;case 37:r=yn(n,2,i);break;case 38:r=yn(n,3,i);break;case 39:r=yn(n,4,i);break;case 40:on(n.g,ln,32);break;case 41:n.h=2,n.g=n.i,n.g.h=0,n.j=i;break;case 42:an(n.s),wn(n);break;case 43:wn(n);break;case 44:r=n.i,o=null,n.h!==En&&(o=rn(r,n.j,i)),un(r,0,15),r=o;break;case 45:r=n.g,n.h!==Sn?r=null:(o=rn(r,n.j,i),sn(r,(s=r.g-r.h+1)-1,s,r.h),un(r,0,s-1),un(r,r.g,15-r.g),n.j=i,r=o);break;case 46:un(n.l,0,15);break;case 47:r=null,n.h!==En&&(r=rn(n.i,n.j,i)),o=n.l,n.l=n.i,n.i=o,bn(n),n.j=i}i=r;break e}i=null}else r=t.Ta,on(n.g,ln,t.Ba),on(n.g,ln,r);return i}function Cn(e,t){var n=[];try{for(;t.pa();){var i=Xt(t).value,r=(224&i)>>5,a=31&i;if(7===r&&0!=a&&(r=63&Xt(t).value),0!=r){e.j.has(r)||e.j.set(r,new Wt(r));for(var o=e.j.get(r),s=t.$();t.$()-s=l){var d=c;if(o.g){var f=o.g;switch(r=null,l){case 8:!Bt(f)||0>=f.g&&0>=f.h||(0>=f.g?(f.g=f.F-1,f.h--):f.g--,f.i[f.h][f.g]=null);break;case 13:if(f.isVisible()&&(r=Vt(f,d,o.i)),f.h+1>=f.I){d=f;for(var h=0,p=1;15>p;p++,h++)d.i[h]=d.i[p];for(p=0;1>p;p++,h++)d.i[h]=Ut()}else f.h++;f.g=0;break;case 14:f.isVisible()&&(r=Vt(f,d,o.i)),f.i[f.h]=Ut(),f.g=0;break;case 12:f.isVisible()&&(r=Vt(f,d,o.i)),Ot(f),(d=f).h=0,d.g=0}var g=r}else g=null}else if(128<=l&&159>=l)g=Yt(o,r,l,c);else{if(4096<=l&&4127>=l)8<=(d=255&l)&&15>=d?r.skip(1):16<=d&&23>=d?r.skip(2):24<=d&&31>=d&&r.skip(3);else if(4224<=l&&4255>=l)128<=(d=255&l)&&135>=d?r.skip(4):136<=d&&143>=d&&r.skip(5);else if(32<=l&&127>=l)r=l,o.g&&Ft(o.g,127===r?"♪":String.fromCharCode(r));else if(160<=l&&255>=l)o.g&&Ft(o.g,String.fromCharCode(l));else if(4128<=l&&4223>=l){if(r=255&l,o.g)if(en.has(r)){var m=en.get(r);Ft(o.g,m)}else Ft(o.g,"_")}else 4256<=l&&4351>=l&&o.g&&Ft(o.g,160!=(255&l)?"_":"[CC]");g=null}(r=g)&&n.push(r)}}}}catch(e){if(!(e instanceof le&&3e3===e.code))throw e;W("CEA708_INVALID_DATA","Buffer read out of bounds / invalid CEA-708 Data.")}return n}function Dn(e){for(var t=0;e;)t^=1&e,e>>=1;return 1===t}var Rn=function e(t,n){var i,r,a,o;return N(e,function(e){if(1==e.g){for(var t=n,s=0,u=0;u>2,f=a.aa(),h=a.aa();d&&(0===(u&=3)||1===u?i.h.push({pts:r,type:u,Ba:f,Ta:h,order:i.h.length}):(i.g.push({pts:r,type:u,value:f,order:i.g.length}),i.g.push({pts:r,type:2,value:h,order:i.g.length})))}}}}return function(e){function t(e,t){return e.pts-t.pts||e.order-t.order}var n=[];e.h.sort(t),e.g.sort(t);for(var i=l(e.h),r=i.next();!r.done;r=i.next())(r=Mn(e,r.value))&&n.push(r);for(r=(i=l(e.g)).next();!r.done;r=i.next())qt(e.i,r.value);for(r=(i=l(e.i.i)).next();!r.done;r=i.next())r=Cn(e,r.value),n.push.apply(n,c(r));return e.i.i=[],e.h=[],e.g=[],n}(e.g)}function Fn(e){return!e||1==e.length&&1e-6>e.end(0)-e.start(0)?null:e.length?e.end(e.length-1):null}function Bn(e,t,n){return n=void 0===n?0:n,!(!e||!e.length||1==e.length&&1e-6>e.end(0)-e.start(0)||t>e.end(e.length-1))&&t+n>=e.start(0)}function Vn(e,t){if(!e||!e.length||1==e.length&&1e-6>e.end(0)-e.start(0))return 0;for(var n=0,i=l(Hn(e)),r=i.next();!r.done;r=i.next()){var a=r.value;r=a.start,(a=a.end)>t&&(n+=a-Math.max(r,t))}return n}function Hn(e){if(!e)return[];for(var t=[],n=l(ee(e.length)),i=n.next();!i.done;i=n.next())i=i.value,t.push({start:e.start(i),end:e.end(i)});return t}_n.prototype.init=function(e){var t=this,n=[],i=[];if((new De).box("moov",Re).box("mvex",Re).T("trex",function(e){var n=e.reader;n.skip(4),n.skip(4),e=n.N(),n=n.N(),t.g=e,t.h=n}).box("trak",Re).T("tkhd",function(e){var t=e.reader;1==e.version?(t.skip(8),t.skip(8)):(t.skip(4),t.skip(4)),e=t.N(),n.push(e)}).box("mdia",Re).T("mdhd",function(e){e=Ln(e.reader,e.version),i.push(e.timescale)}).parse(e,!0),!n.length||!i.length||n.length!=i.length)throw new le(2,2,2010);n.forEach(function(e,n){t.i.set(e,i[n])})},_n.prototype.parse=function(e){var t=this,n=[],i=this.g,r=this.h,a=[],o=null,s=9e4;return(new De).box("moof",Re).box("traf",Re).T("trun",function(e){a=jn(e.reader,e.version,e.flags).ne}).T("tfhd",function(e){e=Nn(e.reader,e.flags),i=e.Xd||t.g,r=e.Le||t.h,e=e.trackId,t.i.has(e)&&(s=t.i.get(e))}).T("tfdt",function(e){o=Pn(e.reader,e.version).fd}).box("mdat",function(e){if(null===o)throw new le(2,2,2010);e=e.reader;var u=o,c=s,d=i,f=r,h=a,p=0,g=f;for(h.length&&(g=h[0].sampleSize||f);e.pa();){var m=e.N();if(6==(31&e.aa())){var v=0;h.length>p&&(v=h[p].Mc||0),v=(u+v)/c;for(var y=l(Rn(t.j,e.bb(m-1))),b=y.next();!b.done;b=y.next())n.push({tf:b.value,pts:v})}else e.skip(m-1);0==(g-=m+4)&&(u=h.length>p?u+(h[p].Gd||d):u+d,p++,g=h.length>p&&h[p].sampleSize||f)}}).parse(e,!1),n},On.prototype.init=function(e){this.h.init(e)}; +/* + @license + Copyright 2008 The Closure Library Authors + SPDX-License-Identifier: Apache-2.0 +*/ +var Kn=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#(.*))?$/; +/* + @license + Copyright 2006 The Closure Library Authors + SPDX-License-Identifier: Apache-2.0 +*/function Gn(e){var t;e instanceof Gn?(qn(this,e.Ga),this.qb=e.qb,this.Ia=e.Ia,zn(this,e.Fb),this.ya=e.ya,Xn(this,e.g.clone()),this.hb=e.hb):e&&(t=String(e).match(Kn))?(qn(this,t[1]||"",!0),this.qb=Wn(t[2]||""),this.Ia=Wn(t[3]||"",!0),zn(this,t[4]),this.ya=Wn(t[5]||"",!0),Xn(this,t[6]||"",!0),this.hb=Wn(t[7]||"")):this.g=new ni(null)}function qn(e,t,n){e.Ga=n?Wn(t,!0):t,e.Ga&&(e.Ga=e.Ga.replace(/:$/,""))}function zn(e,t){if(t){if(t=Number(t),isNaN(t)||0>t)throw Error("Bad port number "+t);e.Fb=t}else e.Fb=null}function Xn(e,t,n){t instanceof ni?e.g=t:(n||(t=Yn(t,ei)),e.g=new ni(t))}function Wn(e,t){return e?t?decodeURI(e):decodeURIComponent(e):""}function Yn(e,t,n){return null!=e?(e=encodeURI(e).replace(t,$n),n&&(e=e.replace(/%25([0-9a-fA-F]{2})/g,"%$1")),e):null}function $n(e){return"%"+((e=e.charCodeAt(0))>>4&15).toString(16)+(15&e).toString(16)}(i=Gn.prototype).Ga="",i.qb="",i.Ia="",i.Fb=null,i.ya="",i.hb="",i.toString=function(){var e=[],t=this.Ga;if(t&&e.push(Yn(t,Jn,!0),":"),t=this.Ia){e.push("//");var n=this.qb;n&&e.push(Yn(n,Jn,!0),"@"),e.push(encodeURIComponent(t).replace(/%25([0-9a-fA-F]{2})/g,"%$1")),null!=(t=this.Fb)&&e.push(":",String(t))}return(t=this.ya)&&(this.Ia&&"/"!=t.charAt(0)&&e.push("/"),e.push(Yn(t,"/"==t.charAt(0)?Zn:Qn,!0))),(t=this.g.toString())&&e.push("?",t),(t=this.hb)&&e.push("#",Yn(t,ti)),e.join("")},i.resolve=function(e){var t=this.clone();"data"===t.Ga&&(t=new Gn);var n=!!e.Ga;n?qn(t,e.Ga):n=!!e.qb,n?t.qb=e.qb:n=!!e.Ia,n?t.Ia=e.Ia:n=null!=e.Fb;var i=e.ya;if(n)zn(t,e.Fb);else if(n=!!e.ya){if("/"!=i.charAt(0))if(this.Ia&&!this.ya)i="/"+i;else{var r=t.ya.lastIndexOf("/");-1!=r&&(i=t.ya.substr(0,r+1)+i)}if(".."==i||"."==i)i="";else if(-1!=i.indexOf("./")||-1!=i.indexOf("/.")){r=0==i.lastIndexOf("/",0),i=i.split("/");for(var a=[],o=0;o>4).toString(16),r+=(15&o).toString(16),n=n.replace(i[0],r)}return n}function yi(e,t){var n=e;return t&&(n+='; codecs="'+t+'"'),n}function bi(e,t,n){return e=yi(e,t),hi.get("muxjs")()&&mi(e)?vi(n,e):e}function wi(e){var t=(e=e.split("."))[0];return e.pop(),t}pi.prototype.destroy=function(){return this.g.dispose(),this.g=null,Promise.resolve()};var Ti=(new Map).set("codecs","codecs").set("frameRate","framerate").set("bandwidth","bitrate").set("width","width").set("height","height").set("channelsCount","channels");function xi(e){this.s=null,this.i=e,this.j=this.C=0,this.l=1/0,this.h=this.g=null,this.u="",this.m=new Map}function Si(e){return!(!Ii[e]&&"application/cea-608"!=e&&"application/cea-708"!=e)}function Ei(e,t,n){if(e.u=t,t=e.m.get(t))for(var i=l(t.keys()),r=i.next();!r.done;r=i.next())(r=t.get(r.value).filter(function(e){return e.endTime<=n}))&&e.i.append(r)}function Ai(e,t,n){t.startTime+=n,t.endTime+=n;for(var i=(t=l(t.nestedCues)).next();!i.done;i=t.next())Ai(e,i.value,n)}function ki(e,t,n,i,r){for(var a=n+" "+i,o=new Map,s=(t=l(t)).next();!s.done;s=t.next()){var u=s.value;s=u.stream,u=u.cue,o.has(s)||o.set(s,new Map),o.get(s).has(a)||o.get(s).set(a,[]),Ai(e,u,r),u.startTime>=e.j&&u.startTime=n.h||(e<=n.g&&t>=n.h?n.g=n.h=null:e<=n.g&&tn.g&&t>=n.h&&(n.h=e)),T(i)})},B("shaka.text.TextEngine",xi),xi.prototype.destroy=xi.prototype.destroy,xi.findParser=function(e){return Ii[e]},xi.unregisterParser=function(e){delete Ii[e]},xi.registerParser=function(e,t){Ii[e]=t};var Ii={};function Mi(e){this.g=!1,this.h=new ci,this.i=e}function Ci(e,t){if(e.g){if(t instanceof le&&7003==t.code)throw t;throw new le(2,7,7003,t)}}function Di(){this.g={}}function Ri(e,t){for(var n in e.g)t(n,e.g[n])}function Ni(){this.g=new Di}function Pi(e,t,n,i){this.target=e,this.type=t,this.listener=n,this.g=function(e,t){if(null==t)return!1;if("boolean"==typeof t)return t;var n=new Set(["passive","capture"]);return Object.keys(t).filter(function(e){return!n.has(e)}),function(e){var t=Li;if(null==t){t=!1;try{var n={},i={get:function(){return t=!0,!1}};Object.defineProperty(n,"passive",i),Object.defineProperty(n,"capture",i),i=function(){},e.addEventListener("test",i,n),e.removeEventListener("test",i,n)}catch(e){t=!1}Li=t}return t||!1}(e)?t:t.capture||!1}(e,i),this.target.addEventListener(t,n,this.g)}Mi.prototype.destroy=function(){var e=this;return this.g?this.h:(this.g=!0,this.i().then(function(){e.h.resolve()},function(){e.h.resolve()}))},Di.prototype.push=function(e,t){this.g.hasOwnProperty(e)?this.g[e].push(t):this.g[e]=[t]},Di.prototype.get=function(e){return(e=this.g[e])?e.slice():null},Di.prototype.remove=function(e,t){e in this.g&&(this.g[e]=this.g[e].filter(function(e){return e!=t}),0==this.g[e].length&&delete this.g[e])},Di.prototype.size=function(){return Object.keys(this.g).length},(i=Ni.prototype).release=function(){this.ob(),this.g=null},i.A=function(e,t,n,i){this.g&&(e=new Pi(e,t,n,i),this.g.push(t,e))},i.wa=function(e,t,n,i){var r=this;this.A(e,t,function i(a){r.Ea(e,t,i),n(a)},i)},i.Ea=function(e,t,n){if(this.g)for(var i=this.g.get(t)||[],r=(i=l(i)).next();!r.done;r=i.next())(r=r.value).target!=e||n!=r.listener&&n||(r.Ea(),this.g.remove(t,r))},i.ob=function(){if(this.g){var e,t=this.g,n=[];for(e in t.g)n.push.apply(n,c(t.g[e]));for(n=(t=l(n)).next();!n.done;n=t.next())n.value.Ea();this.g.g={}}},B("shaka.util.EventManager",Ni),Ni.prototype.removeAll=Ni.prototype.ob,Ni.prototype.unlisten=Ni.prototype.Ea,Ni.prototype.listenOnce=Ni.prototype.wa,Ni.prototype.listen=Ni.prototype.A,Ni.prototype.release=Ni.prototype.release,Pi.prototype.Ea=function(){this.target.removeEventListener(this.type,this.listener,this.g),this.listener=this.target=null,this.g=!1};var Li=void 0;function ji(e,t,n,i){var r=this;this.g=e,this.m=n,this.j={},this.I={},this.i=null,this.L=i||function(){},this.l={},this.h=new Ni,this.u={},this.C=t,this.F=new ci,this.s=function(e,t){var n=new MediaSource;return e.h.wa(n,"sourceopen",function(){URL.revokeObjectURL(e.H),t.resolve()}),e.H=$i(n),e.g.src=e.H,n}(this,this.F),this.J=new Mi(function(){return function(e){var t,n,i,r,a,o,s;return P(function(u){if(1==u.g){for(n in t=[],e.l)for(i=e.l[n],r=i[0],e.l[n]=i.slice(0,1),r&&t.push(r.p.catch(Ie)),a=l(i.slice(1)),o=a.next();!o.done;o=a.next())o.value.p.reject(new le(2,7,7003,void 0));for(s in e.i&&t.push(e.i.destroy()),e.m&&t.push(e.m.destroy()),e.u)t.push(e.u[s].destroy());return w(u,Promise.all(t),2)}e.h&&(e.h.release(),e.h=null),e.g&&(e.g.removeAttribute("src"),e.g.load(),e.g=null),e.s=null,e.i=null,e.m=null,e.j={},e.u={},e.C=null,e.l={},T(u)})}(r)}),this.H=""}function _i(e){var t=yi(e.mimeType,e.codecs),n=function(e){var t=[e.mimeType];return Ti.forEach(function(n,i){var r=e[i];r&&t.push(n+'="'+r+'"')}),"PQ"==e.hdr&&t.push('eotf="smpte2084"'),t.join(";")}(e);return Si(t)||MediaSource.isTypeSupported(n)||gi(t,e.type)}function Oi(e,t){e.i||(e.i=new xi(e.m)),"application/cea-608"!=t&&"application/cea-708"!=t&&(e.i.s=Ce(Ii[t]))}function Ui(e){return!e.s||"ended"==e.s.readyState}function Fi(e,t){if(t==si)var n=e.i.g;else n=!(n=Vi(e,t))||1==n.length&&1e-6>n.end(0)-n.start(0)?null:1==n.length&&0>n.start(0)?0:n.length?n.start(0):null;return n}function Bi(e,t){return t==si?e.i.h:Fn(Vi(e,t))}function Vi(e,t){try{return e.j[t].buffered}catch(e){return null}}function Hi(e,t,n,i,r,a){var o,s,u,c,d,f,h,p;return P(function(g){return 1==g.g?t==(o=ui).ba?w(g,function(e,t,n,i){var r,a,o;return P(function(s){return 1==s.g?w(s,Promise.resolve(),2):e.s&&e.i?null==n||null==i?(e.s.parseInit(oe(t)),s.return()):(r={periodStart:e.C,segmentStart:n,segmentEnd:i},a=e.s.parseMedia(oe(t),r),o=a.filter(function(t){return t.startTime>=e.j&&t.startTime=n?Gi(e,t):e.j[t].remove(0,n)}),0)})}function Gi(e,t){var n=e.l[t][0];n&&(n.p.resolve(),Xi(e,t))}function qi(e,t,n){return Ci(e.J),n={start:n,p:new ci},e.l[t].push(n),1==e.l[t].length&&Wi(e,t),n.p}function zi(e,t){var n,i,r,a,o;return P(function(s){switch(s.g){case 1:for(r in Ci(e.J),n=[],i={},e.j)i.Lb=new ci,a={start:function(e){return function(){return e.Lb.resolve()}}(i),p:i.Lb},e.l[r].push(a),n.push(i.Lb),1==e.l[r].length&&a.start(),i={Lb:i.Lb};return x(s,2),w(s,Promise.all(n),4);case 4:E(s,3);break;case 2:throw A(s);case 3:try{t()}catch(e){throw new le(2,3,3015,e)}finally{for(o in e.j)Xi(e,o)}T(s)}})}function Xi(e,t){e.l[t].shift(),Wi(e,t)}function Wi(e,t){var n=e.l[t][0];if(n)try{n.start()}catch(i){"QuotaExceededError"==i.name?n.p.reject(new le(2,3,3017,t)):n.p.reject(new le(2,3,3015,i)),Xi(e,t)}}function Yi(e,t,n,i){var r=e.g.mediaKeys;return null==n&&r&&(Ge()||Ke())&&"mp4"==e.I[i].split(";")[0].split("/")[1]&&(t=function(e){function t(){r=!0}function n(e){a.push(e),Re(e)}e=oe(e);var i,r=!1,a=[],o=[];if((new De).box("moov",n).box("trak",n).box("mdia",n).box("minf",n).box("stbl",n).T("stsd",function(e){i=e,a.push(e),Ne(e)}).T("encv",t).T("enca",t).T("avc1",function(e){o.push({box:e,$b:1701733238})}).T("avc3",function(e){o.push({box:e,$b:1701733238})}).T("ac-3",function(e){o.push({box:e,$b:1701733217})}).T("ec-3",function(e){o.push({box:e,$b:1701733217})}).T("mp4a",function(e){o.push({box:e,$b:1701733217})}).parse(e),r)return e;if(0==o.length||!i)throw it(e),new le(2,3,3019);o.reverse();for(var s=l(o),u=s.next();!u.done;u=s.next())u=u.value,e=at(e,i,u.box,a,u.$b);return e}(t)),t}(i=ji.prototype).destroy=function(){return this.J.destroy()},i.init=function(e,t){var n,i,r,a,o,s,u,c=this;return P(function(d){if(1==d.g)return n=ui,w(d,c.F,2);for(i={},r=l(e.keys()),a=r.next();!a.done;i={sa:i.sa},a=r.next())i.sa=a.value,o=e.get(i.sa),s=yi(o.mimeType,o.codecs),i.sa==n.ba?Oi(c,s):(!t&&MediaSource.isTypeSupported(s)||!gi(s,i.sa)||(c.u[i.sa]=new pi,s=vi(i.sa,s)),u=c.s.addSourceBuffer(s),c.h.A(u,"error",function(e){return function(){c.l[e.sa][0].p.reject(new le(2,3,3014,c.g.error?c.g.error.code:0))}}(i)),c.h.A(u,"updateend",function(e){return function(){return Gi(c,e.sa)}}(i)),c.j[i.sa]=u,c.I[i.sa]=s,c.l[i.sa]=[]);T(d)})},i.zc=function(){var e={total:Hn(this.g.buffered),audio:Hn(Vi(this,"audio")),video:Hn(Vi(this,"video")),text:[]};if(this.i){var t=this.i.g,n=this.i.h;null!=t&&null!=n&&e.text.push({start:t,end:n})}return e},i.remove=function(e,t,n){var i=this;return P(function(r){return e==ui.ba?w(r,i.i.remove(t,n),0):w(r,qi(i,e,function(){n<=t?Gi(i,e):i.j[e].remove(t,n)}),0)})},i.flush=function(e){var t=this;return P(function(n){return e==ui.ba?n.return():w(n,qi(t,e,function(){t.g.currentTime-=.001,Gi(t,e)}),0)})},i.endOfStream=function(e){var t=this;return P(function(n){return w(n,zi(t,function(){Ui(t)||(e?t.s.endOfStream(e):t.s.endOfStream())}),0)})},i.Ma=function(e){var t=this;return P(function(n){return w(n,zi(t,function(){t.s.duration=e}),0)})},i.getDuration=function(){return this.s.duration};var $i=e.URL.createObjectURL;function Ji(e,t){return e=er(e),t=er(t),e.split("-")[0]==t.split("-")[0]}function Qi(e,t){e=er(e),t=er(t);var n=e.split("-"),i=t.split("-");return n[0]==i[0]&&1==n.length&&2==i.length}function Zi(e,t){e=er(e),t=er(t);var n=e.split("-"),i=t.split("-");return 2==n.length&&2==i.length&&n[0]==i[0]}function er(e){var t=e.split("-");return e=t[0]||"",t=t[1]||"",e=e.toLowerCase(),e=rr.get(e)||e,(t=t.toUpperCase())?e+"-"+t:e}function tr(e,t){return e=er(e),(t=er(t))==e?4:Qi(t,e)?3:Zi(t,e)?2:Qi(e,t)?1:0}function nr(e){return e.language?er(e.language):e.audio&&e.audio.language?er(e.audio.language):e.video&&e.video.language?er(e.video.language):"und"}function ir(e,t){for(var n=er(e),i=new Set,r=l(t),a=r.next();!a.done;a=r.next())i.add(er(a.value));for(a=(r=l(i)).next();!a.done;a=r.next())if((a=a.value)==n)return a;for(a=(r=l(i)).next();!a.done;a=r.next())if(Qi(a=a.value,n))return a;for(a=(r=l(i)).next();!a.done;a=r.next())if(Zi(a=a.value,n))return a;for(a=(i=l(i)).next();!a.done;a=i.next())if(Qi(n,a=a.value))return a;return null}var rr=new Map([["aar","aa"],["abk","ab"],["afr","af"],["aka","ak"],["alb","sq"],["amh","am"],["ara","ar"],["arg","an"],["arm","hy"],["asm","as"],["ava","av"],["ave","ae"],["aym","ay"],["aze","az"],["bak","ba"],["bam","bm"],["baq","eu"],["bel","be"],["ben","bn"],["bih","bh"],["bis","bi"],["bod","bo"],["bos","bs"],["bre","br"],["bul","bg"],["bur","my"],["cat","ca"],["ces","cs"],["cha","ch"],["che","ce"],["chi","zh"],["chu","cu"],["chv","cv"],["cor","kw"],["cos","co"],["cre","cr"],["cym","cy"],["cze","cs"],["dan","da"],["deu","de"],["div","dv"],["dut","nl"],["dzo","dz"],["ell","el"],["eng","en"],["epo","eo"],["est","et"],["eus","eu"],["ewe","ee"],["fao","fo"],["fas","fa"],["fij","fj"],["fin","fi"],["fra","fr"],["fre","fr"],["fry","fy"],["ful","ff"],["geo","ka"],["ger","de"],["gla","gd"],["gle","ga"],["glg","gl"],["glv","gv"],["gre","el"],["grn","gn"],["guj","gu"],["hat","ht"],["hau","ha"],["heb","he"],["her","hz"],["hin","hi"],["hmo","ho"],["hrv","hr"],["hun","hu"],["hye","hy"],["ibo","ig"],["ice","is"],["ido","io"],["iii","ii"],["iku","iu"],["ile","ie"],["ina","ia"],["ind","id"],["ipk","ik"],["isl","is"],["ita","it"],["jav","jv"],["jpn","ja"],["kal","kl"],["kan","kn"],["kas","ks"],["kat","ka"],["kau","kr"],["kaz","kk"],["khm","km"],["kik","ki"],["kin","rw"],["kir","ky"],["kom","kv"],["kon","kg"],["kor","ko"],["kua","kj"],["kur","ku"],["lao","lo"],["lat","la"],["lav","lv"],["lim","li"],["lin","ln"],["lit","lt"],["ltz","lb"],["lub","lu"],["lug","lg"],["mac","mk"],["mah","mh"],["mal","ml"],["mao","mi"],["mar","mr"],["may","ms"],["mkd","mk"],["mlg","mg"],["mlt","mt"],["mon","mn"],["mri","mi"],["msa","ms"],["mya","my"],["nau","na"],["nav","nv"],["nbl","nr"],["nde","nd"],["ndo","ng"],["nep","ne"],["nld","nl"],["nno","nn"],["nob","nb"],["nor","no"],["nya","ny"],["oci","oc"],["oji","oj"],["ori","or"],["orm","om"],["oss","os"],["pan","pa"],["per","fa"],["pli","pi"],["pol","pl"],["por","pt"],["pus","ps"],["que","qu"],["roh","rm"],["ron","ro"],["rum","ro"],["run","rn"],["rus","ru"],["sag","sg"],["san","sa"],["sin","si"],["slk","sk"],["slo","sk"],["slv","sl"],["sme","se"],["smo","sm"],["sna","sn"],["snd","sd"],["som","so"],["sot","st"],["spa","es"],["sqi","sq"],["srd","sc"],["srp","sr"],["ssw","ss"],["sun","su"],["swa","sw"],["swe","sv"],["tah","ty"],["tam","ta"],["tat","tt"],["tel","te"],["tgk","tg"],["tgl","tl"],["tha","th"],["tib","bo"],["tir","ti"],["ton","to"],["tsn","tn"],["tso","ts"],["tuk","tk"],["tur","tr"],["twi","tw"],["uig","ug"],["ukr","uk"],["urd","ur"],["uzb","uz"],["ven","ve"],["vie","vi"],["vol","vo"],["wel","cy"],["wln","wa"],["wol","wo"],["xho","xh"],["yid","yi"],["yor","yo"],["zha","za"],["zho","zh"],["zul","zu"]]);function ar(e,t){var n=Ar(e.variants,t),i=function(e){var t="",n=1/0;return Ri(e,function(e,i){for(var r=0,a=0,o=l(i),s=o.next();!s.done;s=o.next())r+=s.value.bandwidth||0,++a;(r/=a)=t&&e<=n}var r=e.video;return!(r&&r.width&&r.height&&(!i(r.width,t.minWidth,Math.min(t.maxWidth,n.width))||!i(r.height,t.minHeight,Math.min(t.maxHeight,n.height))||!i(r.width*r.height,t.minPixels,t.maxPixels))||e&&e.video&&e.video.frameRate&&!i(e.video.frameRate,t.minFrameRate,t.maxFrameRate)||!i(e.bandwidth,t.minBandwidth,t.maxBandwidth))}function ur(e,t,n,i){return P(function(r){if(1==r.g)return i?w(r,cr(n,0=a*i.bandwidth/this.o.bandwidthDowngradeTarget&&t<=r&&(n=i)}return this.l=Date.now(),n},i.enable=function(){this.i=!0},i.disable=function(){this.i=!1},i.segmentDownloaded=function(e,t){var n=this.g;if(!(16e3>t)){var i=8e3*t/e,r=e/1e3;n.g+=t,H(n.h,r,i),H(n.i,r,i)}if(null!=this.l&&this.i)e:{if(this.s){if(Date.now()-this.l<1e3*this.o.switchInterval)break e}else{if(!(128e3<=this.g.g))break e;this.s=!0}n=this.chooseVariant(),this.g.getBandwidthEstimate(Nr(this)),n&&this.j(n)}},i.getBandwidthEstimate=function(){return this.g.getBandwidthEstimate(this.o.defaultBandwidthEstimate)},i.setVariants=function(e){this.h=e},i.playbackRateChanged=function(e){this.m=e},i.configure=function(e){this.o=e},B("shaka.abr.SimpleAbrManager",Rr),Rr.prototype.configure=Rr.prototype.configure,Rr.prototype.playbackRateChanged=Rr.prototype.playbackRateChanged,Rr.prototype.setVariants=Rr.prototype.setVariants,Rr.prototype.getBandwidthEstimate=Rr.prototype.getBandwidthEstimate,Rr.prototype.segmentDownloaded=Rr.prototype.segmentDownloaded,Rr.prototype.disable=Rr.prototype.disable,Rr.prototype.enable=Rr.prototype.enable,Rr.prototype.chooseVariant=Rr.prototype.chooseVariant,Rr.prototype.init=Rr.prototype.init,Rr.prototype.stop=Rr.prototype.stop,Lr.prototype.add=function(e){return!!jr(this.h,e)&&(this.g.add(e),!0)},Lr.prototype.values=function(){return this.g.values()},Ur.prototype.create=function(e){var t=this,n=e.filter(function(e){return jr(t.g,e)});return n.length?new Lr(n[0],n):this.h.create(e)},Fr.prototype.create=function(e){var t=[];t=function(e,t){var n=ir(er(t),e.map(function(e){return nr(e)}));return n?e.filter(function(e){return n==nr(e)}):[]}(e,this.i);var n=e.filter(function(e){return e.primary});for((e=function(e,t){return e.filter(function(e){return!!e.audio&&(t?e.audio.roles.includes(t):0==e.audio.roles.length)})}(t=t.length?t:n.length?n:e,this.j)).length&&(t=e),this.g&&((e=Ar(t,this.g)).length&&(t=e)),this.h&&((e=function(e,t){return e.filter(function(e){return!!e.audio&&e.audio.label.toLowerCase()==t.toLowerCase()})}(t,this.h)).length&&(t=e)),e=new Lr(t[0]),n=(t=l(t)).next();!n.done;n=t.next())n=n.value,jr(e.h,n)&&e.add(n);return e};var Vr=0,Hr=1;function Kr(e,t){var n={maxAttempts:2,baseDelay:1e3,backoffFactor:2,fuzzFactor:.5,timeout:3e4,stallTimeout:5e3,connectionTimeout:1e4};this.l=null==e.maxAttempts?n.maxAttempts:e.maxAttempts,this.j=null==e.baseDelay?n.baseDelay:e.baseDelay,this.s=null==e.fuzzFactor?n.fuzzFactor:e.fuzzFactor,this.m=null==e.backoffFactor?n.backoffFactor:e.backoffFactor,this.g=0,this.h=this.j,(this.i=void 0!==t&&t)&&(this.g=1)}function Gr(e){var t,n;return P(function(i){if(1==i.g){if(e.g>=e.l){if(!e.i)throw new le(2,7,1010);e.g=1,e.h=e.j}return t=e.g,e.g++,0==t?i.return():(n=e.h*(1+(2*Math.random()-1)*e.s),w(i,new Promise(function(e){new Be(e).V(n/1e3)}),2))}e.h*=e.m,T(i)})}function qr(e,t){this.promise=e,this.i=t,this.g=!1}function zr(e){return new qr(Promise.reject(e),function(){return Promise.resolve()})}function Xr(){var e=Promise.reject(new le(2,7,7001));return e.catch(function(){}),new qr(e,function(){return Promise.resolve()})}function Wr(e){return new qr(Promise.resolve(e),function(){return Promise.resolve()})}function Yr(e){return new qr(e,function(){return e.catch(function(){})})}function $r(e){return new qr(Promise.all(e.map(function(e){return e.promise})),function(){return Promise.all(e.map(function(e){return e.abort()}))})}function Jr(t,n){if(n)if(n instanceof Map)for(var i=l(n.keys()),r=i.next();!r.done;r=i.next())r=r.value,Object.defineProperty(this,r,{value:n.get(r),writable:!0,enumerable:!0});else for(i in n)Object.defineProperty(this,i,{value:n[i],writable:!0,enumerable:!0});this.defaultPrevented=this.cancelable=this.bubbles=!1,this.timeStamp=e.performance&&e.performance.now?e.performance.now():Date.now(),this.type=t,this.isTrusted=!1,this.target=this.currentTarget=null,this.g=!1}function Qr(e){var t,n=new Jr(e.type);for(t in e)Object.defineProperty(n,t,{value:e[t],writable:!0,enumerable:!0});return n}function Zr(){this.U=new Di,this.sc=this}function ea(e){var t=new Set;return function e(n){switch(typeof n){case"undefined":case"boolean":case"number":case"string":case"symbol":case"function":return n;default:if(!n||n.buffer&&n.buffer.constructor==ArrayBuffer)return n;if(t.has(n))return null;var i=n.constructor==Array;if(n.constructor!=Object&&!i)return null;t.add(n);var r,a=i?[]:{};for(r in n)a[r]=e(n[r]);return i&&(a.length=n.length),a}}(e)}function ta(e){var t,n={};for(t in e)n[t]=e[t];return n}function na(){this.g=[]}function ia(e,t){e.g.push(t.finally(function(){lt(e.g,t)}))}function ra(e){Zr.call(this),this.i=!1,this.l=new na,this.g=new Set,this.h=new Set,this.j=e||null,this.m=!1}function aa(e,t,n,i){n=n||ca;var r=da[e];(!r||n>=r.priority)&&(da[e]={priority:n,uf:t,wf:void 0!==i&&i})}function oa(e,t,n){return{uris:e,method:"GET",body:null,headers:{},allowCrossSiteCredentials:!1,retryParameters:t,licenseRequestType:null,sessionId:null,streamDataCallback:void 0===n?null:n}}function sa(){this.g=0}function ua(e,t,n){qr.call(this,e,t),this.h=n}qr.prototype.abort=function(){return this.g=!0,this.i()},qr.prototype.finally=function(e){return this.promise.then(function(){return e(!0)},function(){return e(!1)}),this},qr.prototype.ca=function(e,t){function n(n){return function(s){if(r.g&&n)a.reject(o);else{var u=n?e:t;u?i=function(e,t,n){try{var i=e(t);return i&&i.promise&&i.abort?(n.resolve(i.promise),function(){return i.abort()}):(n.resolve(i),function(){return Promise.resolve(i).then(function(){},function(){})})}catch(e){return n.reject(e),function(){return Promise.resolve()}}}(u,s,a):(n?a.resolve:a.reject)(s)}}}function i(){return a.reject(o),r.abort()}var r=this,a=new ci,o=new le(2,7,7001);return this.promise.then(n(!0),n(!1)),new qr(a,function(){return i()})},B("shaka.util.AbortableOperation",qr),qr.prototype.chain=qr.prototype.ca,qr.prototype.finally=qr.prototype.finally,qr.all=$r,qr.prototype.abort=qr.prototype.abort,qr.notAbortable=Yr,qr.completed=Wr,qr.aborted=Xr,qr.failed=zr,Jr.prototype.preventDefault=function(){this.cancelable&&(this.defaultPrevented=!0)},Jr.prototype.stopImmediatePropagation=function(){this.g=!0},Jr.prototype.stopPropagation=function(){},B("shaka.util.FakeEvent",Jr),Zr.prototype.addEventListener=function(e,t){this.U&&this.U.push(e,t)},Zr.prototype.removeEventListener=function(e,t){this.U&&this.U.remove(e,t)},Zr.prototype.dispatchEvent=function(e){if(!this.U)return!0;var t=this.U.get(e.type)||[],n=this.U.get("All");for(n&&(t=t.concat(n)),n=(t=l(t)).next();!n.done;n=t.next()){n=n.value,e.target=this.sc,e.currentTarget=this.sc;try{n.handleEvent?n.handleEvent(e):n.call(this,e)}catch(e){}if(e.g)break}return e.defaultPrevented},Zr.prototype.release=function(){this.U=null},na.prototype.destroy=function(){for(var e=[],t=l(this.g),n=t.next();!n.done;n=t.next())(n=n.value).promise.catch(function(){}),e.push(n.abort());return this.g=[],Promise.all(e)},m(ra,Zr),(i=ra.prototype).Ld=function(e){this.m=e},i.xf=function(e){this.g.add(e)},i.Of=function(e){this.g.delete(e)},i.Ie=function(){this.g.clear()},i.yf=function(e){this.h.add(e)},i.Pf=function(e){this.h.delete(e)},i.Je=function(){this.h.clear()},i.destroy=function(){return this.i=!0,this.g.clear(),this.h.clear(),Zr.prototype.release.call(this),this.l.destroy()},i.request=function(e,t){var n=this,i=new sa;if(this.i){var r=Promise.reject(new le(2,7,7001));return r.catch(function(){}),new ua(r,function(){return Promise.resolve()},i)}t.method=t.method||"GET",t.headers=t.headers||{},t.retryParameters=t.retryParameters?ea(t.retryParameters):{maxAttempts:2,baseDelay:1e3,backoffFactor:2,fuzzFactor:.5,timeout:3e4,stallTimeout:5e3,connectionTimeout:1e4},t.uris=ea(t.uris);var a=(r=function(e,t,n){for(var i=Wr(void 0),r={},a=(e=l(e.g)).next();!a.done;r={Zc:r.Zc},a=e.next())r.Zc=a.value,i=i.ca(function(e){return function(){return n.body&&(n.body=ae(n.body)),e.Zc(t,n)}}(r));return i.ca(void 0,function(e){if(e instanceof le&&7001==e.code)throw e;throw new le(2,1,1006,e)})}(this,e,t)).ca(function(){return function e(t,n,i,r,a,o,s){t.m&&(i.uris[a]=i.uris[a].replace("http://","https://"));var u=new Gn(i.uris[a]),l=u.Ga,c=!1;l||(l=location.protocol,l=l.slice(0,-1),qn(u,l),i.uris[a]=u.toString());l=l.toLowerCase();var d=(l=da[l])?l.uf:null;if(!d)return zr(new le(2,1,1e3,u));var f,h=l.wf,p=null,g=null,m=!1;return Yr(Gr(r)).ca(function(){if(t.i)return Xr();f=Date.now();var e=d(i.uris[a],i,n,function(e,i,r){p&&p.stop(),g&&g.V(o/1e3),t.j&&n==la&&(t.j(e,i),c=!0,s.g=r)});if(!h)return e;var r=i.retryParameters.connectionTimeout;r&&(p=new Be(function(){m=!0,e.abort()})).V(r/1e3);var o=i.retryParameters.stallTimeout;return o&&(g=new Be(function(){m=!0,e.abort()})),e}).ca(function(e){return p&&p.stop(),g&&g.stop(),null==e.timeMs&&(e.timeMs=Date.now()-f),{response:e,kf:c}},function(u){if(p&&p.stop(),g&&g.stop(),t.i)return Xr();if(m&&(u=new le(1,1,1003,i.uris[a],n)),u instanceof le){if(7001==u.code)throw u;if(1010==u.code)throw o;if(1==u.severity){var l=(new Map).set("error",u);return l=new Jr("retry",l),t.dispatchEvent(l),a=(a+1)%i.uris.length,e(t,n,i,r,a,u,s)}}throw u})}(n,e,t,new Kr(t.retryParameters,!1),0,null,i)}),o=a.ca(function(t){return function(e,t,n){for(var i=Wr(void 0),r={},a=(e=l(e.h)).next();!a.done;r={$c:r.$c},a=e.next())r.$c=a.value,i=i.ca(function(e){return function(){var i=n.response;return i.data&&(i.data=ae(i.data)),e.$c(t,i)}}(r));return i.ca(function(){return n},function(e){var t=2;if(e instanceof le){if(7001==e.code)throw e;t=e.severity}throw new le(t,1,1007,e)})}(n,e,t)}),s=Date.now(),u=0;r.promise.then(function(){u=Date.now()-s},function(){});var c=0;a.promise.then(function(){c=Date.now()},function(){});var d=o.ca(function(t){var i=Date.now()-c,r=t.response;return r.timeMs+=u,r.timeMs+=i,t.kf||!n.j||r.fromCache||e!=la||n.j(r.timeMs,r.data.byteLength),r},function(e){throw e&&(e.severity=2),e});return r=new ua(d.promise,function(){return d.abort()},i),ia(this.l,r),r},B("shaka.net.NetworkingEngine",ra),ra.prototype.request=ra.prototype.request,ra.prototype.destroy=ra.prototype.destroy,ra.makeRequest=oa,ra.defaultRetryParameters=function(){return{maxAttempts:2,baseDelay:1e3,backoffFactor:2,fuzzFactor:.5,timeout:3e4,stallTimeout:5e3,connectionTimeout:1e4}},ra.prototype.clearAllResponseFilters=ra.prototype.Je,ra.prototype.unregisterResponseFilter=ra.prototype.Pf,ra.prototype.registerResponseFilter=ra.prototype.yf,ra.prototype.clearAllRequestFilters=ra.prototype.Ie,ra.prototype.unregisterRequestFilter=ra.prototype.Of,ra.prototype.registerRequestFilter=ra.prototype.xf,ra.unregisterScheme=function(e){delete da[e]},ra.registerScheme=aa,ra.prototype.setForceHTTPS=ra.prototype.Ld,ra.NumBytesRemainingClass=sa,m(ua,qr),ra.PendingRequest=ua;var la=1;ra.RequestType={MANIFEST:0,SEGMENT:la,LICENSE:2,APP:3,TIMING:4};var ca=3;ra.PluginPriority={FALLBACK:1,PREFERRED:2,APPLICATION:ca};var da={};function fa(){}function ha(e){return new Gn(e=pe(e)).Ia}function pa(e,t,n){function i(e){se(a).setUint32(o,e.byteLength,!0),o+=4,a.set(oe(e),o),o+=e.byteLength}if(!n||!n.byteLength)throw new le(2,6,6015);var r;r="string"==typeof t?me(t,!0):t,e=me(e=pe(e),!0);var a=new Uint8Array(12+e.byteLength+r.byteLength+n.byteLength),o=0;return i(e),i(r),i(n),a}function ga(e){for(var t=new Map,n=l(Object.keys(e)),i=n.next();!i.done;i=n.next())i=i.value,t.set(i,e[i]);return t}function ma(e){var t={};return e.forEach(function(e,n){t[n]=e}),t}function va(e,t){if(!e&&!t)return!0;if(e&&!t||t&&!e)return!1;if(e.size!=t.size)return!1;for(var n=l(e),i=n.next();!i.done;i=n.next()){var r=l(i.value);if(i=r.next().value,r=r.next().value,!t.has(i))return!1;if((i=t.get(i))!=r||null==i)return!1}return!0}function ya(e,t){var n=this;t=void 0===t?1:t,this.D=e,this.u=new Set,this.g=this.m=null,this.qa=this.L=!1,this.H=0,this.i=null,this.h=new Ni,this.j=new Map,this.C=[],this.s=new ci,this.o=null,this.l=function(t){n.s.reject(t),e.onError(t)},this.ra=new Map,this.ea=new Map,this.U=new Be(function(){return function(e){var t=e.ra,n=e.ea;n.clear(),t.forEach(function(e,t){return n.set(t,e)}),(t=Array.from(n.values())).length&&t.every(function(e){return"expired"==e})&&e.l(new le(2,6,6014)),e.D.Ic(ma(n))}(n)}),this.F=!1,this.I=[],this.O=!1,this.la=new Be(function(){var e;(e=n).j.forEach(function(t,n){var i=t.zd,r=n.expiration;isNaN(r)&&(r=1/0),r!=i&&(e.D.onExpirationUpdated(n.sessionId,r),t.zd=r)})}).Da(t),this.s.catch(function(){}),this.J=new Mi(function(){return e=n,P(function(t){switch(t.g){case 1:return e.h.release(),e.h=null,e.s.reject(),e.la.stop(),e.la=null,e.U.stop(),e.U=null,w(t,La(e),2);case 2:if(!e.g){t.v(3);break}return x(t,4),w(t,e.g.setMediaKeys(null),6);case 6:E(t,5);break;case 4:A(t);case 5:e.g=null;case 3:e.i=null,e.u.clear(),e.m=null,e.C=[],e.o=null,e.l=function(){},e.D=null,e.W=!1,T(t)}});var e}),this.W=!1}function ba(e,t,n,i){return e.C=n,e.F=0i&&(i+=Math.pow(2,32)),i="0x"+i.toString(16)}e.l(new le(2,6,6006,t.message,t,i))}})}(e,t,n)}function Ea(e){return e?e.keySystem:""}function Aa(e){return!!e&&!!e.match(/^com\.(microsoft|chromecast)\.playready/)}function ka(e,t){if(navigator.userAgent.match(/Edge\//))return!0;if(t=t.toLowerCase(),Ge()&&t.includes('codecs="ac-3"')){var n=t.replace("ac-3","ec-3");return e.u.has(t)||e.u.has(n)}return e.u.has(t)}function Ia(e){return e=Z(e=e.j.keys(),function(e){return e.sessionId}),Array.from(e)}function Ma(e,t){var n=yi(e.mimeType,t||e.codecs);return gi(n)?vi(e.type,n):n}function Ca(e,t,n,i){var r,a,o,s,u,c,d,f,h,p,g,m,v;return P(function(y){switch(y.g){case 1:if(r=new Map,i){e:{for(var b=l(n),T=b.next();!T.done;T=b.next()){var S=l(_a(T.value));for(T=S.next();!T.done;T=S.next()){var k=T.value;r.has(k.keySystem)||r.set(k.keySystem,[]),r.get(k.keySystem).push(k)}}if(1==r.size&&r.has(""))throw new le(2,6,6e3);for(S=(b=l([!0,!1])).next();!S.done;S=b.next())for(S=S.value,T=(k=l(n)).next();!T.done;T=k.next()){var I=l(T.value.decodingInfos);for(T=I.next();!T.done;T=I.next()){var M=T.value;if(M.supported&&M.keySystemAccess){var C=l(T=r.get(M.keySystemAccess.keySystem));for(T=C.next();!T.done;T=C.next())if(!!T.value.licenseServerUri==S){a=M.keySystemAccess;break e}}}}a=null}y.v(2);break}return w(y,function(e,t){var n,i,r,a,o,s,u,c,d,f,h;return P(function(p){switch(p.g){case 1:if(1==t.size&&t.has(""))throw new le(2,6,6e3);for(i=l(t.values()),r=i.next();!r.done;r=i.next())0==(a=r.value).audioCapabilities.length&&delete a.audioCapabilities,0==a.videoCapabilities.length&&delete a.videoCapabilities;o=l([!0,!1]),s=o.next();case 2:if(s.done){p.v(4);break}u=s.value,c=l(t.keys()),d=c.next();case 5:if(d.done){s=o.next(),p.v(2);break}if(f=d.value,h=t.get(f),h.drmInfos.some(function(e){return!!e.licenseServerUri})!=u){p.v(6);break}return x(p,8),w(p,navigator.requestMediaKeySystemAccess(f,[h]),10);case 10:return n=p.h,p.return(n);case 8:A(p);case 9:Ci(e.J);case 6:d=c.next(),p.v(5);break;case 4:return p.return(n)}})}(e,t),3);case 3:a=y.h;case 2:if(!(o=a))throw new le(2,6,6001);for(Ci(e.J),x(y,4),e.u.clear(),s=o.getConfiguration(),u=s.audioCapabilities||[],c=s.videoCapabilities||[],d=l(u),f=d.next();!f.done;f=d.next())h=f.value,e.u.add(h.contentType.toLowerCase());for(p=l(c),f=p.next();!f.done;f=p.next())g=f.value,e.u.add(g.contentType.toLowerCase());if(i){for(S=o.keySystem,Ua(b=r.get(o.keySystem),k=[],T=[],I=[],M=new Set),C=e.F?"persistent-license":"temporary",S={keySystem:S,licenseServerUri:k[0],distinctiveIdentifierRequired:b[0].distinctiveIdentifierRequired,persistentStateRequired:b[0].persistentStateRequired,sessionType:b[0].sessionType||C,audioRobustness:b[0].audioRobustness||"",videoRobustness:b[0].videoRobustness||"",serverCertificate:T[0],initData:I,keyIds:M},k=(b=l(b)).next();!k.done;k=b.next())(k=k.value).distinctiveIdentifierRequired&&(S.distinctiveIdentifierRequired=k.distinctiveIdentifierRequired),k.persistentStateRequired&&(S.persistentStateRequired=k.persistentStateRequired);b=S}else b=o.keySystem,S=t.get(o.keySystem),k=[],T=[],I=[],M=new Set,Ua(S.drmInfos,k,T,I,M),b={keySystem:b,licenseServerUri:k[0],distinctiveIdentifierRequired:"required"==S.distinctiveIdentifier,persistentStateRequired:"required"==S.persistentState,sessionType:S.sessionTypes[0]||"temporary",audioRobustness:(S.audioCapabilities?S.audioCapabilities[0].robustness:"")||"",videoRobustness:(S.videoCapabilities?S.videoCapabilities[0].robustness:"")||"",serverCertificate:T[0],initData:I,keyIds:M};if(e.i=b,!e.i.licenseServerUri)throw new le(2,6,6012,e.i.keySystem);return w(y,o.createMediaKeys(),6);case 6:return m=y.h,Ci(e.J),e.m=m,e.L=!0,w(y,Ta(e),7);case 7:Ci(e.J),E(y,0);break;case 4:if(v=A(y),Ci(e.J,v),e.i=null,e.u.clear(),v instanceof le)throw v;throw new le(2,6,6002,v.message)}})}function Da(e,t){var n,i,r,a,o;return P(function(s){switch(s.g){case 1:try{n=e.m.createSession("persistent-license")}catch(t){return i=new le(2,6,6005,t.message),e.l(i),s.return(Promise.reject(i))}return e.h.A(n,"message",function(t){e.g&&e.o.delayLicenseRequestUntilPlayed&&e.g.paused&&!e.O?e.I.push(t):Na(e,t)}),e.h.A(n,"keystatuseschange",function(t){return Pa(e,t)}),r={initData:null,loaded:!1,zd:1/0,Na:null,type:"persistent-license"},e.j.set(n,r),x(s,2),w(s,n.load(t),4);case 4:return a=s.h,Ci(e.J),a?(r.loaded=!0,Oa(e)&&e.s.resolve(),s.return(n)):(e.j.delete(n),e.l(new le(2,6,6013)),s.return(Promise.resolve()));case 2:o=A(s),Ci(e.J,o),e.j.delete(n),e.l(new le(2,6,6005,o.message));case 3:return s.return(Promise.resolve())}})}function Ra(e,t,n){return"skd"==t&&(t=n.serverCertificate,e=pa(e,n=ha(e),t)),e}function Na(e,t){var n,i,r,a,o,s,u,c,d,f,h,p;P(function(g){switch(g.g){case 1:return n=t.target,e.o.logLicenseExchange&&et(t.message),i=e.j.get(n),r=e.i.licenseServerUri,a=e.o.advanced[e.i.keySystem],"individualization-request"==t.messageType&&a&&a.individualizationServer&&(r=a.individualizationServer),(o=oa([r],e.o.retryParameters)).body=t.message,o.method="POST",o.licenseRequestType=t.messageType,o.sessionId=n.sessionId,Aa(e.i.keySystem)&&function(e){var t=he(e.body,!0,!0);if(t.includes("PlayReadyKeyMessage")){for(var n=l((t=(new DOMParser).parseFromString(t,"application/xml")).getElementsByTagName("HttpHeader")),i=n.next();!i.done;i=n.next())i=i.value,e.headers[i.getElementsByTagName("name")[0].textContent]=i.getElementsByTagName("value")[0].textContent;e.body=tt(t.getElementsByTagName("Challenge")[0].textContent)}else e.headers["Content-Type"]="text/xml; charset=utf-8"}(o),s=Date.now(),x(g,2),w(g,e.D.Cb.request(2,o).promise,4);case 4:u=g.h,E(g,3);break;case 2:return c=A(g),d=new le(2,6,6007,c),e.l(d),i&&i.Na&&i.Na.reject(d),g.return();case 3:return e.J.g?g.return():(e.H+=(Date.now()-s)/1e3,e.o.logLicenseExchange&&et(u.data),x(g,5),w(g,n.update(u.data),7));case 7:E(g,6);break;case 5:return f=A(g),h=new le(2,6,6008,f.message),e.l(h),i&&i.Na&&i.Na.reject(h),g.return();case 6:p=new Jr("drmsessionupdate"),e.D.onEvent(p),i&&(i.Na&&i.Na.resolve(),new Be(function(){i.loaded=!0,Oa(e)&&e.s.resolve()}).V(Va)),T(g)}})}function Pa(e,t){var n=t.target,i=e.j.get(n),r=!1;n.keyStatuses.forEach(function(t,n){if("string"==typeof n){var a=n;n=t,t=a}if(Aa(e.i.keySystem)&&16==n.byteLength&&navigator.userAgent.match(/Edge?\//)){var o=(a=se(n)).getUint32(0,!0),s=a.getUint16(4,!0),u=a.getUint16(6,!0);a.setUint32(0,o,!1),a.setUint16(4,s,!1),a.setUint16(6,u,!1)}"status-pending"!=t&&(i.loaded=!0),"expired"==t&&(r=!0),a=it(n),e.ra.set(a,t)});var a=n.expiration-Date.now();(0>a||r&&1e3>a)&&i&&!i.Na&&(e.j.delete(n),n.close().catch(function(){})),Oa(e)&&(e.s.resolve(),e.U.V(Ha))}function La(e){var t;return P(function(n){return t=Array.from(e.j.entries()),e.j.clear(),w(n,Promise.all(t.map(function(t){var n=(t=l(t)).next().value,i=t.next().value;return P(function(t){return 1==t.g?(x(t,2),e.qa||e.C.includes(n.sessionId)||"persistent-license"!==i.type?w(t,function(e){var t;return P(function(n){return 1==n.g?(t=new Promise(function(e,t){new Be(t).V(Ba)}),x(n,2),w(n,Promise.race([Promise.all([e.close(),e.closed]),t]),4)):2!=n.g?E(n,0):(A(n),void T(n))})}(n),5):w(t,n.remove(),5)):2!=t.g?E(t,0):(A(t),void T(t))})})),0)})}function ja(e,t){if(!e.length)return t;if(!t.length)return e;for(var n=[],i=l(e),r=i.next();!r.done;r=i.next()){r=r.value;for(var a={},o=l(t),s=o.next();!s.done;a={Fa:a.Fa},s=o.next())if(s=s.value,r.keySystem==s.keySystem){a.Fa=[],a.Fa=a.Fa.concat(r.initData||[]),a.Fa=a.Fa.concat(s.initData||[]),a.Fa=a.Fa.filter(function(e){return function(t,n){return void 0===t.keyId||n===e.Fa.findIndex(function(e){return e.keyId===t.keyId})}}(a)),o=r.keyIds&&s.keyIds?new Set([].concat(c(r.keyIds),c(s.keyIds))):r.keyIds||s.keyIds,n.push({keySystem:r.keySystem,licenseServerUri:r.licenseServerUri||s.licenseServerUri,distinctiveIdentifierRequired:r.distinctiveIdentifierRequired||s.distinctiveIdentifierRequired,persistentStateRequired:r.persistentStateRequired||s.persistentStateRequired,videoRobustness:r.videoRobustness||s.videoRobustness,audioRobustness:r.audioRobustness||s.audioRobustness,serverCertificate:r.serverCertificate||s.serverCertificate,initData:a.Fa,keyIds:o});break}}return n}function _a(e){return(e.video?e.video.drmInfos:[]).concat(e.audio?e.audio.drmInfos:[])}function Oa(e){return function(e,t){for(var n=l(e),i=n.next();!i.done;i=n.next())if(!t(i.value))return!1;return!0}(e=e.j.values(),function(e){return e.loaded})}function Ua(e,t,n,i,r){for(var a={},o=(e=l(e)).next();!o.done;a={za:a.za},o=e.next()){if(a.za=o.value,t.includes(a.za.licenseServerUri)||t.push(a.za.licenseServerUri),a.za.serverCertificate&&(n.some(function(e){return function(t){return ie(t,e.za.serverCertificate)}}(a))||n.push(a.za.serverCertificate)),a.za.initData){o={};for(var s=l(a.za.initData),u=s.next();!u.done;o={lc:o.lc},u=s.next())o.lc=u.value,i.some(function(e){return function(t){var n=e.lc;return!(!t.keyId||t.keyId!=n.keyId)||t.initDataType==n.initDataType&&ie(t.initData,n.initData)}}(o))||i.push(o.lc)}if(a.za.keyIds)for(s=(o=l(a.za.keyIds)).next();!s.done;s=o.next())r.add(s.value)}}function Fa(t,n,i){!t.keySystem||"org.w3.clearkey"==t.keySystem&&t.licenseServerUri||(n.size&&(n=n.get(t.keySystem)||"",t.licenseServerUri=n),t.keyIds||(t.keyIds=new Set),(i=i.get(t.keySystem))&&(t.distinctiveIdentifierRequired||(t.distinctiveIdentifierRequired=i.distinctiveIdentifierRequired),t.persistentStateRequired||(t.persistentStateRequired=i.persistentStateRequired),t.videoRobustness||(t.videoRobustness=i.videoRobustness),t.audioRobustness||(t.audioRobustness=i.audioRobustness),t.serverCertificate||(t.serverCertificate=i.serverCertificate),i.sessionType&&(t.sessionType=i.sessionType)),e.cast&&e.cast.__platform__&&"com.microsoft.playready"==t.keySystem&&(t.keySystem="com.chromecast.playready"))}B("shaka.util.FairPlayUtils",fa),fa.initDataTransform=pa,fa.defaultGetContentId=ha,(i=ya.prototype).destroy=function(){return this.J.destroy()},i.configure=function(e){this.o=e},i.Qb=function(e){var t,n=this;return P(function(i){if(1==i.g)return n.m?(n.g=e,n.h.wa(n.g,"play",function(){for(var e=l(n.I),t=e.next();!t.done;t=e.next())Na(n,t.value);n.O=!0,n.I=[]}),"webkitCurrentPlaybackTargetIsWireless"in n.g&&n.h.A(n.g,"webkitcurrentplaybacktargetiswirelesschanged",function(){return La(n)}),w(i,n.g.setMediaKeys(n.m).catch(function(e){return Promise.reject(new le(2,6,6003,e.message))}),2)):(n.h.wa(e,"encrypted",function(){n.l(new le(2,6,6010))}),i.return());Ci(n.J),xa(n),n.i.initData.length||n.C.length||(t=function(e){return Sa(n,e.initDataType,oe(e.initData))},n.h.A(n.g,"encrypted",t)),T(i)})},i.Ub=function(){for(var e=1/0,t=this.j.keys(),n=(t=l(t)).next();!n.done;n=t.next())n=n.value,isNaN(n.expiration)||(e=Math.min(e,n.expiration));return e},i.Bc=function(){return ma(this.ea)};var Ba=1,Va=5,Ha=.5,Ka=new ce(function(){return ae(new Uint8Array([0]))});function Ga(){}function qa(e,t,n,i){var r,a,o,s;return P(function(u){if(1==u.g)return i&&(r=Wa[i.toLowerCase()])?u.return(r):(a=Xa(e))&&(o=Ya[a])?u.return(o):i?u.v(2):w(u,za(e,t,n),3);if(2!=u.g&&(i=u.h)&&(s=Wa[i]))return u.return(s);throw new le(2,4,4e3,e)})}function za(e,t,n){var i,r,a;return P(function(o){return 1==o.g?((i=oa([e],n)).method="HEAD",w(o,t.request(0,i).promise,2)):(r=o.h,a=r.headers["content-type"],o.return(a?a.toLowerCase().split(";").shift():""))})}function Xa(e){return 1==(e=new Gn(e).ya.split("/").pop().split(".")).length?"":e.pop().toLowerCase()}B("shaka.media.ManifestParser",Ga),Ga.unregisterParserByMime=function(e){delete Wa[e]},Ga.registerParserByMime=function(e,t){Wa[e]=t},Ga.registerParserByExtension=function(e,t){Ya[e]=t};var Wa={},Ya={};function $a(e,t,n){this.oa=e,this.ka=t,this.fa=n}function Ja(e,t,n,i,r,a,o,s,u,l){l=void 0===l?[]:l,this.startTime=e,this.j=this.endTime=t,this.i=n,this.ka=i,this.fa=r,this.h=a,this.timestampOffset=o,this.appendWindowStart=s,this.appendWindowEnd=u,this.g=l}function Qa(e,t,n){this.j=e,this.Lc=t,this.m=this.l=1/0,this.g=1,this.h=this.i=null,this.s=0,this.u=!0,this.C=0,this.F=void 0===n||n,this.H=0}function Za(e,t){this.j=e,this.m=eo(e),this.g=e.g.currentTime,this.l=Date.now()/1e3,this.h=!1,this.s=t,this.i=function(){}}function eo(e){if(e.g.paused||0==e.g.playbackRate||0==e.g.buffered.length)var t=!1;else e:{t=e.g.currentTime;for(var n=(e=l(Hn(e.g.buffered))).next();!n.done;n=e.next())if(!(t<(n=n.value).start-.1||t>n.end-.5)){t=!0;break e}t=!1}return t}function to(e,t,n,i,r){var a=this;this.g=e,this.C=t,this.o=n,this.u=r,this.h=new Ni,this.s=!1,this.F=e.readyState,this.j=!1,this.i=i,this.m=!1,this.h.A(e,"waiting",function(){return no(a)}),this.l=new Be(function(){no(a)}).Da(.25)}function no(e){if(0!=e.g.readyState){if(e.g.seeking){if(!e.s)return}else e.s=!1;if(!e.g.paused||0==e.g.currentTime&&(e.g.autoplay||0!=e.g.currentTime)){var t;if(e.g.readyState!=e.F&&(e.j=!1,e.F=e.g.readyState),!(t=!e.i)){var n=(t=e.i).j,i=eo(n),r=n.g.currentTime,a=Date.now()/1e3;t.g==r&&t.m==i||(t.l=a,t.g=r,t.m=i,t.h=!1),(i=(r=a-t.l)>=t.s&&i&&!t.h)&&(t.i(t.g,r),t.h=!0,t.g=n.g.currentTime),t=!i}if(t){r=e.o.smallGapLimit;var o=e.g.currentTime;if(!(null==(n=function(e,t,n){return!e||!e.length||1==e.length&&1e-6>e.end(0)-e.start(0)?null:0<=(e=Hn(e).findIndex(function(e,i,r){return e.start>t&&(0==i||r[i-1].end-t<=n)}))?e:null}(t=e.g.buffered,o,e.o.gapDetectionThreshold))||0==n&&!e.m||(i=t.start(n),i>=e.C.Ua()))){var s=i-o;r=s<=r,a=!1,.001>s||(r||e.j||(e.j=!0,(o=new Jr("largegap",o=(new Map).set("currentTime",o).set("gapSize",s))).cancelable=!0,e.u(o),e.o.jumpLargeGaps&&!o.defaultPrevented&&(a=!0)),!r&&!a)||(0!=n&&t.end(n-1),e.g.currentTime=i)}}}}}function io(e,t,n,i){t==HTMLMediaElement.HAVE_NOTHING||e.readyState>=t?i():(t=ro.value().get(t),n.wa(e,t,i))}$a.prototype.Xb=function(){return this.ka},$a.prototype.Tb=function(){return this.fa},B("shaka.media.InitSegmentReference",$a),$a.prototype.getEndByte=$a.prototype.Tb,$a.prototype.getStartByte=$a.prototype.Xb,(i=Ja.prototype).oa=function(){return this.i()},i.df=function(){return this.startTime},i.Re=function(){return this.endTime},i.Xb=function(){return this.ka},i.Tb=function(){return this.fa},B("shaka.media.SegmentReference",Ja),Ja.prototype.getEndByte=Ja.prototype.Tb,Ja.prototype.getStartByte=Ja.prototype.Xb,Ja.prototype.getEndTime=Ja.prototype.Re,Ja.prototype.getStartTime=Ja.prototype.df,Ja.prototype.getUris=Ja.prototype.oa,(i=Qa.prototype).getDuration=function(){return this.l},i.Xe=function(){return this.g},i.Ma=function(e){this.l=e},i.cf=function(){return this.j},i.se=function(e){this.s=e},i.fc=function(e){this.u=e},i.Od=function(e){this.m=e},i.Jf=function(e){this.Lc=e},i.Qe=function(){return this.Lc},i.Db=function(e){if(0!=e.length){var t=e[e.length-1].endTime;this.xd(e[0].startTime),this.g=e.reduce(function(e,t){return Math.max(e,t.endTime-t.startTime)},this.g),this.h=Math.max(this.h,t),null!=this.j&&this.F&&(this.j=(Date.now()+this.s)/1e3-this.h-this.g)}},i.xd=function(e){this.i=null==this.i?e:Math.min(this.i,e)},i.wd=function(e){this.g=Math.max(this.g,e)},i.offset=function(e){null!=this.i&&(this.i+=e),null!=this.h&&(this.h+=e)},i.Z=function(){return 1/0==this.l&&!this.u},i.mb=function(){return 1/0!=this.l&&!this.u},i.Va=function(){return Math.max(this.C,this.ib()-this.m)},i.te=function(e){this.C=e},i.ib=function(){return this.Z()||this.mb()?Math.min(Math.max(0,(Date.now()+this.s)/1e3-this.g-this.j)+this.H,this.l):this.h||this.l},i.Wb=function(e){var t=Math.max(this.i,this.C);return 1/0==this.m?Math.ceil(1e3*t)/1e3:Math.max(t,Math.min(this.ib()-this.m+e,this.Ua()))},i.zb=function(){return this.Wb(0)},i.Ua=function(){return Math.max(0,this.ib()-(this.Z()||this.mb()?this.Lc:0))},i.we=function(){return!(null==this.j||null!=this.h&&this.F)},i.re=function(e){this.H=e},B("shaka.media.PresentationTimeline",Qa),Qa.prototype.setAvailabilityTimeOffset=Qa.prototype.re,Qa.prototype.usingPresentationStartTime=Qa.prototype.we,Qa.prototype.getSeekRangeEnd=Qa.prototype.Ua,Qa.prototype.getSeekRangeStart=Qa.prototype.zb,Qa.prototype.getSafeSeekRangeStart=Qa.prototype.Wb,Qa.prototype.getSegmentAvailabilityEnd=Qa.prototype.ib,Qa.prototype.setUserSeekStart=Qa.prototype.te,Qa.prototype.getSegmentAvailabilityStart=Qa.prototype.Va,Qa.prototype.isInProgress=Qa.prototype.mb,Qa.prototype.isLive=Qa.prototype.Z,Qa.prototype.offset=Qa.prototype.offset,Qa.prototype.notifyMaxSegmentDuration=Qa.prototype.wd,Qa.prototype.notifyMinSegmentStartTime=Qa.prototype.xd,Qa.prototype.notifySegments=Qa.prototype.Db,Qa.prototype.getDelay=Qa.prototype.Qe,Qa.prototype.setDelay=Qa.prototype.Jf,Qa.prototype.setSegmentAvailabilityDuration=Qa.prototype.Od,Qa.prototype.setStatic=Qa.prototype.fc,Qa.prototype.setClockOffset=Qa.prototype.se,Qa.prototype.getPresentationStartTime=Qa.prototype.cf,Qa.prototype.setDuration=Qa.prototype.Ma,Qa.prototype.getMaxSegmentDuration=Qa.prototype.Xe,Qa.prototype.getDuration=Qa.prototype.getDuration,Za.prototype.release=function(){this.j=null,this.i=function(){}},to.prototype.release=function(){this.h&&(this.h.release(),this.h=null),null!=this.l&&(this.l.stop(),this.l=null),this.i&&(this.i.release(),this.i=null),this.g=this.C=this.u=null},to.prototype.Bd=function(){this.m=!0,no(this)};var ro=new ce(function(){return new Map([[HTMLMediaElement.HAVE_METADATA,"loadedmetadata"],[HTMLMediaElement.HAVE_CURRENT_DATA,"loadeddata"],[HTMLMediaElement.HAVE_FUTURE_DATA,"canplay"],[HTMLMediaElement.HAVE_ENOUGH_DATA,"canplaythrough"]])});function ao(e,t,n){var i=this;this.g=e,this.l=t,this.j=n,this.m=!1,this.h=new Ni,this.i=new co(e),io(this.g,HTMLMediaElement.HAVE_METADATA,this.h,function(){uo(i,i.j)})}function oo(e){return e.m?e.g.currentTime:e.j}function so(e,t){0Math.abs(e.g.currentTime-t)?lo(e):(e.h.wa(e.g,"seeking",function(){lo(e)}),fo(e.i,0==e.g.currentTime?t:e.g.currentTime))}function lo(e){e.m=!0,e.h.A(e.g,"seeking",function(){return e.l()})}function co(e){var t=this;this.h=e,this.m=10,this.l=this.j=this.i=0,this.g=new Be(function(){0>=t.i?t.g.stop():t.h.currentTime!=t.j?t.g.stop():(t.h.currentTime=t.l,t.i--)})}function fo(e,t){e.j=e.h.currentTime,e.l=t,e.i=e.m,e.h.currentTime=t,e.g.Da(.1)}function ho(e){var t=this;this.g=e,this.j=!1,this.i=null,this.h=new Ni,io(this.g,HTMLMediaElement.HAVE_CURRENT_DATA,this.h,function(){null==t.i||0==t.i?t.j=!0:(t.h.wa(t.g,"seeking",function(){t.j=!0}),t.g.currentTime=Math.max(0,t.g.currentTime+t.i))})}function po(e,t,n,i,r,a){var o=this;this.i=e,this.g=t.presentationTimeline,this.H=t.minBufferTime||0,this.o=n,this.C=r,this.u=null,this.j=new to(e,t.presentationTimeline,n,function(e,t){if(!t.stallEnabled)return null;var n=t.stallSkip,i=new Za(new function(e){this.g=e}(e),t.stallThreshold);return function(e,t){e.i=t}(i,function(){n?e.currentTime+=n:(e.pause(),e.play())}),i}(e,n),a),this.h=new ao(e,function(){var e=o.j;e.s=!0,e.m=!1,e.j=!1;var t=oo(o.h);return e=mo(o,t),.001e.g.getDuration()?e.g.zb():e.g.Ua():0>t&&(t=e.g.Ua()+t),go(e,vo(e,t))}(this,i)),this.s=new Be(function(){if(0!=o.i.readyState&&!o.i.paused){var e=oo(o.h),t=o.g.zb(),n=o.g.Ua();3>n-t&&(t=n-3),e=n?n-e.o.durationBackoff:t}function mo(e,t){var n=Math.max(e.H,e.o.rebufferingGoal),i=e.o.safeSeekOffset,r=e.g.zb(),a=e.g.Ua(),o=e.g.getDuration();3>a-r&&(r=a-3);var s=e.g.Wb(n),u=e.g.Wb(i);return n=e.g.Wb(n+i),t>=o?go(e,t):t>a?a:t=s||Bn(e.i.buffered,t)?t:n}function vo(e,t){var n=e.g.zb();return t(n=e.g.Ua())?n:t}function yo(e){this.M=e,this.g=null,this.h=0,this.i=!1}function bo(e,t,n){return new yo([new Ja(e,e+t,function(){return n},0,null,null,e,e,e+t)])}function wo(e,t,n){this.i=e,this.h=t,this.g=n}function To(){yo.call(this,[]),this.j=[]}function xo(e){var t=this;this.g=e,this.j=!1,this.i=this.g.Dc(),this.h=new Be(function(){t.g.ie(.25*t.i)})}function So(e){e.h.stop();var t=e.j?0:e.i;if(0<=t)try{return void(e.g.Dc()!=t&&e.g.Nd(t))}catch(e){}e.h.Da(.25),0!=e.g.Dc()&&e.g.Nd(0)}function Eo(e){var t=this;this.h=e,this.g=new Set,this.i=new Be(function(){Ao(t,!1)}).Da(.25)}function Ao(e,t){for(var n=l(e.g),i=n.next();!i.done;i=n.next()){i=i.value;for(var r=e.h.currentTime,a=t,o=l(i.i.g),s=o.next();!s.done;s=o.next()){s=s.value;var u=i.g.get(s),c=rs.endTime?Ro:Do;i.g.set(s,c);for(var d=l(i.j),f=d.next();!f.done;f=d.next())(f=f.value).tb==u&&f.sb==c&&f.lb(s,a)}}}function ko(e){Zr.call(this);var t=this;this.g=new Set,this.i=e,this.h=new Be(function(){for(var e=t.i(),n=l(t.g),i=n.next();!i.done;i=n.next())(i=i.value).endTime=i.startTime&&e(e-=this.h)||e>=this.M.length?null:this.M[e]},i.offset=function(e){if(!this.i)for(var t=l(this.M),n=t.next();!n.done;n=t.next())(n=n.value).startTime+=e,n.endTime+=e,n.timestampOffset+=e},i.Gc=function(e){!this.i&&e.length&&(this.M=this.M.filter(function(t){return t.startTimet&&(0==n.M.length||e.endTime>n.M[0].startTime)}),this.Gc(e),this.gb(t)},i.gb=function(e){if(!this.i){var t=this.M.length;this.M=this.M.filter(function(t){return t.endTime>e}),this.h+=t-this.M.length}},i.ab=function(e,t,n){if(n=void 0!==n&&n,!this.i){for(;this.M.length&&this.M[this.M.length-1].startTime>=t;)this.M.pop();for(;this.M.length&&this.M[0].endTime<=e;)this.M.shift(),n||this.h++;0!=this.M.length&&(e=this.M[this.M.length-1],this.M[this.M.length-1]=new Ja(e.startTime,t,e.i,e.ka,e.fa,e.h,e.timestampOffset,e.appendWindowStart,e.appendWindowEnd))}},i.Oc=function(e,t){var n=this;this.i||(this.g&&this.g.stop(),this.g=new Be(function(){var e=t();e?n.M.push.apply(n.M,c(e)):(n.g.stop(),n.g=null)}),this.g.Da(e))},yo.prototype[Symbol.iterator]=function(){return this.yb(0)},yo.prototype.yb=function(e){var t=this.find(e);if(null==t)return null;t--;var n=this.get(t+1),i=-1;if(n&&0=a.startTime&&e=e.g.length&&(this.h++,this.g=0,e=this.i.get(this.h)),e&&0s):a=!1,a&&t.xa.abort(),T(r)})}(e,a).catch(function(t){e.D&&e.D.onError(t)})):function(e,t){var n,i,r,a;P(function(o){switch(o.g){case 1:return n=ui,x(o,2),w(o,Ki(e.D.S,n.ba),4);case 4:E(o,3);break;case 2:i=A(o),e.D&&e.D.onError(i);case 3:r=yi(t.mimeType,t.codecs),Oi(e.D.S,r),(e.D.S.m.isTextVisible()||e.o.alwaysStreamText)&&(a=Fo(t),e.g.set(n.ba,a),Go(e,a,0)),T(o)}})}(e,t)}function Uo(e,t){t.Rb||t.rb||(t.La?(t.rb=!0,t.wc=0):null==Fi(e.D.S,t.type)?null==t.Oa&&Go(e,t,0):(qo(t),Ko(e,t,!1,0).catch(function(t){e.D&&e.D.onError(t)})))}function Fo(e){return{stream:e,type:e.type,da:null,Ca:null,Fc:null,td:null,sd:null,rd:null,pb:null,endOfStream:!1,La:!1,Oa:null,rb:!1,wc:0,Rc:!1,Rb:!1,Ed:!1,Yb:!1,xa:null}}function Bo(e,t,n,i,r,a){var o;return P(function(s){return 1==s.g?(o=i.closedCaptions&&0=(a=n-r-i)?o.return():w(o,e.D.S.remove(t.type,r,r+a),2);Ci(e.J),T(o)})}(e,t,n),2)):3!=s.g?(Ci(e.J),w(s,Hi(e.D.S,t.type,a,r.startTime,r.endTime,o),3)):(Ci(e.J),void T(s))})}function Vo(e){return e&&e.type==si&&("application/cea-608"==e.stream.mimeType||"application/cea-708"==e.stream.mimeType)}function Ho(e,t,n,i){var r,a,o,s;return P(function(u){return 1==u.g?(r=la,a=No(n.oa(),n.ka,n.fa,e.o.retryParameters,i),o=e.D.Cb.request(r,a),t.xa=o,w(u,o.promise,2)):(s=u.h,t.xa=null,u.return(s.data))})}function Ko(e,t,n,i){var r,a;return P(function(o){return 1==o.g?(t.rb=!1,t.Rc=!1,t.wc=0,t.Rb=!0,t.Ca=null,t.Fc=null,t.da=null,i?(r=e.D.Cc(),a=e.D.S.getDuration(),w(o,e.D.S.remove(t.type,r+i,a),3)):w(o,Ki(e.D.S,t.type),4)):3!=o.g?(Ci(e.J),n?w(o,e.D.S.flush(t.type),3):o.v(3)):(Ci(e.J),t.Rb=!1,t.endOfStream=!1,Go(e,t,0),void T(o))})}function Go(e,t,n){var i=t.type;(i!=si||e.g.has(i))&&(t.Oa=new Fe(function(){var n;return P(function(i){return 1==i.g?(x(i,2),w(i,e.ac(t),4)):2!=i.g?E(i,0):(n=A(i),e.D&&e.D.onError(n),void T(i))})}).V(n))}function qo(e){null!=e.Oa&&(e.Oa.stop(),e.Oa=null)}function zo(e){return P(function(t){return e.xa?w(t,e.xa.abort(),0):t.v(0)})}function Xo(e,t){return P(function(n){if(1==n.g)return w(n,Gr(e.s),2);Ci(e.J),e.D.onError(t),t.handled||e.o.failureCallback(t),T(n)})}function Wo(e,t){var n=eu(),i=this;this.j=t,this.i=e,this.l=n,this.s=null,this.m=[],this.h=this.g=null,this.u=Promise.resolve().then(function(){return e=i,P(function(t){if(e.J.g)t=t.v(0);else{if(0==e.m.length||e.g&&!e.g.kb)var n=!1;else{e.g&&(e.g.Ja.nb(),e.g=null);var i=(n=e.m.shift()).create(e.l);i?(n.Ja.Eb(),e.g={node:i.node,payload:i.payload,kb:i.kb,Ja:n.Ja}):n.Ja.Jc(),n=!0}n?n=Promise.resolve():e.g?n=function(e){var t,n;return P(function(i){switch(i.g){case 1:return e.i=e.j.Ze(e.i,e.l,e.g.node,e.g.payload),x(i,2),e.h=e.j.Ne(e.i,e.l,e.g.payload),w(i,e.h.promise,4);case 4:e.h=null,e.i==e.g.node&&(e.g.Ja.Hc(),e.g=null),E(i,0);break;case 2:return 7001==(t=A(i)).code?e.g.Ja.nb():e.g.Ja.onError(t),e.g=null,e.h=null,n=e,w(i,e.j.handleError(e.l,t),5);case 5:n.i=i.h,T(i)}})}(e):(e.j.rf(e.i),e.s=new ci,n=e.s),t=w(t,n,1)}return t});var e}),this.J=new Mi(function(){return e=i,P(function(i){if(1==i.g)return e.h&&e.h.abort(),$o(e),w(i,e.u,2);for(e.g&&e.g.Ja.nb(),t=l(e.m),n=t.next();!n.done;n=t.next())n.value.Ja.nb();e.g=null,e.m=[],e.j=null,T(i)});var e,t,n})}function Yo(e,t){var n={Eb:function(){},Hc:function(){},nb:function(){},onError:function(){},Jc:function(){},sg:function(){}};return e.m.push({create:t,Ja:n}),e.h&&e.h.abort(),$o(e),n}function $o(e){e.s&&(e.s.resolve(),e.s=null)}function Jo(e){this.g=null;for(var t=l(Array.from(e.textTracks)),n=t.next();!n.done;n=t.next())(n=n.value).mode="disabled","Shaka Player TextTrack"==n.label&&(this.g=n);this.g||(this.g=e.addTextTrack("subtitles","Shaka Player TextTrack")),this.g.mode="hidden"}function Qo(e){if(e.startTime>=e.endTime)return null;var t=new VTTCue(e.startTime,e.endTime,e.payload);t.lineAlign=e.lineAlign,t.positionAlign=e.positionAlign,e.size&&(t.size=e.size);try{t.align=e.textAlign}catch(e){}return"center"==e.textAlign&&"center"!=t.align&&(t.align="middle"),"vertical-lr"==e.writingMode?t.vertical="lr":"vertical-rl"==e.writingMode&&(t.vertical="rl"),1==e.lineInterpretation&&(t.snapToLines=!1),null!=e.line&&(t.line=e.line),null!=e.position&&(t.position=e.position),t}function Zo(e,t){var n=e.mode;e.mode="showing"==n?"showing":"hidden";for(var i=l(Array.from(e.cues)),r=i.next();!r.done;r=i.next())(r=r.value)&&t(r)&&e.removeCue(r);e.mode=n}function es(){}function ts(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function ns(t,n){var i=this;this.m=!1,this.l=[],this.g=t,this.u=n,this.i=document.createElement("div"),this.i.classList.add("shaka-text-container"),this.i.style.textAlign="center",this.i.style.display="flex",this.i.style.flexDirection="column",this.i.style.alignItems="center",this.i.style.justifyContent="flex-end",this.u.appendChild(this.i),this.C=new Be(function(){is(i)}).Da(.25),this.j=new Map,this.h=new Ni,this.h.A(document,"fullscreenchange",function(){is(i,!0)}),this.s=null,"ResizeObserver"in e&&(this.s=new ResizeObserver(function(){is(i,!0)}),this.s.observe(this.i))}function is(e,t){if(e.i){var n=e.g.currentTime;if((!e.m||void 0!==t&&t)&&0r,h=d?d.ye:null;d&&(s.push(d.Vd),f||(o=!0,t.j.delete(c),d=null)),f&&(u.push(c),d||(rs(t,c,a),h=(d=t.j.get(c)).ye,o=!0)),0(r=e.indexOf(".",r)));)0!=r&&"\\"==e[r-1]||(i[a=e.substring(a,r).replace(/\\\./g,".")]={},i=i[a],a=r+1),r+=1;return i[e.substring(a).replace(/\\\./g,".")]=t,n}function ls(){}function cs(){var e=1/0;navigator.connection&&navigator.connection.saveData&&(e=360);var t={retryParameters:{maxAttempts:2,baseDelay:1e3,backoffFactor:2,fuzzFactor:.5,timeout:3e4,stallTimeout:5e3,connectionTimeout:1e4},servers:{},clearKeys:{},advanced:{},delayLicenseRequestUntilPlayed:!1,initDataTransform:Ra,logLicenseExchange:!1,updateExpirationTime:1},n={retryParameters:{maxAttempts:2,baseDelay:1e3,backoffFactor:2,fuzzFactor:.5,timeout:3e4,stallTimeout:5e3,connectionTimeout:1e4},availabilityWindowOverride:NaN,disableAudio:!1,disableVideo:!1,disableText:!1,disableThumbnails:!1,defaultPresentationDelay:0,dash:{clockSyncUri:"",ignoreDrmInfo:!1,disableXlinkProcessing:!1,xlinkFailGracefully:!1,ignoreMinBufferTime:!1,autoCorrectDrift:!0,initialSegmentLimit:1e3,ignoreSuggestedPresentationDelay:!1,ignoreEmptyAdaptationSet:!1,ignoreMaxSegmentDuration:!1,keySystemsByURI:{"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:79f0049a-4098-8642-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime"}},hls:{ignoreTextStreamFailures:!1,useFullSegmentsForStartTime:!1}},i={retryParameters:{maxAttempts:2,baseDelay:1e3,backoffFactor:2,fuzzFactor:.5,timeout:3e4,stallTimeout:5e3,connectionTimeout:1e4},failureCallback:function(e){return[e]},rebufferingGoal:2,bufferingGoal:10,bufferBehind:30,ignoreTextStreamFailures:!1,alwaysStreamText:!1,startAtSegmentBoundary:!1,gapDetectionThreshold:.1,smallGapLimit:.5,jumpLargeGaps:!1,durationBackoff:1,forceTransmuxTS:!1,safeSeekOffset:5,stallEnabled:!0,stallThreshold:1,stallSkip:.1,useNativeHlsOnSafari:!0,inaccurateManifestTolerance:2,lowLatencyMode:!1,autoLowLatencyMode:!1,forceHTTPS:!1,preferNativeHls:!1};(navigator.userAgent.match(/Edge\//)||Ge()||qe())&&(i.gapDetectionThreshold=.5),(We("Web0S")||Ge()||qe())&&(i.stallSkip=0);var r={trackSelectionCallback:function(e){return P(function(t){return t.return(e)})},downloadSizeCallback:function(e){var t;return P(function(n){return 1==n.g?navigator.storage&&navigator.storage.estimate?w(n,navigator.storage.estimate(),3):n.return(!0):(t=n.h,n.return(t.usage+e<.95*t.quota))})},progressCallback:function(e,t){return[e,t]},usePersistentLicense:!0},a={drm:t,manifest:n,streaming:i,offline:r,abrFactory:function(){return new Rr},abr:{enabled:!0,useNetworkInformation:!0,defaultBandwidthEstimate:1e6,switchInterval:8,bandwidthUpgradeTarget:.85,bandwidthDowngradeTarget:.95,restrictions:{minWidth:0,maxWidth:1/0,minHeight:0,maxHeight:e,minPixels:0,maxPixels:1/0,minFrameRate:0,maxFrameRate:1/0,minBandwidth:0,maxBandwidth:1/0}},preferredAudioLanguage:"",preferredTextLanguage:"",preferredVariantRole:"",preferredTextRole:"",preferredAudioChannelCount:2,preferForcedSubs:!1,restrictions:{minWidth:0,maxWidth:1/0,minHeight:0,maxHeight:1/0,minPixels:0,maxPixels:1/0,minFrameRate:0,maxFrameRate:1/0,minBandwidth:0,maxBandwidth:1/0},playRangeStart:0,playRangeEnd:1/0,useMediaCapabilities:!1,textDisplayFactory:function(){return null}};return r.trackSelectionCallback=function(e){return P(function(t){return t.return(function(e,t){var n=e.filter(function(e){return"variant"==e.type}),i=[],r=ir(t,n.map(function(e){return e.language}));r&&(i=n.filter(function(e){return er(e.language)==r})),0==i.length&&(i=n.filter(function(e){return e.primary})),0==i.length&&(n.map(function(e){return e.language}),i=n);var a=i.filter(function(e){return e.height&&480>=e.height});if(a.length&&(a.sort(function(e,t){return t.height-e.height}),i=a.filter(function(e){return e.height==a[0].height})),n=[],i.length){var o=Math.floor(i.length/2);i.sort(function(e,t){return e.bandwidth-t.bandwidth}),n.push(i[o])}for(i=l(e),o=i.next();!o.done;o=i.next())(o=o.value).type!=si&&"image"!=o.type||n.push(o);return n}(e,a.preferredAudioLanguage))})},a}function ds(e,t,n){var i={".drm.servers":"",".drm.clearKeys":"",".drm.advanced":{distinctiveIdentifierRequired:!1,persistentStateRequired:!1,videoRobustness:"",audioRobustness:"",sessionType:"",serverCertificate:new Uint8Array(0),individualizationServer:""}};return ss(e,t,n||cs(),i,"")}function fs(e,t){if(null==e.g)e.g={timestamp:Date.now()/1e3,state:t,duration:0};else{var n=Date.now()/1e3;e.g.duration=n-e.g.timestamp,e.g.state!=t&&(e.h.push(e.g),e.g={timestamp:n,state:t,duration:0})}}function hs(e,t){var n=0;e.g&&e.g.state==t&&(n+=e.g.duration);for(var i=l(e.h),r=i.next();!r.done;r=i.next())n+=(r=r.value).state==t?r.duration:0;return n}function ps(e,t,n){e.h!=t&&(e.h=t,e.g.push({timestamp:Date.now()/1e3,id:t.id,type:"variant",fromAdaptation:n,bandwidth:t.bandwidth}))}function gs(e,t,n){e.i!=t&&(e.i=t,e.g.push({timestamp:Date.now()/1e3,id:t.id,type:"text",fromAdaptation:n,bandwidth:null}))}function ms(){this.s=this.u=this.I=this.F=this.m=this.j=this.H=this.l=this.i=this.L=this.O=this.U=this.C=this.W=NaN,this.h=new function(){this.g=null,this.h=[]},this.g=new function(){this.i=this.h=null,this.g=[]}}function vs(t,n){Zr.call(this);var i=this;this.l=Iu,this.qc=this.g=null,this.ea=!1,this.h=new Ni,this.dd=this.u=this.$a=this.B=this.tc=this.s=this.i=this.ic=this.I=this.rc=this.F=this.Pa=this.C=this.L=this.m=this.P=null,this.ld=1e9,this.o=ks(this),this.kd={width:1/0,height:1/0},this.j=null,this.qa=new Fr(this.o.preferredAudioLanguage,this.o.preferredVariantRole,this.o.preferredAudioChannelCount),this.ra=this.o.preferredTextLanguage,this.Ob=this.o.preferredTextRole,this.Nb=this.o.preferForcedSubs,this.ed=[],n&&n(this),this.P=function(e){return new ra(function(t,n){e.u&&e.u.segmentDownloaded(t,n)})}(this),this.P.Ld(this.o.streaming.forceHTTPS),this.H=null,Pu&&(this.H=Ce(Pu)),this.h.A(e,"online",function(){i.Fd()}),this.ta={name:"detach"},this.Sa={name:"attach"},this.W={name:"unload"},this.nd={name:"manifest-parser"},this.jd={name:"manifest"},this.Ha={name:"media-source"},this.gd={name:"drm-engine"},this.O={name:"load"},this.od={name:"src-equals-drm-engine"},this.Qa={name:"src-equals"};var r=new Map;r.set(this.Sa,function(e,t){return Yr(function(e,t,n){return null==t.G&&(t.G=n.G,e.h.A(t.G,"error",function(){var t=Ks(e);t&&Vs(e,t)})),e.g=t.G,Promise.resolve()}(i,e,t))}),r.set(this.ta,function(e){return e.G&&(i.h.Ea(e.G,"error"),e.G=null),i.H&&i.H.release(),i.g=null,Yr(e=Promise.resolve())}),r.set(this.W,function(e){return Yr(bs(i,e))}),r.set(this.Ha,function(e){return Yr(e=function(e,t){var n,i,r,a;return P(function(o){if(1==o.g)return n=new On,i=e.o.textDisplayFactory,r=Ce(i),e.hd=i,a=function(e,t,n,i){return new ji(e,t,n,i)}(t.G,n,r,function(t,n,i){for(var r=(t=l(t)).next();!r.done;r=t.next())if((r=r.value).data&&r.cueTime&&r.frames){for(var a=r.cueTime+n,o=i,s=l(r.frames),u=s.next();!u.done;u=s.next())ws(e,a,o,"ID3",u.value);e.H&&e.H.onHlsTimedMetadata(r,a)}}),w(o,a.F,2);e.L=a,T(o)})}(i,e))}),r.set(this.nd,function(e,t){return Yr(function(e,t,n){var i,r,a,o;return P(function(s){if(1==s.g)return t.mimeType=n.mimeType,t.uri=n.uri,i=t.uri,r=e.P,e.$a=i,a=e,w(s,qa(i,r,e.o.manifest.retryParameters,t.mimeType),2);a.tc=s.h,e.s=Ce(e.tc),o=ea(e.o.manifest),n.G&&"AUDIO"===n.G.nodeName&&(o.disableVideo=!0),e.s.configure(o),T(s)})}(i,e,t))}),r.set(this.jd,function(e){return function(e,t){var n=t.uri,i=e.P;e.ic=new ko(function(){return e.Hd()}),e.ic.addEventListener("regionadd",function(t){t=t.region,Hs(e,bu,t),e.H&&e.H.onDashTimedMetadata(t)});var r={networkingEngine:i,filter:function(t){return P(function(n){return n.return(e.yc(t))})},makeTextStreamsForClosedCaptions:function(t){return function(e,t){for(var n=new Set,i=l(t.textStreams),r=i.next();!r.done;r=i.next())"application/cea-608"!=(r=r.value).mimeType&&"application/cea-708"!=r.mimeType||n.add(r.originalId);for(i=l(t.variants),r=i.next();!r.done;r=i.next())if((r=r.value.video)&&r.closedCaptions)for(var a=l(r.closedCaptions.keys()),o=a.next();!o.done;o=a.next())if(o=o.value,!n.has(o)){var s=o.startsWith("CC")?"application/cea-608":"application/cea-708",u=new To;s={id:e.ld++,originalId:o,createSegmentIndex:function(){return Promise.resolve()},segmentIndex:u,mimeType:s,codecs:"",kind:"caption",encrypted:!1,drmInfos:[],keyIds:new Set,language:r.closedCaptions.get(o),label:null,type:si,primary:!1,trickModeVideo:null,emsgSchemeIdUris:null,roles:r.roles,forced:!1,channelsCount:null,audioSamplingRate:null,spatialAudio:!1,closedCaptions:null},t.textStreams.push(s),n.add(o)}}(e,t)},onTimelineRegionAdded:function(t){var n=e.ic;e:{for(var i=l(n.g),r=i.next();!r.done;r=i.next())if((r=r.value).schemeIdUri==t.schemeIdUri&&r.id==t.id&&r.startTime==t.startTime&&r.endTime==t.endTime){i=r;break e}i=null}null==i&&(n.g.add(t),t=new Jr("regionadd",new Map([["region",t]])),n.dispatchEvent(t))},onEvent:function(t){return e.dispatchEvent(t)},onError:function(t){return Vs(e,t)},isLowLatencyMode:function(){return e.o.streaming.lowLatencyMode},isAutoLowLatencyMode:function(){return e.o.streaming.autoLowLatencyMode},enableLowLatencyMode:function(){e.configure("streaming.lowLatencyMode",!0)}},a=Date.now()/1e3;return new qr(P(function(t){if(1==t.g)return o=e,w(t,e.s.start(n,r),2);if(o.B=t.h,s=ys(du),e.dispatchEvent(s),0==e.B.variants.length)throw new le(2,4,4036);!function(e){function t(e){return e.video&&e.audio||e.video&&e.video.codecs.includes(",")}e.variants.some(t)&&(e.variants=e.variants.filter(t))}(e.B),u=Date.now()/1e3,c=u-a,e.j.H=c,T(t)}),function(){return e.s.stop()});var o,s,u,c}(i,e)}),r.set(this.gd,function(e){return Yr(e=function(e,t){var n,i;return P(function(r){return 1==r.g?(n=Date.now()/1e3,i=!0,e.m=Ts(e,{Cb:e.P,onError:function(t){Vs(e,t)},Ic:function(t){Gs(e,t)},onExpirationUpdated:function(t,n){qs(e,t,n)},onEvent:function(t){e.dispatchEvent(t),t.type==au&&i&&(i=!1,e.j.j=Date.now()/1e3-n)}}),e.o.useMediaCapabilities||dr(e.B),e.m.configure(e.o.drm),w(r,ba(e.m,e.B.variants,e.B.offlineSessionIds,e.o.useMediaCapabilities),2)):3!=r.g?w(r,e.m.Qb(t.G),3):w(r,e.yc(e.B),0)})}(i,e))}),r.set(this.O,function(e,t){return Yr(function(e,t,n){var i,r,a,o,s,u,c,d,f,h;return P(function(p){switch(p.g){case 1:if(t.startTime=n.startTime,i=t.G,r=t.uri,e.$a=r,e.F=new xo({Dc:function(){return t.G.playbackRate},Ac:function(){return t.G.defaultPlaybackRate},Nd:function(e){t.G.playbackRate=e},ie:function(e){t.G.currentTime+=e}}),a=function(){return Ds(e)},o=function(){return Cs(e)},e.h.A(i,"playing",a),e.h.A(i,"pause",a),e.h.A(i,"ended",a),e.h.A(i,"ratechange",o),s=e.o.abrFactory,e.u&&e.dd==s||(e.dd=s,e.u=Ce(s),"function"!=typeof e.u.playbackRateChanged&&(xe("AbrManager","Please use an AbrManager with playbackRateChanged function."),e.u.playbackRateChanged=function(){}),e.u.configure(e.o.abr)),e.qa=new Fr(e.o.preferredAudioLanguage,e.o.preferredVariantRole,e.o.preferredAudioChannelCount),e.ra=e.o.preferredTextLanguage,e.Ob=e.o.preferredTextRole,e.Nb=e.o.preferForcedSubs,zs(e.B.presentationTimeline,e.o.playRangeStart,e.o.playRangeEnd),e.u.init(function(t,n,i){n=void 0!==n&&n,i=void 0===i?0:i,e.i&&t!=e.i.h&&(ps(e.j.g,t,!0),jo(e.i,t,n,i),js(e))}),e.C=function(e,t){return new po(e.g,e.B,e.o.streaming,t,function(){if(e.Pa&&Ao(e.Pa,!0),e.i)for(var t=e.i,n=t.D.Cc(),i=t.o.smallGapLimit,r=l(t.g.keys()),a=r.next();!a.done;a=r.next()){a=a.value;var o=t.g.get(a);o.da=null;var s=t.D.S;if(a==si?s=null!=(s=s.i).g&&null!=s.h&&(n>=s.g&&n, the browser will not load anything until play() is called. We are unable to measure load latency in a meaningful way, and we cannot provide track info yet. Please do not use preload="none" with Shaka Player.'),r.resolve()),e.h.wa(e.g,"error",function(){r.reject(Ks(e))}),new qr(r,function(){return r.reject(new le(2,7,7001)),Promise.resolve()})}(i,e,t)}),this.la=new Wo(this.ta,{Ze:function(e,t,n,r){var a=null;return e==i.ta&&(a=n==i.ta?i.ta:i.Sa),e==i.Sa&&(a=n==i.ta||t.G!=r.G?i.ta:n==i.Sa?i.Sa:n==i.Ha||n==i.O?i.Ha:n==i.Qa?i.od:null),e==i.Ha&&(a=n==i.O&&t.G==r.G?i.nd:i.W),e==i.nd&&(a=Zs(i.O,i.jd,i.W,n,t,r)),e==i.jd&&(a=Zs(i.O,i.gd,i.W,n,t,r)),e==i.gd&&(a=Zs(i.O,i.O,i.W,n,t,r)),e==i.od&&(a=n==i.Qa&&t.G==r.G?i.Qa:i.W),e!=i.O&&e!=i.Qa||(a=i.W),e==i.W&&(a=r.G&&t.G==r.G?i.Sa:i.ta),a},Ne:function(e,t,n){return i.dispatchEvent(ys(hu,(new Map).set("state",e.name))),r.get(e)(t,n)},handleError:function(e){return P(function(t){return 1==t.g?w(t,bs(i,e),2):t.return(e.G?i.Sa:i.ta)})},rf:function(e){i.dispatchEvent(ys(pu,(new Map).set("state",e.name)))}}),t&&this.Qb(t,!0)}function ys(e,t){return new Jr(e,t)}function bs(e,t){var n,i,r,a,o,s,u,c,d;return P(function(f){switch(f.g){case 1:return e.l!=ku&&(e.l=Iu),n=e.ed.map(function(e){return e()}),e.ed=[],w(f,Promise.all(n),2);case 2:if(e.dispatchEvent(ys(Su)),t.mimeType=null,t.startTime=null,t.uri=null,t.G&&(e.h.Ea(t.G,"loadedmetadata"),e.h.Ea(t.G,"playing"),e.h.Ea(t.G,"pause"),e.h.Ea(t.G,"ended"),e.h.Ea(t.G,"ratechange")),e.Pa&&(e.Pa.release(),e.Pa=null),e.rc&&(e.rc.stop(),e.rc=null),!e.s){f.v(3);break}return w(f,e.s.stop(),4);case 4:e.s=null,e.tc=null;case 3:if(!e.u){f.v(5);break}return w(f,e.u.stop(),5);case 5:if(!e.i){f.v(7);break}return w(f,e.i.destroy(),8);case 8:e.i=null;case 7:if(e.F&&(e.F.release(),e.F=null),e.C&&(e.C.release(),e.C=null),!e.L){f.v(9);break}return w(f,e.L.destroy(),10);case 10:e.L=null;case 9:if(e.H&&e.H.onAssetUnload(),!t.G||!t.G.src){f.v(11);break}return w(f,new Promise(function(e){return new Be(e).V(.1)}),12);case 12:for(t.G.removeAttribute("src"),t.G.load();t.G.lastChild;)t.G.removeChild(t.G.firstChild);case 11:if(!e.m){f.v(13);break}return w(f,e.m.destroy(),14);case 14:e.m=null;case 13:if(e.$a=null,e.I=null,e.B){for(i=l(e.B.variants),r=i.next();!r.done;r=i.next())for(a=r.value,o=l([a.audio,a.video]),s=o.next();!s.done;s=o.next())(u=s.value)&&u.segmentIndex&&u.segmentIndex.release();for(c=l(e.B.textStreams),s=c.next();!s.done;s=c.next())(d=s.value).segmentIndex&&d.segmentIndex.release()}e.B=null,e.j=new ms,e.hd=null,Ms(e),T(f)}})}function ws(e,t,n,i,r){t=(new Map).set("startTime",t).set("endTime",n).set("metadataType",i).set("payload",r),e.dispatchEvent(ys(fu,t))}function Ts(e,t){return new ya(t,e.o.drm.updateExpirationTime)}function xs(e,t){e.I=new function(){this.g=Hr,this.h=(new Map).set(Hr,2).set(Vr,1)},e.I.g=Vr,Br(e.I,t,Math.min(.5,t/2)),Ms(e),e.rc=new Be(function(){Ss(e)}).Da(.25)}function Ss(e){switch(e.l){case Cu:if(e.g.ended)var t=!0;else{var n=Fn(e.g.buffered);t=null!=n&&n>=e.g.duration-1}break;case Mu:e:if(e.g.ended||Ui(e.L))t=!0;else{if(e.B.presentationTimeline.Z()){n=e.B.presentationTimeline.ib();var i=Fn(e.g.buffered);if(null!=i&&i>=n){t=!0;break e}}t=!1}break;default:t=!1}i=Vn(e.g.buffered,e.g.currentTime);var r=t,a=(n=e.I).h.get(n.g);t=n.g,i=r||i>=a?Hr:Vr,n.g=i,t!=i&&Ms(e)}function Es(e){if(e.s){var t=ea(e.o.manifest);e.g&&"AUDIO"===e.g.nodeName&&(t.disableVideo=!0),e.s.configure(t)}if(e.m&&e.m.configure(e.o.drm),e.i){e.i.configure(e.o.streaming);try{Is(e,e.B)}catch(t){Vs(e,t)}e.u&&Rs(e),!(t=e.i.h)||t.allowedByApplication&&t.allowedByKeySystem||Ns(e)}if(e.P&&e.P.Ld(e.o.streaming.forceHTTPS),e.L&&(t=e.o.textDisplayFactory,e.hd!=t)){var n=Ce(t),i=e.L,r=i.m;i.m=n,r&&(n.setTextVisibility(r.isTextVisible()),r.destroy()),i.i&&(i.i.i=n),e.hd=t,e.i&&((n=(t=e.i).g.get(si))&&Oo(t,n.stream,!0,0,!0))}e.u&&(e.u.configure(e.o.abr),e.o.abr.enabled?e.u.enable():e.u.disable(),Bs(e)),e.I&&(t=e.o.streaming.rebufferingGoal,e.B&&(t=Math.max(t,e.B.minBufferTime)),Br(e.I,t,Math.min(.5,t/2))),e.B&&zs(e.B.presentationTimeline,e.o.playRangeStart,e.o.playRangeEnd)}function As(e){return Array.from(e.g.textTracks).filter(function(e){return"metadata"!=e.kind&&"chapters"!=e.kind&&"Shaka Player TextTrack"!=e.label})}function ks(e){var t=cs();return t.streaming.failureCallback=function(t){e.Z()&&[1001,1002,1003].includes(t.code)&&(t.severity=1,e.Fd())},t.textDisplayFactory=function(){return e.qc?new ns(e.g,e.qc):new Jo(e.g)},t}function Is(e,t){if(e.l!=ku){for(var n=e.o.restrictions,i=e.kd,r=!1,a=l(t.variants),o=a.next();!o.done;o=a.next()){var s=(o=o.value).allowedByApplication;o.allowedByApplication=sr(o,n,i),s!=o.allowedByApplication&&(r=!0)}if(r&&e.i&&_s(e),(n=e.m?e.m.i:null)&&e.m.m)for(r=(i=l(t.variants)).next();!r.done;r=i.next())for(a=(r=l(((r=r.value).video?r.video.drmInfos:[]).concat(r.audio?r.audio.drmInfos:[]))).next();!a.done;a=r.next())if((a=a.value).keySystem==n.keySystem)for(o=(a=l(a.initData||[])).next();!o.done;o=a.next())o=o.value,Sa(e.m,o.initDataType,o.initData);Xs(e,t)}}function Ms(e){var t=e.pd();if(e.j&&e.I&&e.C){var n=e.F;n.j=t,So(n),Ds(e)}t=(new Map).set("buffering",t),e.dispatchEvent(ys(ru,t))}function Cs(e){var t=e.g.playbackRate;0!=t&&(e.F&&e.F.set(t),t=ys(gu),e.dispatchEvent(t))}function Ds(e){if(e.j&&e.I){var t=e.j.h;e.I.g==Vr?fs(t,"buffering"):e.g.paused?fs(t,"paused"):e.g.ended?fs(t,"ended"):fs(t,"playing")}}function Rs(e){try{Xs(e,e.B)}catch(t){return Vs(e,t),!1}var t=e.B.variants.filter(function(e){return Er(e)});return t=e.qa.create(t),e.u.setVariants(Array.from(t.values())),!0}function Ns(e){var t;(t=Rs(e)?e.u.chooseVariant():null)&&(Ps(e,t,!0,!0,0),js(e))}function Ps(e,t,n,i,r){var a=e.i.h;t==a?i&&jo(e.i,t,i,r,!0):(ps(e.j.g,t,n),jo(e.i,t,i,r),n=null,a&&(n=yr(a)),Os(e,n,t=yr(t)))}function Ls(e,t){var n=Array.from(e.g.audioTracks).find(function(e){return e.enabled});t.enabled=!0,t.id!==n.id&&(n.enabled=!1),Os(e,n=xr(n),xr(t))}function js(e){Ys(e,ys(iu))}function _s(e){Ys(e,ys(xu))}function Os(e,t,n){t=(new Map).set("oldTrack",t).set("newTrack",n),Ys(e,t=ys(Eu,t))}function Us(e){Ys(e,ys(vu))}function Fs(e){Ys(e,ys(yu))}function Bs(e){var t=(new Map).set("newStatus",e.o.abr.enabled);Ys(e,ys(nu,t))}function Vs(e,t){if(e.l!=ku){var n=ys(su,(new Map).set("detail",t));e.dispatchEvent(n),n.defaultPrevented&&(t.handled=!0)}}function Hs(e,t,n){n=(new Map).set("detail",{schemeIdUri:n.schemeIdUri,value:n.value,startTime:n.startTime,endTime:n.endTime,id:n.id,eventElement:n.eventElement}),e.dispatchEvent(ys(t,n))}function Ks(e){if(!e.g.error)return null;var t=e.g.error.code;if(1==t)return null;var n=e.g.error.msExtendedCode;return n&&(0>n&&(n+=Math.pow(2,32)),n=n.toString(16)),new le(2,3,3016,t,n,e.g.error.message)}function Gs(e,t){if(e.i){var n=Object.keys(t),i=1==n.length&&"00"==n[0],r=!1;if(n.length)for(var a=(n=l(e.B.variants)).next();!a.done;a=n.next()){var o=[];(a=a.value).audio&&o.push(a.audio),a.video&&o.push(a.video);for(var s=(o=l(o)).next();!s.done;s=o.next()){var u=s.value;if(s=a.allowedByKeySystem,u.keyIds.size){a.allowedByKeySystem=!0;for(var c=(u=l(u.keyIds)).next();!c.done;c=u.next())c=c.value,c=t[i?"00":c],a.allowedByKeySystem=a.allowedByKeySystem&&!!c&&!Ru.includes(c)}s!=a.allowedByKeySystem&&(r=!0)}}r&&Rs(e),(i=e.i.h)&&!i.allowedByKeySystem&&Ns(e),r&&_s(e)}}function qs(e,t,n){e.s&&e.s.onExpirationUpdated&&e.s.onExpirationUpdated(t,n),t=ys(uu),e.dispatchEvent(t)}function zs(e,t,n){0h?e.D.S.Ma(h):e.D.S.Ma(Math.pow(2,32)),o=l(n.keys()),s=o.next();!s.done;s=o.next())u=s.value,c=n.get(u),e.g.has(u)||(d=Fo(c),e.g.set(u,d),Go(e,d,0));T(f)})}(e),2);Ci(e.J),e.m=!0,T(t)})},Po.prototype.ac=function(t){var n,i,r,a,o,s=this;return P(function(u){switch(u.g){case 1:if(Ci(s.J),t.La||null==t.Oa||t.Rb)return u.return();if(t.Oa=null,!t.rb){u.v(2);break}return w(u,Ko(s,t,t.Rc,t.wc),3);case 3:return u.return();case 2:if(t.stream.segmentIndex){u.v(4);break}return n=t.stream,w(u,t.stream.createSegmentIndex(),5);case 5:if(n!=t.stream)return null==t.Oa&&Go(s,t,0),u.return();case 4:x(u,6),null!=(i=function(t,n){if(Vo(n))return function(e,t){var n=Bi(e,"video")||0;Ei(e.i,t,n)}(t.D.S,n.stream.originalId||""),null;n.type==si&&function(e){e.i&&Ei(e.i,"",0)}(t.D.S);var i=t.D.Cc(),r=n.Ca?n.Ca.endTime:i,a=function(e,t,n){return t==si?null==(e=e.i).h||e.ht.B.presentationTimeline.getDuration()-r)return n.endOfStream=!0,"video"==n.type&&(i=t.g.get(si))&&Vo(i)&&(i.endOfStream=!0),null;if(n.endOfStream=!1,a>=o)return.5;if(a=Bi(t.D.S,n.type),!(a=function(e,t,n,i){if(t.da)return t.da.current();if(t.Ca||i)return t.da=t.stream.segmentIndex.yb(t.Ca?t.Ca.endTime:i),t.da&&t.da.next().value;e=e.o.inaccurateManifestTolerance,i=Math.max(n-e,0);var r=null;return e&&(t.da=t.stream.segmentIndex.yb(i),r=t.da&&t.da.next().value),r||(t.da=t.stream.segmentIndex.yb(n),r=t.da&&t.da.next().value),r}(t,n,i,a)))return 1;o=1/0;for(var s=Array.from(t.g.values()),u=(s=l(s)).next();!u.done;u=s.next())Vo(u=u.value)||u.da&&!u.da.current()||(o=Math.min(o,u.Ca?u.Ca.endTime:i));return r>=o+t.B.presentationTimeline.g?1:(function(t,n,i,r){var a,o,s,u,l,c,d,f,h,p,g;return P(function(m){switch(m.g){case 1:return a=ui,o=n.stream,s=n.da,n.La=!0,x(m,2),w(m,function(e,t,n){var i,r,a,o,s,u,l;return P(function(c){return i=[],r=Math.max(0,n.appendWindowStart-.1),a=n.appendWindowEnd+.01,(o=n.timestampOffset)==t.td&&r==t.sd&&a==t.rd||(s=function(){var n;return P(function(i){if(1==i.g)return x(i,2),t.sd=r,t.rd=a,t.td=o,w(i,function(e,t,n,i,r){return P(function(a){return t==ui.ba?(e.i.C=n,function(e,t,n){e.j=t,e.l=n}(e.i,i,r),a.return()):w(a,Promise.all([qi(e,t,function(){var n=e.j[t].appendWindowStart,i=e.j[t].appendWindowEnd;e.j[t].abort(),e.j[t].appendWindowStart=n,e.j[t].appendWindowEnd=i,Gi(e,t)}),qi(e,t,function(){var i=n;0>i&&(i+=.001),e.j[t].timestampOffset=i,Gi(e,t)}),qi(e,t,function(){e.j[t].appendWindowStart=0,e.j[t].appendWindowEnd=r,e.j[t].appendWindowStart=i,Gi(e,t)})]),0)})}(e.D.S,t.type,o,r,a),4);if(2!=i.g)return E(i,0);throw n=A(i),t.sd=null,t.rd=null,t.td=null,n})},i.push(s())),!function(e,t){return e&&t?e.Xb()==t.Xb()&&e.Tb()==t.Tb()&&dt(e.oa(),t.oa()):e==t}(n.h,t.Fc)&&(t.Fc=n.h)&&(u=Ho(e,t,n.h),l=function(){var n,i,r;return P(function(a){switch(a.g){case 1:return x(a,2),w(a,u,4);case 4:return n=a.h,Ci(e.J),i=t.stream.closedCaptions&&0e}),!0)},i.append=function(e){function t(e){var n=[],i=700<=e.fontWeight,r="italic"==e.fontStyle,a=e.textDecoration.includes("underline");return i&&n.push("b"),r&&n.push("i"),a&&n.push("u"),i=n.reduce(function(e,t){return e+"<"+t+">"},""),n=n.reduceRight(function(e,t){return e+""},""),e.lineBreak||e.spacer?(e.spacer&&xe("shaka.extern.Cue","Please use lineBreak instead of spacer."),"\n"):e.nestedCues.length?e.nestedCues.map(t).join(""):i+e.payload+n}var n=e.map(function(e){if(e.nestedCues.length){var n=e.clone();return n.nestedCues=[],n.payload=t(e),n}return e}),i=[];e=this.g.cues?Array.from(this.g.cues):[];for(var r={},a=(n=l(n)).next();!a.done;r={ub:r.ub},a=n.next())r.ub=a.value,e.some(function(e){return function(t){return t.startTime==e.ub.startTime&&t.endTime==e.ub.endTime&&t.text==e.ub.payload}}(r))||(a=Qo(r.ub))&&i.push(a);for(r=(e=l(e=i.slice().sort(function(e,t){return e.startTime!=t.startTime?e.startTime-t.startTime:e.endTime!=t.endTime?e.endTime-t.startTime:"line"in VTTCue.prototype?i.indexOf(t)-i.indexOf(e):i.indexOf(e)-i.indexOf(t)}))).next();!r.done;r=e.next())this.g.addCue(r.value)},i.destroy=function(){return this.g&&(Zo(this.g,function(){return!0}),this.g.mode="disabled"),this.g=null,Promise.resolve()},i.isTextVisible=function(){return"showing"==this.g.mode},i.setTextVisibility=function(e){this.g.mode=e?"showing":"hidden"},B("shaka.text.SimpleTextDisplayer",Jo),Jo.prototype.setTextVisibility=Jo.prototype.setTextVisibility,Jo.prototype.isTextVisible=Jo.prototype.isTextVisible,Jo.prototype.destroy=Jo.prototype.destroy,Jo.prototype.append=Jo.prototype.append,Jo.prototype.remove=Jo.prototype.remove,B("shaka.util.Dom",es),es.removeAllChildren=ts,(i=ns.prototype).append=function(e){for(var t=[].concat(c(this.l)),n={},i=(e=l(e)).next();!i.done;n={jc:n.jc},i=e.next())n.jc=i.value,t.some(function(e){return function(t){return ht(t,e.jc)}}(n))||this.l.push(n.jc);is(this)},i.destroy=function(){this.u.removeChild(this.i),this.i=null,this.m=!1,this.l=[],this.C&&this.C.stop(),this.j.clear(),this.h&&(this.h.release(),this.h=null),this.s&&(this.s.disconnect(),this.s=null)},i.remove=function(e,t){if(!this.i)return!1;var n=this.l.length;return this.l=this.l.filter(function(n){return n.startTime=t}),is(this,n>this.l.length),!0},i.isTextVisible=function(){return this.m},i.setTextVisibility=function(e){this.m=e},B("shaka.text.UITextDisplayer",ns),ns.prototype.setTextVisibility=ns.prototype.setTextVisibility,ns.prototype.isTextVisible=ns.prototype.isTextVisible,ns.prototype.remove=ns.prototype.remove,ns.prototype.destroy=ns.prototype.destroy,ns.prototype.append=ns.prototype.append,B("shaka.text.WebVttGenerator",function(){}),B("shaka.util.ConfigUtils",os),os.convertToConfigObject=us,os.mergeConfigObjects=ss,B("shaka.util.PlayerConfiguration",ls),ls.mergeConfigObjects=ds,m(vs,Zr),(i=vs.prototype).destroy=function(){var e,t=this;return P(function(n){switch(n.g){case 1:return t.l==ku?n.return():(t.l=ku,e=Yo(t.la,function(){return{node:t.ta,payload:eu(),kb:!1}}),w(n,new Promise(function(t){e.Eb=function(){},e.Hc=function(){t()},e.nb=function(){t()},e.onError=function(){t()},e.Jc=function(){t()}}),2));case 2:return w(n,t.la.destroy(),3);case 3:if(t.h&&(t.h.release(),t.h=null),t.dd=null,t.u=null,t.o=null,t.j=null,t.qc=null,!t.P){n.v(4);break}return w(n,t.P.destroy(),5);case 5:t.P=null;case 4:Zr.prototype.release.call(t),T(n)}})},i.Qb=function(e,t){if(t=void 0===t||t,this.l==ku)return Promise.reject(Qs());var n=eu();n.G=e,Ve()||(t=!1);var i=t?this.Ha:this.Sa,r=Yo(this.la,function(){return{node:i,payload:n,kb:!1}});return r.Eb=function(){},tu(r)},i.detach=function(){var e=this;if(this.l==ku)return Promise.reject(Qs());var t=Yo(this.la,function(){return{node:e.ta,payload:eu(),kb:!1}});return t.Eb=function(){},tu(t)},i.Rd=function(e){var t=this;if(e=void 0===e||e,this.l==ku)return Promise.reject(Qs());Ve()||(e=!1);var n=eu(),i=Yo(this.la,function(i){var r=i.G&&e?t.Ha:i.G?t.Sa:t.ta;return n.G=i.G,{node:r,payload:n,kb:!1}});return i.Eb=function(){},tu(i)},i.load=function(e,t,n){var i=this;if(this.l==ku)return Promise.reject(Qs());this.dispatchEvent(ys(cu));var r=eu();r.uri=e,r.Pd=Date.now()/1e3,n&&(r.mimeType=n),void 0!==t&&(r.startTime=t);var a=function(e,t){if(!Ve())return!0;var n=t.mimeType,i=t.uri||"";if(n||(n={mp4:"video/mp4",m4v:"video/mp4",m4a:"audio/mp4",webm:"video/webm",weba:"audio/webm",mkv:"video/webm",ts:"video/mp2t",ogv:"video/ogg",ogg:"audio/ogg",mpg:"video/mpeg",mpeg:"video/mpeg",m3u8:"application/x-mpegurl",mpd:"application/dash+xml",mp3:"audio/mpeg",aac:"audio/aac",flac:"audio/flac",wav:"audio/wav"}[Xa(i)]),n){if(""==(t.G||Ye()).canPlayType(n))return!1;if(!Ve()||!(n in Wa||Xa(i)in Ya)||e.o.streaming.preferNativeHls)return!0;if(ze())return e.o.streaming.useNativeHlsOnSafari}return!1}(this,r)?this.Qa:this.O,o=Yo(this.la,function(e){return null==e.G?null:(r.G=e.G,{node:a,payload:r,kb:!0})});return this.j=new ms,o.Eb=function(){},new Promise(function(e,t){o.Jc=function(){return t(new le(2,7,7002))},o.Hc=function(){e(),i.dispatchEvent(ys(lu))},o.nb=function(){return t(Qs())},o.onError=function(e){return t(e)}})},i.configure=function(e,t){2==arguments.length&&"string"==typeof e&&(e=us(e,t)),e.manifest&&e.manifest.dash&&"defaultPresentationDelay"in e.manifest.dash&&(xe("manifest.dash.defaultPresentationDelay configuration","Please Use manifest.defaultPresentationDelay instead."),e.manifest.defaultPresentationDelay=e.manifest.dash.defaultPresentationDelay,delete e.manifest.dash.defaultPresentationDelay),e.streaming&&e.streaming.lowLatencyMode&&(null==e.streaming.inaccurateManifestTolerance&&(e.streaming.inaccurateManifestTolerance=0),null==e.streaming.rebufferingGoal&&(e.streaming.rebufferingGoal=.01));var n=ds(this.o,e,ks(this));return Es(this),n},i.getConfiguration=function(){var e=ks(this);return ds(e,this.o,ks(this)),e},i.Df=function(){for(var e in this.o)delete this.o[e];ds(this.o,ks(this),ks(this)),Es(this)},i.Ue=function(){return this.l},i.Ye=function(){return this.g},i.Vb=function(){return this.P},i.md=function(){return this.$a},i.ae=function(){return this.H?this.H:null},i.Z=function(){return this.B?this.B.presentationTimeline.Z():!(!this.g||!this.g.src)&&1/0==this.g.duration},i.mb=function(){return!!this.B&&this.B.presentationTimeline.mb()},i.lf=function(){if(this.B){var e=this.B.variants;return!!e.length&&!e[0].video}return!(!this.g||!this.g.src)&&(this.g.videoTracks?0==this.g.videoTracks.length:0==this.g.videoHeight)},i.Hd=function(){if(this.B){var e=this.B.presentationTimeline;return{start:e.zb(),end:e.Ua()}}return this.g&&this.g.src&&(e=this.g.seekable).length?{start:e.start(0),end:e.end(e.length-1)}:{start:0,end:0}},i.keySystem=function(){return Ea(this.drmInfo())},i.drmInfo=function(){return this.m?this.m.i:null},i.Ub=function(){return this.m?this.m.Ub():1/0},i.Bc=function(){return this.m?this.m.Bc():{}},i.pd=function(){return!!this.I&&this.I.g==Vr},i.$e=function(){return this.g?this.F?this.F.i:1:0},i.Mf=function(e){0==e?X("A trick play rate of 0 is unsupported!"):(this.g.paused&&this.g.play(),this.F.set(e),this.l==Mu&&(this.u.playbackRateChanged(e),Lo(this.i,1n(o,i))&&(a=o);if(a)return n=yr(a),void this.qe(n,!0)}Ns(this)}else if(this.g&&this.g.audioTracks){for(r=Array.from(this.g.audioTracks),n=er(e),a=i=null,o=(r=l(r)).next();!o.done;o=r.next()){var s=xr(o=o.value);er(s.language)==n&&(i=o,t?s.roles.includes(t)&&(a=o):0==s.roles.length&&(a=o))}a?Ls(this,a):i&&Ls(this,i)}},i.Jd=function(e,t,n){if(n=void 0!==n&&n,this.B&&this.C)this.ra=e,this.Ob=t||"",this.Nb=n,(e=kr(this.B.textStreams,this.ra,this.Ob,this.Nb)[0]||null)&&e!=this.i.i&&(gs(this.j.g,e,!1),this.o.streaming.alwaysStreamText||this.qd())&&(_o(this.i,e),Us(this));else{var i=er(e);(e=this.jb().find(function(e){return er(e.language)==i&&(!t||e.roles.includes(t))&&e.forced==n}))&&this.pe(e)}},i.Ef=function(e){if(this.B&&this.C){for(var t=null,n=l(this.B.variants),i=n.next();!i.done;i=n.next())if((i=i.value).audio.label==e){t=i;break}null!=t&&(this.qa=new Fr(t.language,"",0,e),Ns(this))}},i.qd=function(){var e=this.ea;return this.L?this.L.m.isTextVisible():this.g&&this.g.src&&this.g.textTracks?As(this).some(function(e){return"showing"==e.mode}):e},i.Kf=function(e){if(e=!!e,this.ea!=e){if(this.ea=e,this.l==Mu)this.L.m.setTextVisibility(e),this.o.streaming.alwaysStreamText||(e?this.i.i||0<(e=kr(this.B.textStreams,this.ra,this.Ob,this.Nb)).length&&(_o(this.i,e[0]),Us(this)):function(e){var t=e.g.get(si);t&&(qo(t),zo(t).catch(function(){}),e.g.delete(si)),e.i=null}(this.i));else if(this.g&&this.g.src&&this.g.textTracks)for(var t=As(this),n=(t=l(t)).next();!n.done;n=t.next())"disabled"!=(n=n.value).mode&&(n.mode=e?"showing":"hidden");Fs(this)}},i.bf=function(){if(!this.Z())return null;var e=this.la.l,t=0;if(this.C)t=this.C.l();else if(e){if(null==e.startTime)return new Date;t=e.startTime}return this.B?new Date(1e3*(this.B.presentationTimeline.j+t)):this.g&&this.g.getStartDate?(e=this.g.getStartDate(),isNaN(e.getTime())?null:new Date(e.getTime()+1e3*t)):null},i.be=function(){if(!this.Z())return null;if(this.B)return new Date(1e3*this.B.presentationTimeline.j);if(this.g&&this.g.getStartDate){var e=this.g.getStartDate();return isNaN(e.getTime())?null:e}return null},i.zc=function(){if(this.l==Mu)return this.L.zc();var e={total:[],audio:[],video:[],text:[]};return this.l==Cu&&(e.total=Hn(this.g.buffered)),e},i.getStats=function(){if(this.l!=Mu&&this.l!=Cu)return{width:NaN,height:NaN,streamBandwidth:NaN,decodedFrames:NaN,droppedFrames:NaN,corruptedFrames:NaN,estimatedBandwidth:NaN,completionPercent:NaN,loadLatency:NaN,manifestTimeSeconds:NaN,drmTimeSeconds:NaN,playTime:NaN,pauseTime:NaN,bufferingTime:NaN,licenseTime:NaN,liveLatency:NaN,maxSegmentDuration:NaN,switchHistory:[],stateHistory:[]};Ds(this);var e=this.g,t=e.currentTime/e.duration;if(!isNaN(t)){var n=this.j;t=Math.round(100*t),n.i=isNaN(n.i)?t:Math.max(n.i,t)}e.getVideoPlaybackQuality&&(e=e.getVideoPlaybackQuality(),n=this.j,t=Number(e.totalVideoFrames),n.U=Number(e.droppedVideoFrames),n.O=t,this.j.L=Number(e.corruptedVideoFrames)),this.m?e=(e=this.m).H?e.H:NaN:e=NaN,this.j.m=e,this.l==Mu&&((e=this.i.h)&&(this.j.u=(this.F?this.F.i:1)*e.bandwidth),e&&e.video&&(n=this.j,t=e.video.height||NaN,n.W=e.video.width||NaN,n.C=t),this.Z()&&(e=this.be().valueOf()+1e3*this.Hd().end,this.j.F=(Date.now()-e)/1e3),this.B&&this.B.presentationTimeline&&(this.j.I=this.B.presentationTimeline.g),e=this.u.getBandwidthEstimate(),this.j.s=e);var i=this.j;e=i.W,n=i.C,t=i.u;for(var r=i.O,a=i.U,o=i.L,s=i.s,u=i.i,c=i.l,d=i.H,f=i.j,h=hs(i.h,"playing"),p=hs(i.h,"paused"),g=hs(i.h,"buffering"),m=i.m,v=i.F,y=i.I,b=function(e){function t(e){return{timestamp:e.timestamp,state:e.state,duration:e.duration}}for(var n=[],i=l(e.h),r=i.next();!r.done;r=i.next())n.push(t(r.value));return e.g&&n.push(t(e.g)),n}(i.h),w=[],T=(i=l(i.g.g)).next();!T.done;T=i.next())T=T.value,w.push({timestamp:T.timestamp,id:T.id,type:T.type,fromAdaptation:T.fromAdaptation,bandwidth:T.bandwidth});return{width:e,height:n,streamBandwidth:t,decodedFrames:r,droppedFrames:a,corruptedFrames:o,estimatedBandwidth:s,completionPercent:u,loadLatency:c,manifestTimeSeconds:d,drmTimeSeconds:f,playTime:h,pauseTime:p,bufferingTime:g,licenseTime:m,liveLatency:v,maxSegmentDuration:y,stateHistory:b,switchHistory:w}},i.addTextTrack=function(e,t,n,i,r,a,o){if(o=void 0!==o&&o,xe("addTextTrack","Please use an addTextTrackAsync."),this.l!=Mu&&this.l!=Cu)throw new le(1,7,7004);if(!i){var s=Xa(e);if(!(i={sbv:"text/x-subviewer",srt:"text/srt",vtt:"text/vtt",webvtt:"text/vtt",ttml:"application/ttml+xml",lrc:"application/x-subtitle-lrc",ssa:"text/x-ssa",ass:"text/x-ssa"}[s]))throw new le(1,2,2011,s)}if(this.l==Cu){if("text/vtt"!=i)throw new le(1,2,2013,i);if(o&&(n="forced"),(i=document.createElement("track")).src=e,i.label=a||"",i.kind=n,i.srclang=t,this.g.getAttribute("crossorigin")||this.g.setAttribute("crossorigin","anonymous"),this.g.appendChild(i),e=this.jb().find(function(e){return e.language==t&&e.label==(a||"")&&e.kind==n}))return _s(this),e;throw new le(1,2,2012)}if(1/0==(s=this.B.presentationTimeline.getDuration()))throw new le(1,4,4033);if(!Si(yi((e={id:this.ld++,originalId:null,createSegmentIndex:function(){return Promise.resolve()},segmentIndex:bo(0,s,[e]),mimeType:i||"",codecs:r||"",kind:n,encrypted:!1,drmInfos:[],keyIds:new Set,language:t,label:a||null,type:si,primary:!1,trickModeVideo:null,emsgSchemeIdUris:null,roles:[],forced:!!o,channelsCount:null,audioSamplingRate:null,spatialAudio:!1,closedCaptions:null}).mimeType,e.codecs)))throw new le(2,2,2014,i);return this.B.textStreams.push(e),_s(this),br(e)},i.Ce=function(e,t,n,i,r,a,o){o=void 0!==o&&o;var s,u,c,d,f,h,p,g,m,v,y,b=this;return P(function(T){switch(T.g){case 1:if(b.l!=Mu&&b.l!=Cu)throw new le(1,7,7004);if(i){T.v(2);break}if(s=Xa(e),i={sbv:"text/x-subviewer",srt:"text/srt",vtt:"text/vtt",webvtt:"text/vtt",ttml:"application/ttml+xml",lrc:"application/x-subtitle-lrc",ssa:"text/x-ssa",ass:"text/x-ssa"}[s]){T.v(3);break}return x(T,4),w(T,za(e,b.P,b.o.streaming.retryParameters),6);case 6:i=T.h,E(T,3);break;case 4:A(T);case 3:if(!i)throw new le(1,2,2011,s);case 2:if(b.l!=Cu){T.v(7);break}if("text/vtt"==i){T.v(8);break}return w(T,function(e,t,n){var i,r,a;return P(function(o){return 1==o.g?(i=la,(r=oa([e],n)).method="GET",w(o,t.request(i,r).promise,2)):(a=o.h,o.return(a.data))})}(e,b.P,b.o.streaming.retryParameters),9);case 9:u=T.h,c=function(e,t,n){var i=Ii[n];if(i)return n=i(),e={periodStart:0,segmentStart:0,segmentEnd:e.g.duration},t=oe(t),function(e){function t(e){var n=[],i=700<=e.fontWeight,r="italic"==e.fontStyle,a=e.textDecoration.includes("underline");return i&&n.push("b"),r&&n.push("i"),a&&n.push("u"),i=n.reduce(function(e,t){return e+"<"+t+">"},""),n=n.reduceRight(function(e,t){return e+""},""),e.lineBreak||e.spacer?(e.spacer&&xe("shaka.text.Cue","Please use lineBreak instead of spacer."),"\n"):e.nestedCues.length?e.nestedCues.map(t).join(""):i+e.payload+n}var n=e.map(function(e){if(e.nestedCues.length){var n=e.clone();return n.nestedCues=[],n.payload=t(e),n}return e});e="WEBVTT\n\n";for(var i=(n=l(n)).next();!i.done;i=n.next()){var r=function(e){var t=Math.floor(e/3600),n=Math.floor(e/60%60),i=Math.floor(e%60);return(10>t?"0":"")+t+":"+(10>n?"0":"")+n+":"+(10>i?"0":"")+i+"."+(100>(e=Math.floor(1e3*e%1e3))?10>e?"00":"0":"")+e};e+=r((i=i.value).startTime)+" --\x3e "+r(i.endTime)+"\n",e+=i.payload+"\n\n"}return e}(t=n.parseMedia(t,e));throw new le(2,2,2014,n)}(b,u,i),d=new Blob([c],{type:"text/vtt"}),e=$i(d),i="text/vtt";case 8:if(o&&(n="forced"),(f=document.createElement("track")).src=e,f.label=a||"",f.kind=n,f.srclang=t,b.g.getAttribute("crossorigin")||b.g.setAttribute("crossorigin","anonymous"),b.g.appendChild(f),h=b.jb(),p=h.find(function(e){return e.language==t&&e.label==(a||"")&&e.kind==n}))return _s(b),T.return(p);throw new le(1,2,2012);case 7:if(g=ui,1/0==(m=b.B.presentationTimeline.getDuration()))throw new le(1,4,4033);if(v={id:b.ld++,originalId:null,createSegmentIndex:function(){return Promise.resolve()},segmentIndex:bo(0,m,[e]),mimeType:i||"",codecs:r||"",kind:n,encrypted:!1,drmInfos:[],keyIds:new Set,language:t,label:a||null,type:g.ba,primary:!1,trickModeVideo:null,emsgSchemeIdUris:null,roles:[],forced:!!o,channelsCount:null,audioSamplingRate:null,spatialAudio:!1,closedCaptions:null},y=yi(v.mimeType,v.codecs),!Si(y))throw new le(2,2,2014,i);return b.B.textStreams.push(v),_s(b),T.return(br(v))}})},i.Md=function(e,t){this.kd.width=e,this.kd.height=t},i.Fd=function(){if(this.l==Mu){var e=this.i;if(e.J.g)e=!1;else if(e.j)e=!1;else{for(var t=l(e.g.values()),n=t.next();!n.done;n=t.next())(n=n.value).Yb&&(n.Yb=!1,Go(e,n,.1));e=!0}}else e=!1;return e},i.Ve=function(){return X("Shaka Player's internal Manifest structure is NOT covered by semantic versioning compatibility guarantees. It may change at any time! Please consider filing a feature request for whatever you use getManifest() for."),this.B},i.We=function(){return this.tc},i.ue=function(e){this.qc=e},i.yc=function(e){var t=this;return P(function(n){if(1==n.g)return w(n,function(e,t){var n;return P(function(i){if(1==i.g)return n=e.i?e.i.h:null,w(i,ur(e.m,n,t,e.o.useMediaCapabilities),2);Ws(t),T(i)})}(t,e),2);Is(t,e),T(n)})},B("shaka.Player",vs),vs.prototype.setVideoContainer=vs.prototype.ue,vs.prototype.getManifestParserFactory=vs.prototype.We,vs.prototype.getManifest=vs.prototype.Ve,vs.prototype.retryStreaming=vs.prototype.Fd,vs.prototype.setMaxHardwareResolution=vs.prototype.Md,vs.prototype.addTextTrackAsync=vs.prototype.Ce,vs.prototype.addTextTrack=vs.prototype.addTextTrack,vs.prototype.getStats=vs.prototype.getStats,vs.prototype.getBufferedInfo=vs.prototype.zc,vs.prototype.getPresentationStartTimeAsDate=vs.prototype.be,vs.prototype.getPlayheadTimeAsDate=vs.prototype.bf,vs.prototype.setTextTrackVisibility=vs.prototype.Kf,vs.prototype.isTextTrackVisible=vs.prototype.qd,vs.prototype.selectVariantsByLabel=vs.prototype.Ef,vs.prototype.selectTextLanguage=vs.prototype.Jd,vs.prototype.selectAudioLanguage=vs.prototype.Id,vs.prototype.getTextLanguages=vs.prototype.ff,vs.prototype.getAudioLanguages=vs.prototype.Oe,vs.prototype.getTextLanguagesAndRoles=vs.prototype.gf,vs.prototype.getAudioLanguagesAndRoles=vs.prototype.Pe,vs.prototype.selectVariantTrack=vs.prototype.qe,vs.prototype.selectTextTrack=vs.prototype.pe,vs.prototype.getThumbnails=vs.prototype.hf,vs.prototype.getImageTracks=vs.prototype.Se,vs.prototype.getTextTracks=vs.prototype.jb,vs.prototype.getVariantTracks=vs.prototype.Ec,vs.prototype.cancelTrickPlay=vs.prototype.Ge,vs.prototype.trickPlay=vs.prototype.Mf,vs.prototype.getPlaybackRate=vs.prototype.$e,vs.prototype.isBuffering=vs.prototype.pd,vs.prototype.getKeyStatuses=vs.prototype.Bc,vs.prototype.getExpiration=vs.prototype.Ub,vs.prototype.drmInfo=vs.prototype.drmInfo,vs.prototype.keySystem=vs.prototype.keySystem,vs.prototype.seekRange=vs.prototype.Hd,vs.prototype.isAudioOnly=vs.prototype.lf,vs.prototype.isInProgress=vs.prototype.mb,vs.prototype.isLive=vs.prototype.Z,vs.prototype.getAdManager=vs.prototype.ae,vs.prototype.getAssetUri=vs.prototype.md,vs.prototype.getNetworkingEngine=vs.prototype.Vb,vs.prototype.getMediaElement=vs.prototype.Ye,vs.prototype.getLoadMode=vs.prototype.Ue,vs.prototype.resetConfiguration=vs.prototype.Df,vs.prototype.getConfiguration=vs.prototype.getConfiguration,vs.prototype.configure=vs.prototype.configure,vs.prototype.load=vs.prototype.load,vs.prototype.unload=vs.prototype.Rd,vs.prototype.detach=vs.prototype.detach,vs.prototype.attach=vs.prototype.Qb,vs.probeSupport=function(e){var t,n,i,r,a;return e=void 0===e||e,P(function(o){if(1==o.g)return t={},e?w(o,function(){var e,t,n,i,r,a;return P(function(o){return 1==o.g?(e="org.w3.clearkey com.widevine.alpha com.microsoft.playready com.microsoft.playready.recommendation com.apple.fps.3_0 com.apple.fps.2_0 com.apple.fps.1_0 com.apple.fps com.adobe.primetime".split(" "),n=[{videoCapabilities:t=[{contentType:'video/mp4; codecs="avc1.42E01E"'},{contentType:'video/webm; codecs="vp8"'}],persistentState:"required",sessionTypes:["persistent-license"]},{initDataTypes:["cenc"],videoCapabilities:t}],i=new Map,r=function(e){var t,r,a;return P(function(o){switch(o.g){case 1:return x(o,2),w(o,navigator.requestMediaKeySystemAccess(e,n),4);case 4:return t=o.h,a=!!(r=t.getConfiguration().sessionTypes)&&r.includes("persistent-license"),We("Tizen 3")&&(a=!1),i.set(e,{persistentState:a}),w(o,t.createMediaKeys(),5);case 5:E(o,0);break;case 2:A(o),i.set(e,null),T(o)}})},a=e.map(function(e){return r(e)}),w(o,Promise.all(a),2)):o.return(ma(i))})}(),3):o.v(2);2!=o.g&&(t=o.h);var s={};if(Ve()){for(var u in Wa)s[u]=!0;for(var c in Ya)s[c]=!0}u={mpd:"application/dash+xml",m3u8:"application/x-mpegurl",ism:"application/vnd.ms-sstr+xml"};for(var d=(c=l(["application/dash+xml","application/x-mpegurl","application/vnd.apple.mpegurl","application/vnd.ms-sstr+xml"])).next();!d.done;d=c.next())s[d=d.value]=Ve()?!!Wa[d]:He(d);for(var f in u)s[f]=Ve()?!!Ya[f]:He(u[f]);for(n=s,s={},u=(f=l('video/mp4; codecs="avc1.42E01E",video/mp4; codecs="avc3.42E01E",video/mp4; codecs="hev1.1.6.L93.90",video/mp4; codecs="hvc1.1.6.L93.90",video/mp4; codecs="hev1.2.4.L153.B0"; eotf="smpte2084",video/mp4; codecs="hvc1.2.4.L153.B0"; eotf="smpte2084",video/mp4; codecs="vp9",video/mp4; codecs="vp09.00.10.08",video/mp4; codecs="av01.0.01M.08",audio/mp4; codecs="mp4a.40.2",audio/mp4; codecs="ac-3",audio/mp4; codecs="ec-3",audio/mp4; codecs="opus",audio/mp4; codecs="flac",video/webm; codecs="vp8",video/webm; codecs="vp9",video/webm; codecs="vp09.00.10.08",audio/webm; codecs="vorbis",audio/webm; codecs="opus",video/mp2t; codecs="avc1.42E01E",video/mp2t; codecs="avc3.42E01E",video/mp2t; codecs="hvc1.1.6.L93.90",video/mp2t; codecs="mp4a.40.2",video/mp2t; codecs="ac-3",video/mp2t; codecs="ec-3",text/vtt,application/mp4; codecs="wvtt",application/ttml+xml,application/mp4; codecs="stpp"'.split(","))).next();!u.done;u=f.next())s[u=u.value]=Ve()?!!Si(u)||(MediaSource.isTypeSupported(u)||gi(u)):He(u),s[c=u.split(";")[0]]=s[c]||s[u];for(a in i={manifest:n,media:s,drm:t},r=Nu)i[a]=r[a]();return o.return(i)})},vs.isBrowserSupported=function(){if(e.Promise||X("A Promise implementation or polyfill is required"),e.TextDecoder&&e.TextEncoder||X("A TextDecoder/TextEncoder implementation or polyfill is required"),!(e.Promise&&e.Uint8Array&&e.TextDecoder&&e.TextEncoder&&Array.prototype.forEach)||We("Trident/"))return!1;var t=Xe();return!(t&&12>t||!(e.MediaKeys&&e.navigator&&e.navigator.requestMediaKeySystemAccess&&e.MediaKeySystemAccess&&e.MediaKeySystemAccess.prototype.getConfiguration))&&(!!Ve()||He("application/x-mpegurl"))},vs.setAdManagerFactory=function(e){Pu=e},vs.registerSupportPlugin=function(e,t){Nu[e]=t},vs.prototype.destroy=vs.prototype.destroy;var nu="abrstatuschanged",iu="adaptation",ru="buffering",au="drmsessionupdate",ou="emsg",su="error",uu="expirationupdated",lu="loaded",cu="loading",du="manifestparsed",fu="metadata",hu="onstatechange",pu="onstateidle",gu="ratechange",mu="streaming",vu="textchanged",yu="texttrackvisibility",bu="timelineregionadded",wu="timelineregionenter",Tu="timelineregionexit",xu="trackschanged",Su="unloading",Eu="variantchanged",Au={Tf:nu,Uf:iu,Vf:ru,Wf:au,Yf:ou,Error:su,Zf:uu,$f:"largegap",ag:lu,bg:cu,cg:du,Metadata:fu,dg:hu,eg:pu,fg:gu,gg:"sessiondata",hg:mu,ig:vu,jg:yu,kg:bu,lg:wu,mg:Tu,ng:xu,og:Su,pg:Eu},ku=0,Iu=1,Mu=2,Cu=3;vs.LoadMode={DESTROYED:ku,NOT_LOADED:Iu,MEDIA_SOURCE:Mu,SRC_EQUALS:Cu},vs.version="v3.1.6";var Du=["3","1"];Ae=new function(e){this.g=e,this.i=Se,this.h=Ee}(new Te(Number(Du[0]),Number(Du[1])));var Ru=["output-restricted","internal-error"],Nu={},Pu=null;function Lu(){this.h=[],this.j=this.i=this.g=0}function ju(e,t){var n=this;this.i=e,this.g=t,this.j=!1,this.l=this.g.getVolume(),this.h=new Ni,this.h.A(this.g,google.ima.AdEvent.Type.PAUSED,function(){n.j=!0}),this.h.A(this.g,google.ima.AdEvent.Type.RESUMED,function(){n.j=!1})}function _u(t,n,i,r){var a=this;this.m=t,this.g=n,this.u=null,this.C=NaN,this.j=r,this.s=null,this.h=new Ni,google.ima.settings.setLocale(i),(t=new google.ima.AdDisplayContainer(this.m,this.g)).initialize(),this.l=new google.ima.AdsLoader(t),this.l.getSettings().setPlayerType("shaka-player"),this.l.getSettings().setPlayerVersion("v3.1.6"),this.i=null,this.h.wa(this.l,google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,function(t){!function(t,n){t.j(new Jr("ads-loaded",(new Map).set("loadTime",Date.now()/1e3-t.C))),t.i=n.getAdsManager(t.g),t.j(new Jr("ima-ad-manager-loaded",(new Map).set("imaAdManager",t.i)));var i=t.i.getCuePoints();if(i.length){for(var r=[],a=(i=l(i)).next();!a.done;a=i.next())r.push(new Ku(a.value));t.j(new Jr("ad-cue-points-changed",(new Map).set("cuepoints",r)))}!function(e){function t(t,n){var i=(new Map).set("originalEvent",t);e.j(new Jr(n,i))}e.h.A(e.i,google.ima.AdErrorEvent.Type.AD_ERROR,function(t){Ou(e,t)}),e.h.A(e.i,google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED,function(t){Uu(e,t)}),e.h.A(e.i,google.ima.AdEvent.Type.STARTED,function(t){Uu(e,t)}),e.h.A(e.i,google.ima.AdEvent.Type.FIRST_QUARTILE,function(e){t(e,"ad-first-quartile")}),e.h.A(e.i,google.ima.AdEvent.Type.MIDPOINT,function(e){t(e,"ad-midpoint")}),e.h.A(e.i,google.ima.AdEvent.Type.THIRD_QUARTILE,function(e){t(e,"ad-third-quartile")}),e.h.A(e.i,google.ima.AdEvent.Type.COMPLETE,function(e){t(e,"ad-complete")}),e.h.A(e.i,google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED,function(t){Fu(e,t)}),e.h.A(e.i,google.ima.AdEvent.Type.ALL_ADS_COMPLETED,function(t){Fu(e,t)}),e.h.A(e.i,google.ima.AdEvent.Type.SKIPPED,function(e){t(e,"ad-skipped")}),e.h.A(e.i,google.ima.AdEvent.Type.VOLUME_CHANGED,function(e){t(e,"ad-volume-changed")}),e.h.A(e.i,google.ima.AdEvent.Type.VOLUME_MUTED,function(e){t(e,"ad-muted")}),e.h.A(e.i,google.ima.AdEvent.Type.PAUSED,function(n){e.s.j=!0,t(n,"ad-paused")}),e.h.A(e.i,google.ima.AdEvent.Type.RESUMED,function(n){e.s.j=!1,t(n,"ad-resumed")}),e.h.A(e.i,google.ima.AdEvent.Type.SKIPPABLE_STATE_CHANGED,function(e){t(e,"ad-skip-state-changed")}),e.h.A(e.i,google.ima.AdEvent.Type.CLICK,function(e){t(e,"ad-clicked")}),e.h.A(e.i,google.ima.AdEvent.Type.AD_PROGRESS,function(e){t(e,"ad-progress")}),e.h.A(e.i,google.ima.AdEvent.Type.AD_BUFFERING,function(e){t(e,"ad-buffering")}),e.h.A(e.i,google.ima.AdEvent.Type.IMPRESSION,function(e){t(e,"ad-impression")}),e.h.A(e.i,google.ima.AdEvent.Type.DURATION_CHANGE,function(e){t(e,"ad-duration-changed")}),e.h.A(e.i,google.ima.AdEvent.Type.USER_CLOSE,function(e){t(e,"ad-closed")}),e.h.A(e.i,google.ima.AdEvent.Type.LOADED,function(e){t(e,"ad-loaded")}),e.h.A(e.i,google.ima.AdEvent.Type.ALL_ADS_COMPLETED,function(e){t(e,"all-ads-completed")}),e.h.A(e.i,google.ima.AdEvent.Type.LINEAR_CHANGED,function(e){t(e,"ad-linear-changed")}),e.h.A(e.i,google.ima.AdEvent.Type.AD_METADATA,function(e){t(e,"ad-metadata")}),e.h.A(e.i,google.ima.AdEvent.Type.LOG,function(e){t(e,"ad-recoverable-error")}),e.h.A(e.i,google.ima.AdEvent.Type.AD_BREAK_READY,function(e){t(e,"ad-break-ready")}),e.h.A(e.i,google.ima.AdEvent.Type.INTERACTION,function(e){t(e,"ad-interaction")})}(t);try{t.i.init(t.g.offsetWidth,t.g.offsetHeight,document.fullscreenElement?google.ima.ViewMode.FULLSCREEN:google.ima.ViewMode.NORMAL),t.h.A(t.g,"loadeddata",function(){t.i.resize(t.g.offsetWidth,t.g.offsetHeight,document.fullscreenElement?google.ima.ViewMode.FULLSCREEN:google.ima.ViewMode.NORMAL)}),"ResizeObserver"in e&&(t.u=new ResizeObserver(function(){t.i.resize(t.g.offsetWidth,t.g.offsetHeight,document.fullscreenElement?google.ima.ViewMode.FULLSCREEN:google.ima.ViewMode.NORMAL)}),t.u.observe(t.g)),t.i.start()}catch(e){Fu(t,null)}}(a,t)}),this.h.A(this.l,google.ima.AdErrorEvent.Type.AD_ERROR,function(e){Ou(a,e)}),this.g.onended=function(){a.l.contentComplete()}}function Ou(e,t){t.getError(),Fu(e,null),e.j(new Jr("ad-cue-points-changed",(new Map).set("cuepoints",[])))}function Uu(e,t){var n=t.getAd();e.s=new ju(n,e.i),n=(new Map).set("ad",e.s).set("sdkAdObject",n).set("originalEvent",t),e.j(new Jr("ad-started",n)),e.m.setAttribute("ad-active","true"),e.g.pause()}function Fu(e,t){e.j(new Jr("ad-stopped",(new Map).set("originalEvent",t))),e.m.removeAttribute("ad-active"),e.g.play()}function Bu(e,t){this.i=e,this.h=null,this.g=t}function Vu(e,t,n,i){var r=this;this.u=e,this.g=t,this.l=null,this.I=NaN,this.j=i,this.H=!1,this.C=this.m=this.s=null,this.F="",this.h=new Ni,(e=new google.ima.dai.api.UiSettings).setLocale(n),this.i=new google.ima.dai.api.StreamManager(this.g,this.u,e),this.j(new Jr("ima-stream-manager-loaded",(new Map).set("imaStreamManager",this.i))),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.LOADED,function(e){!function(e,t){e.j(new Jr("ads-loaded",(new Map).set("loadTime",Date.now()/1e3-e.I)));var n=t.getStreamData().url;e.l.resolve(n),e.l=null,e.H||e.h.A(e.g,"seeked",function(){var t=e.g.currentTime;if(0!=t){e.i.streamTimeForContentTime(t);var n=e.i.previousCuePointForStreamTime(t);n&&!n.played&&(e.s=t,e.g.currentTime=n.start)}})}(r,e)}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.ERROR,function(){r.F.length?r.l.resolve(r.F):r.l.reject("IMA Stream request returned an error and there was no backup asset uri provided."),r.l=null}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,function(){}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.STARTED,function(e){e=e.getAd(),r.m=new Bu(e,r.g),r.C&&(r.m.h=r.C),r.j(new Jr("ad-started",(new Map).set("ad",r.m))),r.u.setAttribute("ad-active","true")}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED,function(){r.u.removeAttribute("ad-active");var e=r.g.currentTime;r.s&&r.s>e&&(r.g.currentTime=r.s,r.s=null)}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.AD_PROGRESS,function(e){r.C=e.getStreamData().adProgressData,r.m&&(r.m.h=r.C)}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.FIRST_QUARTILE,function(){r.j(new Jr("ad-first-quartile"))}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.MIDPOINT,function(){r.j(new Jr("ad-midpoint"))}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.THIRD_QUARTILE,function(){r.j(new Jr("ad-third-quartile"))}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.COMPLETE,function(){r.j(new Jr("ad-complete")),r.j(new Jr("ad-stopped")),r.u.removeAttribute("ad-active"),r.m=null}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.SKIPPED,function(){r.j(new Jr("ad-skipped")),r.j(new Jr("ad-stopped"))}),this.h.A(this.i,google.ima.dai.api.StreamEvent.Type.CUEPOINTS_CHANGED,function(e){var t=e.getStreamData();e=[];for(var n=(t=l(t.cuepoints)).next();!n.done;n=t.next())n=n.value,e.push(new Ku(n.start,n.end));r.j(new Jr("ad-cue-points-changed",(new Map).set("cuepoints",e)))})}function Hu(){Zr.call(this),this.g=this.h=null,this.j=new Lu,this.i=navigator.language}function Ku(e,t){this.start=e,this.end=void 0===t?null:t}function Gu(e){return JSON.stringify(e,function(e,t){if("function"!=typeof t){if(t instanceof Event||t instanceof Jr){var n={};for(r in t){var i=t[r];i&&"object"==typeof i?"detail"==r&&(n[r]=i):r in Event||(n[r]=i)}return n}if(t instanceof Error){var r=new Set(["name","message","stack"]);for(n in t)r.add(n);for(n=(i=l(Object.getOwnPropertyNames(t))).next();!n.done;n=i.next())r.add(n.value);for(i={},n=(r=l(r)).next();!n.done;n=r.next())i[n=n.value]=t[n];r={__type__:"Error",contents:i}}else if(t instanceof TimeRanges)for(r={__type__:"TimeRanges",length:t.length,start:[],end:[]},i=(n=l(Hn(t))).next();!i.done;i=n.next()){var a=(i=i.value).end;r.start.push(i.start),r.end.push(a)}else r=t instanceof Uint8Array?{__type__:"Uint8Array",entries:Array.from(t)}:"number"==typeof t?isNaN(t)?"NaN":isFinite(t)?t:0>t?"-Infinity":"Infinity":t;return r}})}function qu(e){return JSON.parse(e,function(e,t){if("NaN"==t)var n=NaN;else if("-Infinity"==t)n=-1/0;else if("Infinity"==t)n=1/0;else if(t&&"object"==typeof t&&"TimeRanges"==t.__type__)n={length:(a=t).length,start:function(e){return a.start[e]},end:function(e){return a.end[e]}};else if(t&&"object"==typeof t&&"Uint8Array"==t.__type__)n=new Uint8Array(t.entries);else if(t&&"object"==typeof t&&"Error"==t.__type__){n=t.contents;var i,r=Error(n.message);for(i in n)r[i]=n[i];n=r}else n=t;var a;return n})}(i=ju.prototype).getDuration=function(){return this.i.getDuration()},i.getMinSuggestedDuration=function(){return this.i.getMinSuggestedDuration()},i.getRemainingTime=function(){return this.g.getRemainingTime()},i.isPaused=function(){return this.j},i.isSkippable=function(){return 0<=this.i.getSkipTimeOffset()},i.getTimeUntilSkippable=function(){var e=this.i.getSkipTimeOffset();return e=this.getRemainingTime()-e,Math.max(e,0)},i.canSkipNow=function(){return this.g.getAdSkippableState()},i.skip=function(){return this.g.skip()},i.pause=function(){return this.g.pause()},i.play=function(){return this.g.resume()},i.getVolume=function(){return this.g.getVolume()},i.setVolume=function(e){return this.g.setVolume(e)},i.isMuted=function(){return 0==this.g.getVolume()},i.resize=function(e,t){this.g.resize(e,t,document.fullscreenElement?google.ima.ViewMode.FULLSCREEN:google.ima.ViewMode.NORMAL)},i.setMuted=function(e){e?(this.l=this.getVolume(),this.setVolume(0)):this.setVolume(this.l)},i.getSequenceLength=function(){var e=this.i.getAdPodInfo();return null==e?1:e.getTotalAds()},i.getPositionInSequence=function(){var e=this.i.getAdPodInfo();return null==e?1:e.getAdPosition()},i.release=function(){this.g=this.i=null},B("shaka.ads.ClientSideAd",ju),ju.prototype.release=ju.prototype.release,ju.prototype.getPositionInSequence=ju.prototype.getPositionInSequence,ju.prototype.getSequenceLength=ju.prototype.getSequenceLength,ju.prototype.setMuted=ju.prototype.setMuted,ju.prototype.resize=ju.prototype.resize,ju.prototype.isMuted=ju.prototype.isMuted,ju.prototype.setVolume=ju.prototype.setVolume,ju.prototype.getVolume=ju.prototype.getVolume,ju.prototype.play=ju.prototype.play,ju.prototype.pause=ju.prototype.pause,ju.prototype.skip=ju.prototype.skip,ju.prototype.canSkipNow=ju.prototype.canSkipNow,ju.prototype.getTimeUntilSkippable=ju.prototype.getTimeUntilSkippable,ju.prototype.isSkippable=ju.prototype.isSkippable,ju.prototype.isPaused=ju.prototype.isPaused,ju.prototype.getRemainingTime=ju.prototype.getRemainingTime,ju.prototype.getMinSuggestedDuration=ju.prototype.getMinSuggestedDuration,ju.prototype.getDuration=ju.prototype.getDuration,_u.prototype.stop=function(){this.i&&this.i.stop(),this.m&&ts(this.m)},_u.prototype.release=function(){this.stop(),this.u&&this.u.disconnect(),this.h&&this.h.release(),this.i&&this.i.destroy(),this.l.destroy()},(i=Bu.prototype).getDuration=function(){return this.h?this.h.duration:-1},i.getMinSuggestedDuration=function(){return this.getDuration()},i.getRemainingTime=function(){return this.h?this.h.duration-this.h.currentTime:-1},i.isPaused=function(){return this.g.paused},i.isSkippable=function(){return this.i.isSkippable()},i.getTimeUntilSkippable=function(){var e=this.i.getSkipTimeOffset();return e=this.getRemainingTime()-e,Math.max(e,0)},i.canSkipNow=function(){return 0==this.getTimeUntilSkippable()},i.skip=function(){this.g.currentTime+=this.getRemainingTime()},i.pause=function(){return this.g.pause()},i.play=function(){return this.g.play()},i.getVolume=function(){return this.g.volume},i.setVolume=function(e){this.g.volume=e},i.isMuted=function(){return this.g.muted},i.resize=function(){},i.setMuted=function(e){this.g.muted=e},i.getSequenceLength=function(){var e=this.i.getAdPodInfo();return null==e?1:e.getTotalAds()},i.getPositionInSequence=function(){var e=this.i.getAdPodInfo();return null==e?1:e.getAdPosition()},i.release=function(){this.g=this.h=this.i=null},B("shaka.ads.ServerSideAd",Bu),Bu.prototype.release=Bu.prototype.release,Bu.prototype.getPositionInSequence=Bu.prototype.getPositionInSequence,Bu.prototype.getSequenceLength=Bu.prototype.getSequenceLength,Bu.prototype.setMuted=Bu.prototype.setMuted,Bu.prototype.resize=Bu.prototype.resize,Bu.prototype.isMuted=Bu.prototype.isMuted,Bu.prototype.setVolume=Bu.prototype.setVolume,Bu.prototype.getVolume=Bu.prototype.getVolume,Bu.prototype.play=Bu.prototype.play,Bu.prototype.pause=Bu.prototype.pause,Bu.prototype.skip=Bu.prototype.skip,Bu.prototype.canSkipNow=Bu.prototype.canSkipNow,Bu.prototype.getTimeUntilSkippable=Bu.prototype.getTimeUntilSkippable,Bu.prototype.isSkippable=Bu.prototype.isSkippable,Bu.prototype.isPaused=Bu.prototype.isPaused,Bu.prototype.getRemainingTime=Bu.prototype.getRemainingTime,Bu.prototype.getMinSuggestedDuration=Bu.prototype.getMinSuggestedDuration,Bu.prototype.getDuration=Bu.prototype.getDuration,Vu.prototype.stop=function(){this.F="",this.s=null},Vu.prototype.release=function(){this.stop(),this.h&&this.h.release()},Vu.prototype.onCueMetadataChange=function(e){if(e.key&&e.data){var t={};t[e.key]=e.data,this.i.onTimedMetadata(t)}},m(Hu,Zr),(i=Hu.prototype).setLocale=function(e){this.i=e},i.initClientSide=function(t,n){var i=this;if(!e.google||!google.ima||!google.ima.AdsLoader)throw new le(2,10,1e4);this.h&&this.h.release(),this.h=new _u(t,n,this.i,function(e){if(e&&e.type)switch(e.type){case"ads-loaded":i.j.h.push(e.loadTime);break;case"ad-started":i.j.g++;break;case"ad-complete":i.j.i++;break;case"ad-skipped":i.j.j++}i.dispatchEvent(e)})},i.release=function(){this.h&&(this.h.release(),this.h=null),this.g&&(this.g.release(),this.g=null),Zr.prototype.release.call(this)},i.onAssetUnload=function(){this.h&&this.h.stop(),this.g&&this.g.stop(),this.dispatchEvent(new Jr("ad-stopped")),this.j=new Lu},i.requestClientSideAds=function(e){if(!this.h)throw new le(1,10,10001);var t=this.h;t.C=Date.now()/1e3,t.l.requestAds(e)},i.initServerSide=function(t,n){var i=this;if(!e.google||!google.ima||!google.ima.dai)throw new le(2,10,10002);this.g&&this.g.release(),this.g=new Vu(t,n,this.i,function(e){if(e&&e.type)switch(e.type){case"ads-loaded":i.j.h.push(e.loadTime);break;case"ad-started":i.j.g++;break;case"ad-complete":i.j.i++;break;case"ad-skipped":i.j.j++}i.dispatchEvent(e)})},i.requestServerSideStream=function(e,t){if(t=void 0===t?"":t,!this.g)throw new le(1,10,10003);e.adTagParameters||(e.adTagParameters={});var n=e.adTagParameters;(n.mpt||n.mpv)&&X('You have attempted to set "mpt" and/or "mpv" parameters of the ad tag. Please note that those parameters are used for Shaka adoption tracking and will be overriden.'),e.adTagParameters.mpt="shaka-player",e.adTagParameters.mpv="v3.1.6";var i=t;return(n=this.g).l?n=Promise.reject(new le(1,10,10004)):(e instanceof google.ima.dai.api.LiveStreamRequest&&(n.H=!0),n.l=new ci,n.i.requestStream(e),n.F=i||"",n.I=Date.now()/1e3,n=n.l),n},i.replaceServerSideAdTagParameters=function(e){if(!this.g)throw new le(1,10,10003);(e.mpt||e.mpv)&&X('You have attempted to set "mpt" and/or "mpv" parameters of the ad tag. Please note that those parameters are used for Shaka adoption tracking and will be overriden.'),e.mpt="Shaka Player",e.mpv="v3.1.6",this.g.i.replaceAdTagParameters(e)},i.getStats=function(){var e=this.j;return{loadTimes:e.h,started:e.g,playedCompletely:e.i,skipped:e.j}},i.onDashTimedMetadata=function(e){if(this.g&&"urn:google:dai:2018"==e.schemeIdUri){var t=e.schemeIdUri,n=e.eventElement?e.eventElement.getAttribute("messageData"):null;this.g.i.processMetadata(t,n,e.startTime)}},i.onHlsTimedMetadata=function(e,t){this.g&&this.g.i.processMetadata("ID3",e.data,t)},i.onCueMetadataChange=function(e){this.g&&this.g.onCueMetadataChange(e)},B("shaka.ads.AdManager",Hu),Hu.prototype.onCueMetadataChange=Hu.prototype.onCueMetadataChange,Hu.prototype.onHlsTimedMetadata=Hu.prototype.onHlsTimedMetadata,Hu.prototype.onDashTimedMetadata=Hu.prototype.onDashTimedMetadata,Hu.prototype.getStats=Hu.prototype.getStats,Hu.prototype.replaceServerSideAdTagParameters=Hu.prototype.replaceServerSideAdTagParameters,Hu.prototype.requestServerSideStream=Hu.prototype.requestServerSideStream,Hu.prototype.initServerSide=Hu.prototype.initServerSide,Hu.prototype.requestClientSideAds=Hu.prototype.requestClientSideAds,Hu.prototype.onAssetUnload=Hu.prototype.onAssetUnload,Hu.prototype.release=Hu.prototype.release,Hu.prototype.initClientSide=Hu.prototype.initClientSide,Hu.prototype.setLocale=Hu.prototype.setLocale,Hu.ADS_LOADED="ads-loaded",Hu.AD_STARTED="ad-started",Hu.AD_FIRST_QUARTILE="ad-first-quartile",Hu.AD_MIDPOINT="ad-midpoint",Hu.AD_THIRD_QUARTILE="ad-third-quartile",Hu.AD_COMPLETE="ad-complete",Hu.AD_STOPPED="ad-stopped",Hu.AD_SKIPPED="ad-skipped",Hu.AD_VOLUME_CHANGED="ad-volume-changed",Hu.AD_MUTED="ad-muted",Hu.AD_PAUSED="ad-paused",Hu.AD_RESUMED="ad-resumed",Hu.AD_SKIP_STATE_CHANGED="ad-skip-state-changed",Hu.CUEPOINTS_CHANGED="ad-cue-points-changed",Hu.IMA_AD_MANAGER_LOADED="ima-ad-manager-loaded",Hu.IMA_STREAM_MANAGER_LOADED="ima-stream-manager-loaded",Hu.AD_CLICKED="ad-clicked",Hu.AD_PROGRESS="ad-progress",Hu.AD_BUFFERING="ad-buffering",Hu.AD_IMPRESSION="ad-impression",Hu.AD_DURATION_CHANGED="ad-duration-changed",Hu.AD_CLOSED="ad-closed",Hu.AD_LOADED="ad-loaded",Hu.ALL_ADS_COMPLETED="all-ads-completed",Hu.AD_LINEAR_CHANGED="ad-linear-changed",Hu.AD_METADATA="ad-metadata",Hu.AD_RECOVERABLE_ERROR="ad-recoverable-error",Hu.AD_BREAK_READY="ad-break-ready",Hu.AD_INTERACTION="ad-interaction",Pu=function(){return new Hu};var zu="ended play playing pause pausing ratechange seeked seeking timeupdate volumechange".split(" "),Xu="buffered currentTime duration ended loop muted paused playbackRate seeking videoHeight videoWidth volume".split(" "),Wu=["loop","playbackRate"],Yu=["pause","play"],$u={getAssetUri:2,getAudioLanguages:4,getAudioLanguagesAndRoles:4,getBufferedInfo:2,getConfiguration:2,getExpiration:2,getKeyStatuses:2,getPlaybackRate:2,getTextLanguages:4,getTextLanguagesAndRoles:4,getTextTracks:2,getStats:5,getVariantTracks:2,getImageTracks:2,getThumbnails:2,isAudioOnly:10,isBuffering:1,isInProgress:1,isLive:10,isTextTrackVisible:1,keySystem:10,seekRange:1,getLoadMode:10},Ju={getPlayheadTimeAsDate:1,getPresentationStartTimeAsDate:20},Qu=[["getConfiguration","configure"]],Zu=[["isTextTrackVisible","setTextTrackVisibility"]],el="addTextTrack addTextTrackAsync cancelTrickPlay configure resetConfiguration retryStreaming selectAudioLanguage selectTextLanguage selectTextTrack selectVariantTrack selectVariantsByLabel setTextTrackVisibility trickPlay".split(" "),tl=["attach","detach","load","unload"];function nl(e,t,n,i,r,a){var o=this;this.L=e,this.j=new Be(t),this.ea=n,this.C=!1,this.u=i,this.I=r,this.U=a,this.h=this.m=!1,this.W="",this.s=null,this.F=function(){return sl(o)},this.H=function(e,t){var n=qu(t);switch(n.type){case"event":var i=n.targetName;n=Qr(n.event),o.u(i,n);break;case"update":for(var r in i=n.update)for(var a in n=o.g[r]||{},i[r])n[a]=i[r][a];o.C&&(o.ea(),o.C=!1);break;case"asyncComplete":if(r=n.id,n=n.error,a=o.i[r],delete o.i[r],a)if(n){for(i in r=new le(n.severity,n.category,n.code),n)r[i]=n[i];a.reject(r)}else a.resolve()}},this.g={video:{},player:{}},this.O=0,this.i={},this.l=null,hl.add(this)}function il(e,t,n){fl=n,n.addUpdateListener(e.F),n.addMessageListener("urn:x-cast:com.google.shaka.v2",e.H),sl(e),ll(e,{type:"init",initState:t,appData:e.s}),e.l.resolve()}function rl(e,t){var n=8003;switch(t.code){case"cancel":n=8004;break;case"timeout":n=8005;break;case"receiver_unavailable":n=8006}e.l.reject(new le(2,8,n,t))}function al(e,t){var n=e.U();e.l=new ci,e.C=!0,il(e,n,t)}function ol(e){var t=fl;t.removeUpdateListener(e.F),t.removeMessageListener("urn:x-cast:com.google.shaka.v2",e.H)}function sl(e){var t=!!fl&&"connected"==fl.status;if(e.h&&!t){for(var n in e.I(),e.g)e.g[n]={};ul(e)}e.h=t,e.W=t?fl.receiver.friendlyName:"",e.j.hc()}function ul(e){for(var t in e.i){var n=e.i[t];delete e.i[t],n.reject(new le(1,7,7e3))}}function ll(e,t){var n=Gu(t),i=fl;try{i.sendMessage("urn:x-cast:com.google.shaka.v2",n,function(){},Y)}catch(t){throw n=new le(2,8,8005,t),i=new Jr("error",(new Map).set("detail",n)),e.u("player",i),e.wb(),n}}(i=nl.prototype).destroy=function(){return hl.delete(this),ul(this),fl&&ol(this),this.j&&(this.j.stop(),this.j=null),this.I=this.u=null,this.h=this.m=!1,this.H=this.F=this.l=this.i=this.g=this.s=null,Promise.resolve()},i.ua=function(){return this.h},i.Dd=function(){return this.W},i.init=function(){if(this.L.length)if(e.chrome&&chrome.cast&&chrome.cast.isAvailable){this.m=!0,this.j.hc();var t=new chrome.cast.SessionRequest(this.L);t=new chrome.cast.ApiConfig(t,function(e){for(var t=l(hl),n=t.next();!n.done;n=t.next())al(n.value,e)},function(e){for(var t=l(hl),n=t.next();!n.done;n=t.next())n=n.value,dl="available"==e,n.j.hc()},"origin_scoped"),chrome.cast.initialize(t,function(){},function(){}),dl&&this.j.V(cl),(t=fl)&&t.status!=chrome.cast.SessionStatus.STOPPED?al(this,t):fl=null}else e.__onGCastApiAvailable||(e.__onGCastApiAvailable=pl),e.__onGCastApiAvailable!=pl&&X("A global Cast SDK hook is already installed! Shaka Player will be unable to receive a notification when the Cast SDK is ready.")},i.Kd=function(e){this.s=e,this.h&&ll(this,{type:"appData",appData:this.s})},i.cast=function(e){var t=this;return P(function(n){if(!t.m)throw new le(1,8,8e3);if(!dl)throw new le(1,8,8001);if(t.h)throw new le(1,8,8002);return t.l=new ci,chrome.cast.requestSession(function(n){return il(t,e,n)},function(e){return rl(t,e)}),w(n,t.l,0)})},i.wb=function(){if(this.h){if(ul(this),fl){ol(this);try{fl.stop(function(){},function(){})}catch(e){}fl=null}sl(this)}},i.get=function(e,t){var n=this;if("video"==e){if(Yu.includes(t))return function(i){for(var r=[],a=0;an.byteLength){n=[];break e}var a=oe(n,e,r);t.push({type:i,value:a}),e+=r}n=t}return n}(e=tt(e.textContent)).filter(function(e){return e.type===lc})[0])&&(e=rc(e=he(e.value,!0),"WRMHEADER"))?function(e){for(var t=(e=l(e.getElementsByTagName("DATA"))).next();!t.done;t=e.next())for(var n=(t=l(t.value.childNodes)).next();!n.done;n=t.next())if((n=n.value)instanceof Element&&"LA_URL"==n.tagName)return n.textContent;return""}(e):""}function uc(e){var t=e.getAttribute("schemeIdUri"),n=ql(e,"urn:mpeg:cenc:2013","default_KID"),i=Gl(e,"urn:mpeg:cenc:2013","pssh").map(Xl);if(!t)return null;if(t=t.toLowerCase(),n&&(n=n.replace(/-/g,"").toLowerCase()).includes(" "))throw new le(2,4,4009);var r=[];try{r=i.map(function(e){return{initDataType:"cenc",initData:tt(e),keyId:null}})}catch(e){throw new le(2,4,4007)}return{node:e,oe:t,keyId:n,init:0(g=m||0))if(p){if(null==(p=Yl(p,"t",tc)))break;if(h>=p)break;g=Math.ceil((p-h)/f)-1}else{if(1/0==u)break;if(h/a>=u)break;g=Math.ceil((u*a-h)/f)-1}for(0>>31,h&=2147483647;var p=o.reader.N();if(o.reader.skip(4),1==d)throw new le(2,3,3006);s.push(new Ja(c/u+n,(c+p)/u+n,function(){return a},e,e+h-1,t,n,i,r)),c+=p,e+=h}return o.parser.stop(),s}(t,i,r,a,o,n,e)});if(e&&u.parse(e),s)return s;throw new le(2,3,3004)}function vc(e){this.h=se(e),this.g=new ye(this.h,0)}function yc(e){var t=bc(e);if(7s()&&!n.length?null:n})}return Promise.resolve(E)}(u,s,r,o,a)}};var c=null;i=null,e.ha.id&&e.K.id&&(i=e.ha.id+","+e.K.id,c=n[i]);var d=function(e,t,n){var i=e.X.start,r=e.X.duration,a=i-t.Xa;r=r?i+r:1/0;for(var o=[],s={},u=l(te(t.timeline)),c=u.next();!c.done;s={Vc:s.Vc,Yc:s.Yc,ad:s.ad,Sc:s.Sc,cd:s.cd,Tc:s.Tc},c=u.next()){var d=(c=c.value).item,f=d.start,h=d.Qf;d=d.end,s.ad=c.ga+t.Ib,s.cd=h+t.Sd,s.Yc=e.K.id,s.Sc=e.bandwidth||null,s.Vc=t.vd,s.Tc=e.K.Aa,o.push(new Ja(i+f,i+d,function(e){return function(){var t=dc(e.Vc,e.Yc,e.ad,e.Sc||null,e.cd);return ii(e.Tc,[t]).map(function(e){return e.toString()})}}(s),0,null,n,a,i,r))}return o}(u,s,o),f=e.X.start,h=e.X.duration?e.X.start+e.X.duration:1/0,p=1/0!=h;return c?(p&&new yo(d).ab(f,h,!0),c.Bb(d,e.presentationTimeline.Va())):(c=new yo(d),i&&e.fb&&(n[i]=c)),e.presentationTimeline.Db(d),p&&c.ab(f,h),{xb:function(){return Promise.resolve(c)}}}function Nc(e){return e.ec}function Pc(){this.l=[],this.g=[],this.h=[],this.j=[],this.i=[],this.m=new Set}function Lc(e,t,n){var i,r,a,o,s,u,c,d,f,h,p,g,m,v,y,b,x,S,E,A,k,I,M,C,D,R,N,L,j,_,O;return P(function(P){switch(P.g){case 1:if(i=ui,function(e){for(var t=(e=l(e)).next();!t.done;t=e.next()){t=t.value;for(var n=[],i=l(t.uc),r=i.next();!r.done;r=i.next()){r=r.value;for(var a=!1,o=l(n),s=o.next();!s.done;s=o.next())s=s.value,r.id!=s.id&&r.channelsCount==s.channelsCount&&r.language==s.language&&r.bandwidth==s.bandwidth&&r.label==s.label&&r.codecs==s.codecs&&r.mimeType==s.mimeType&&ct(r.roles,s.roles)&&r.audioSamplingRate==s.audioSamplingRate&&r.primary==s.primary&&(a=!0);a||n.push(r)}t.uc=n}}(t),function(e){for(var t=(e=l(e)).next();!t.done;t=e.next()){t=t.value;for(var n=[],i=l(t.Qc),r=i.next();!r.done;r=i.next()){r=r.value;for(var a=!1,o=l(n),s=o.next();!s.done;s=o.next())s=s.value,r.id!=s.id&&r.width==s.width&&r.frameRate==s.frameRate&&r.codecs==s.codecs&&r.mimeType==s.mimeType&&r.label==s.label&&ct(r.roles,s.roles)&&va(r.closedCaptions,s.closedCaptions)&&r.bandwidth==s.bandwidth&&(a=!0);a||n.push(r)}t.Qc=n}}(t),function(e){for(var t=(e=l(e)).next();!t.done;t=e.next()){t=t.value;for(var n=[],i=l(t.textStreams),r=i.next();!r.done;r=i.next()){r=r.value;for(var a=!1,o=l(n),s=o.next();!s.done;s=o.next())s=s.value,r.id!=s.id&&r.language==s.language&&r.label==s.label&&r.codecs==s.codecs&&r.mimeType==s.mimeType&&ct(r.roles,s.roles)&&(a=!0);a||n.push(r)}t.textStreams=n}}(t),function(e){for(var t=(e=l(e)).next();!t.done;t=e.next()){t=t.value;for(var n=[],i=l(t.imageStreams),r=i.next();!r.done;r=i.next()){r=r.value;for(var a=!1,o=l(n),s=o.next();!s.done;s=o.next())s=s.value,r.id!=s.id&&r.width==s.width&&r.codecs==s.codecs&&r.mimeType==s.mimeType&&(a=!0);a||n.push(r)}t.imageStreams=n}}(t),!n&&1==t.length){r=t[0],e.g=r.uc,e.h=r.Qc,e.j=r.textStreams,e.i=r.imageStreams,P.v(2);break}for(a=-1,o=l(te(t)),s=o.next();!s.done;s=o.next())u=s.value,c=u.ga,d=u.item,e.m.has(d.id)||(e.m.add(d.id),-1==a&&(a=c));if(-1==a)return P.return();for(f=t.map(function(e){return e.uc}),h=t.map(function(e){return e.Qc}),p=t.map(function(e){return e.textStreams}),g=t.map(function(e){return e.imageStreams}),m=l(p),v=m.next();!v.done;v=m.next())v.value.push(Qc(i.ba));for(y=l(g),b=y.next();!b.done;b=y.next())b.value.push(Qc(i.pc));return w(P,_c(e.g,f,a,Fc,Vc),3);case 3:return w(P,_c(e.h,h,a,Fc,Vc),4);case 4:return w(P,_c(e.j,p,a,Fc,Vc),5);case 5:return w(P,_c(e.i,g,a,Fc,Vc),2);case 2:if(x=0,S=[],e.h.length&&e.g.length)for(C=l(e.g),D=C.next();!D.done;D=C.next())for(R=D.value,N=l(e.h),L=N.next();!L.done;L=N.next())j=L.value,_=ja(R.drmInfos,j.drmInfos),R.drmInfos.length&&j.drmInfos.length&&!_.length||(O=x++,S.push({id:O,language:R.language,primary:R.primary,audio:R,video:j,bandwidth:(R.bandwidth||0)+(j.bandwidth||0),drmInfos:_,allowedByApplication:!0,allowedByKeySystem:!0,decodingInfos:[]}));else for(E=e.h.concat(e.g),A=l(E),k=A.next();!k.done;k=A.next())I=k.value,M=x++,S.push({id:M,language:I.language,primary:I.primary,audio:I.type==i.eb?I:null,video:I.type==i.Ra?I:null,bandwidth:I.bandwidth||0,drmInfos:I.drmInfos,allowedByApplication:!0,allowedByKeySystem:!0,decodingInfos:[]});e.l=S,T(P)}})}function jc(e){var t,n,i,r,a,o,s,u,c,d,f,h,p,g,m,v,y,b,T,x,S,E,A,k;return P(function(I){switch(I.g){case 1:if(t=ui,1==e.length)return I.return(e[0]);for(n=e.map(function(e){return e.filter(function(e){return e.type==t.eb})}),i=e.map(function(e){return e.filter(function(e){return e.type==t.Ra})}),r=e.map(function(e){return e.filter(function(e){return e.type==t.ba})}),a=e.map(function(e){return e.filter(function(e){return e.type==t.pc})}),o=l(r),s=o.next();!s.done;s=o.next())s.value.push(Jc(t.ba));for(u=l(a),c=u.next();!c.done;c=u.next())c.value.push(Jc(t.pc));return w(I,_c([],n,0,Bc,Hc),2);case 2:return d=I.h,w(I,_c([],i,0,Bc,Hc),3);case 3:return f=I.h,w(I,_c([],r,0,Bc,Hc),4);case 4:return h=I.h,w(I,_c([],a,0,Bc,Hc),5);case 5:if(p=I.h,g=0,f.length&&d.length)for(b=l(d),T=b.next();!T.done;T=b.next())for(x=T.value,S=l(f),E=S.next();!E.done;E=S.next())A=E.value,k=g++,A.variantIds.push(k),x.variantIds.push(k);else for(m=f.concat(d),v=l(m),y=v.next();!y.done;y=v.next())y.value.variantIds=[g++];return I.return(f.concat(d).concat(h).concat(p))}})}function _c(e,t,n,i,r){var a,o,s,u,c,d,f,h,p,g,m,v,y,b,T,x,S,E,A,k,I;return P(function(M){switch(M.g){case 1:for(a=ui,o=[],s=l(te(t)),u=s.next();!u.done;u=s.next())c=u.value,d=c.ga,f=c.item,d>=n?o.push(new Set(f)):o.push(new Set);h=l(e),p=h.next();case 2:if(p.done){M.v(4);break}return w(M,function(e,t,n,i,r){var a;return P(function(o){return 1==o.g?(a=Kc(t,e))?w(o,Oc(a),2):o.return(!1):(Uc(e,a,n,i,r),o.return(!0))})}(p.value,t,n,r,o),5);case 5:if(!M.h)throw new le(2,4,4037);p=h.next(),M.v(2);break;case 4:g=l(o),m=g.next();case 6:if(m.done){M.v(8);break}v=m.value,y=l(v),b=y.next();case 9:if(b.done){m=g.next(),M.v(6);break}return w(M,function(e,t,n,i,r){var a,o;return P(function(s){return 1==s.g?(a=n(e),(o=Kc(t,a))?a.createSegmentIndex?w(s,Oc(o),2):s.v(2):s.return(null)):(Uc(a,o,0,i,r),s.return(a))})}(b.value,t,i,r,o),12);case 12:(T=M.h)&&e.push(T),b=y.next(),M.v(9);break;case 8:for(x=l(o),m=x.next();!m.done;m=x.next())for(S=m.value,E={},A=l(S),b=A.next();!b.done;E={Za:E.Za},b=A.next())if(E.Za=b.value,k=E.Za.type==a.ba&&!E.Za.language,I=E.Za.type==a.pc&&!E.Za.tilesLayout,!k&&!I&&e.some(function(e){return function(t){return t.mimeType==e.Za.mimeType&&wi(t.codecs)==wi(e.Za.codecs)}}(E)))throw new le(2,4,4037);return M.return(e)}})}function Oc(e){for(var t=[],n=(e=l(e)).next();!n.done;n=e.next())n=n.value,t.push(n.createSegmentIndex()),n.trickModeVideo&&!n.trickModeVideo.segmentIndex&&t.push(n.trickModeVideo.createSegmentIndex());return Promise.all(t)}function Uc(e,t,n,i,r){for(var a=(t=l(te(t))).next();!a.done;a=t.next()){var o=a.value;if(a=o.ga,o=o.item,a>=n){i(e,o);var s=!0;"audio"==e.type&&0==tr(e.language,o.language)&&(s=!1),s&&r[a].delete(o)}}}function Fc(e){return(e=Object.assign({},e)).originalId=null,e.createSegmentIndex=function(){return Promise.resolve()},e.segmentIndex=new To,e.emsgSchemeIdUris=[],e.keyIds=new Set,e.closedCaptions=null,e.trickModeVideo=null,e}function Bc(e){return(e=Object.assign({},e)).keyIds=new Set,e.segments=[],e.variantIds=[],e.closedCaptions=null,e}function Vc(e,t){e.roles=Array.from(new Set(e.roles.concat(t.roles))),t.emsgSchemeIdUris&&(e.emsgSchemeIdUris=Array.from(new Set(e.emsgSchemeIdUris.concat(t.emsgSchemeIdUris))));var n=t.keyIds;if(n=new Set([].concat(c(e.keyIds),c(n))),e.keyIds=n,null==e.originalId?e.originalId=t.originalId:e.originalId+=","+(t.originalId||""),n=ja(e.drmInfos,t.drmInfos),t.drmInfos.length&&e.drmInfos.length&&!n.length)throw new le(2,4,4038);if(e.drmInfos=n,e.encrypted=e.encrypted||t.encrypted,t.closedCaptions){e.closedCaptions||(e.closedCaptions=new Map);for(var i=(n=l(t.closedCaptions)).next();!i.done;i=n.next()){var r=l(i.value);i=r.next().value,r=r.next().value,e.closedCaptions.set(i,r)}}e.segmentIndex.j.push(t.segmentIndex),t.trickModeVideo?(e.trickModeVideo||(e.trickModeVideo=Fc(t.trickModeVideo),e.trickModeVideo.segmentIndex=e.segmentIndex.clone()),Vc(e.trickModeVideo,t.trickModeVideo)):e.trickModeVideo&&Vc(e.trickModeVideo,t)}function Hc(e,t){e.roles=Array.from(new Set(e.roles.concat(t.roles)));var n=t.keyIds;if(n=new Set([].concat(c(e.keyIds),c(n))),e.keyIds=n,e.encrypted=e.encrypted&&t.encrypted,e.segments.push.apply(e.segments,c(t.segments)),t.closedCaptions){e.closedCaptions||(e.closedCaptions=new Map);for(var i=(n=l(t.closedCaptions)).next();!i.done;i=n.next()){var r=l(i.value);i=r.next().value,r=r.next().value,e.closedCaptions.set(i,r)}}}function Kc(e,t){for(var n=[],i=l(e),r=i.next();!r.done;r=i.next()){for(var a=t,o={audio:Gc,video:Gc,text:qc,image:zc}[a.type],s={audio:Xc,video:Wc,text:Yc,image:$c}[a.type],u=null,c=(r=l(r.value)).next();!c.done;c=r.next())!o(a,c=c.value)||u&&!s(a,u,c)||(u=c);if(!(a=u))return null;n.push(a)}return n}function Gc(e,t){var n;if(!(n=t.mimeType!=e.mimeType||wi(t.codecs)!=wi(e.codecs))&&(n=e.drmInfos)){n=e.drmInfos;var i=t.drmInfos;n=!(!n.length||!i.length||0i||!(ri.length||!(r.lengthi)return!0;if(ri.length)return!0;if(r.lengthe){if(n<=e||n-et-e)return id}else{if(n>e)return id;if(e-ne-t)return id}return nd}function ed(e,t,n){return t=Math.abs(e-t),(e=Math.abs(e-n))e.j)&&(e.j=c),o=sd(e,t,n,{start:c,duration:g,node:d,ee:null==g||!f}),a.push(o),t.ha.id&&g&&(e.L[t.ha.id]=g),null==g){o=null;break}o=c+g}}return e.I=a.map(function(e){return e.id}),null!=r?{periods:a,duration:r,Yd:!1}:{periods:a,duration:o,Yd:!0}}(e,D,u,t),N=R.duration,L=R.periods,"static"!=b&&R.Yd||S.Ma(N||1/0),e.l&&!e.s&&e.D.isAutoLowLatencyMode()&&(e.D.enableLowLatencyMode(),e.s=e.D.isLowLatencyMode()),e.s?S.re(e.l):e.l&&X("Low-latency DASH live stream detected, but low-latency streaming mode is not enabled in Shaka Player. Set streaming.lowLatencyMode configuration to true, and see https://bit.ly/3clctcj for details."),S.wd(y||1),w(O,Lc(e.g,L,D.fb),2);case 2:if(e.B){e.B.variants=e.g.l,e.B.textStreams=e.g.j.slice(),e.B.imageStreams=e.g.i,e.D.filter(e.B),O.v(3);break}if(e.B={presentationTimeline:S,variants:e.g.l,textStreams:e.g.j.slice(),imageStreams:e.g.i,offlineSessionIds:[],minBufferTime:f||0},!S.we()){O.v(3);break}return j=Kl(t,"UTCTiming"),w(O,function(e,t,n){var i,r,a,o,s,u,c,d;return P(function(f){switch(f.g){case 1:i=n.map(function(e){return{scheme:e.getAttribute("schemeIdUri"),value:e.getAttribute("value")}}),r=e.o.dash.clockSyncUri,!i.length&&r&&i.push({scheme:"urn:mpeg:dash:utc:http-head:2014",value:r}),a=l(i),o=a.next();case 2:if(o.done){f.v(4);break}switch(s=o.value,x(f,5),u=s.scheme,c=s.value,u){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":return f.v(7);case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":return f.v(8);case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":return d=Date.parse(c),f.return(isNaN(d)?0:d-Date.now());case"urn:mpeg:dash:utc:http-ntp:2014":case"urn:mpeg:dash:utc:ntp:2014":case"urn:mpeg:dash:utc:sntp:2014":X("NTP UTCTiming scheme is not supported");break;default:X("Unrecognized scheme in UTCTiming element",u)}f.v(9);break;case 7:return w(f,dd(e,t,c,"HEAD"),10);case 10:return f.return(f.h);case 8:return w(f,dd(e,t,c,"GET"),11);case 11:return f.return(f.h);case 9:E(f,3);break;case 5:A(f);case 3:o=a.next(),f.v(2);break;case 4:return X("A UTCTiming element should always be given in live manifests! This content may not play on clients with bad clocks!"),f.return(0)}})}(e,u,j),5);case 5:if(_=O.h,!e.D)return O.return();S.se(_);case 3:e.D.makeTextStreamsForClosedCaptions(e.B),T(O)}})}function sd(e,t,n,i){t.ha=cd(i.node,null,n),t.X=i,t.ha.vb=t.vb,t.ha.id||(t.ha.id="__shaka_period_"+i.start);var r=Kl(i.node,"EventStream");n=t.presentationTimeline.Va();for(var a=(r=l(r)).next();!a.done;a=r.next())fd(e,i.start,i.duration,a.value,n);if(n=Kl(i.node,"AdaptationSet").map(function(n){return function(e,t,n){function i(e){switch(e){case 1:case 6:case 13:case 14:case 15:return"SDR";case 16:return"PQ";case 18:return"HLG"}}t.ma=cd(n,t.ha,null);var r,a=!1,o=Kl(n,"Role"),s=o.map(function(e){return e.getAttribute("value")}).filter(Me),u=void 0,d=t.ma.contentType==si;d&&(u="subtitle");for(var f=(o=l(o)).next();!f.done;f=o.next()){var h=(f=f.value).getAttribute("schemeIdUri");if(null==h||"urn:mpeg:dash:role:2011"==h)switch(f=f.getAttribute("value"),f){case"main":a=!0;break;case"caption":case"subtitle":u=f}}h=Kl(n,"EssentialProperty"),o=null,f=!1;for(var p=(h=l(h)).next();!p.done;p=h.next()){var g=(p=p.value).getAttribute("schemeIdUri");"http://dashif.org/guidelines/trickmode"==g?o=p.getAttribute("value"):"urn:mpeg:mpegB:cicp:TransferCharacteristics"==g?r=i(parseInt(p.getAttribute("value"),10)):f=!0}for(h=l(h=Kl(n,"SupplementalProperty")),p=h.next();!p.done;p=h.next())"urn:mpeg:mpegB:cicp:TransferCharacteristics"==(p=p.value).getAttribute("schemeIdUri")&&(r=i(parseInt(p.getAttribute("value"),10)));h=Kl(n,"Accessibility");var m=new Map;for(h=l(h),p=h.next();!p.done;p=h.next())if(g=p.value,p=g.getAttribute("schemeIdUri"),g=g.getAttribute("value"),"urn:scte:dash:cc:cea-608:2015"==p)if(p=1,null!=g)for(var v=l(g=g.split(";")),y=v.next();!y.done;y=v.next()){var b=y.value,x=y=void 0;b.includes("=")?(b=b.split("="),y=b[0].startsWith("CC")?b[0]:"CC"+b[0],x=b[1]||"und"):(y="CC"+p,2==g.length?p+=2:p++,x=b),m.set(y,er(x))}else m.set("CC1","und");else if("urn:scte:dash:cc:cea-708:2015"==p)if(p=1,null!=g)for(g=l(g.split(";")),y=g.next();!y.done;y=g.next())y=y.value,b=v=void 0,y.includes("=")?(y=y.split("="),v="svc"+y[0],b=y[1].split(",")[0].split(":").pop()):(v="svc"+p,p++,b=y),m.set(v,er(b));else m.set("svc1","und");else"urn:mpeg:dash:role:2011"==p&&null!=g&&(s.push(g),"captions"==g&&(u="caption"));if(f)return null;var S=oc(f=Kl(n,"ContentProtection"),e.o.dash.ignoreDrmInfo,e.o.dash.keySystemsByURI),E=er(n.getAttribute("lang")||"und"),A=n.getAttribute("label");if((f=Kl(n,"Label"))&&f.length&&(f=f[0]).textContent&&(A=f.textContent),f=Kl(n,"Representation"),0==(n=f.map(function(n){return(n=function(e,t,n,i,r,a,o,s,u,l){if(t.K=cd(l,t.ma,null),e.l=Math.min(e.l,t.K.vb),!function(e){var t=e.dc?1:0;return t+=e.cb?1:0,0==(t+=e.ec?1:0)?e.contentType==si||"application"==e.contentType:(1!=t&&(e.dc&&(e.cb=null),e.ec=null),!0)}(t.K))return null;var c=t.X.start;t.bandwidth=Yl(l,"bandwidth",ec)||0;var d=t.K.contentType,f=d==si||"application"==d;d="image"==d;try{var h=function(t,n,i){return function(e,t,n,i){var r,a,o,s,u;return P(function(l){return 1==l.g?(r=la,a=No(t,n,i,e.o.retryParameters),o=e.D.networkingEngine,s=o.request(r,a),ia(e.i,s),w(l,s.promise,2)):(u=l.h,l.return(u.data))})}(e,t,n,i)};if(t.K.dc)var p=Ec(t,h);else if(t.K.cb)p=Cc(t,e.m);else if(t.K.ec)p=Rc(t,h,e.m,!!e.B,e.o.dash.initialSegmentLimit,e.L);else{var g=t.K.Aa,m=t.X.duration||0;p={xb:function(){return Promise.resolve(bo(c,m,g))}}}}catch(e){if((f||d)&&4002==e.code)return null;throw e}h=function(e,t,n,i){var r=oc(e,n,i);if(t.$d)e=1==t.drmInfos.length&&!t.drmInfos[0].keySystem,n=0==r.drmInfos.length,(0==t.drmInfos.length||e&&!n)&&(t.drmInfos=r.drmInfos),t.$d=!1;else if(0e.C||e.u.V(Math.max(3,e.C-t,K(e.H)))}function cd(e,t,n){t=t||{contentType:"",mimeType:"",codecs:"",emsgSchemeIdUris:[],frameRate:void 0,pixelAspectRatio:void 0,yd:null,audioSamplingRate:null,vb:0},n=n||t.Aa;for(var i=Kl(e,"BaseURL"),r=i.map(Xl),a=e.getAttribute("contentType")||t.contentType,o=e.getAttribute("mimeType")||t.mimeType,s=e.getAttribute("codecs")||t.codecs,u=Yl(e,"frameRate",ic)||t.frameRate,c=e.getAttribute("sar")||t.pixelAspectRatio,d=Kl(e,"InbandEventStream"),f=t.emsgSchemeIdUris.slice(),h=(d=l(d)).next();!h.done;h=d.next())h=h.value.getAttribute("schemeIdUri"),f.includes(h)||f.push(h);d=function(e){for(var t=(e=l(e)).next();!t.done;t=e.next()){var n=t.value;if((t=n.getAttribute("schemeIdUri"))&&(n=n.getAttribute("value")))switch(t){case"urn:mpeg:dash:outputChannelPositionList:2012":return n.trim().split(/ +/).length;case"urn:mpeg:dash:23003:3:audio_channel_configuration:2011":case"urn:dts:dash:audio_channel_configuration:2012":if(!(t=parseInt(n,10)))continue;return t;case"tag:dolby.com,2014:dash:audio_channel_configuration:2011":case"urn:dolby:dash:audio_channel_configuration:2011":if(!(t=parseInt(n,16)))continue;for(e=0;t;)1&t&&++e,t>>=1;return e;case"urn:mpeg:mpegB:cicp:ChannelConfiguration":if(t=[0,1,2,3,4,5,6,8,2,3,4,7,8,24,8,12,10,12,14,12,14],(n=parseInt(n,10))&&0n.length||"data"!=n[0])throw new le(2,1,1004,t);if(2>(n=n.slice(1).join(":").split(",")).length)throw new le(2,1,1004,t);var i=n[0];t=e.decodeURIComponent(n.slice(1).join(",")),i=(n=i.split(";"))[0];var r=!1;return 1>4)&&2!=u||r(),3==u&&(u=a.aa(),a.skip(u)),1==a.N()>>8){a.skip(3),0!=(n=a.aa()>>6)&&1!=n||r(),0==a.aa()&&r(),n=a.aa(),u=a.Gb();var l=a.Gb();return(1073741824*((14&n)>>1)+((65534&u)<<14|(65534&l)>>1))/9e4}i()}else i()}}(t,g.uri,g.data));case 4:throw new le(2,4,4030,t)}})}function Yd(e,t){var n=String(e).replace(/%7B/g,"{").replace(/%7D/g,"}"),i=n.match(/{\$\w*}/g);if(i)for(var r=(i=l(i)).next();!r.done;r=i.next()){var a=(r=r.value).slice(2,r.length-1),o=t.get(a);if(!o)throw new le(2,4,4039,a);n=n.replace(r,o)}return n}function $d(e,t){e.j=t,e.g&&e.g.fc(e.j==tf),e.j!=tf||e.s.stop()}function Jd(e,t,n){if(!e.C)throw new le(2,7,7001);return t=e.D.networkingEngine.request(n,t),ia(e.C,t),t.promise}B("shaka.net.DataUriPlugin",Nd),Nd.parse=Pd,aa("data",Pd),(i=jd.prototype).configure=function(e){this.o=e},i.start=function(e,t){var n,i,r=this;return P(function(a){return 1==a.g?(r.D=t,r.i=t.isLowLatencyMode(),w(a,Jd(r,oa([e],r.o.retryParameters),0),2)):3!=a.g?(n=a.h,r.L=n.uri,w(a,function(e,t){var n,i,r,a,o,s,u,c,d,f,h,p,g,m,v,y,b,S,E,k,I,M,C,D,R,N,L,j,_,O,U,F,B,V;return P(function(H){switch(H.g){case 1:if(0!=(n=Md(e.ea,t,e.L)).type)throw new le(2,4,4022);for(i=wd(n.Y,"EXT-X-DEFINE"),function(e,t){for(var n=l(t),i=n.next();!i.done;i=n.next()){var r=i.value;i=md(r,"NAME"),r=md(r,"VALUE"),i&&r&&(e.u.has(i)||e.u.set(i,r))}}(e,i),r=wd(n.Y,"EXT-X-MEDIA"),a=wd(n.Y,"EXT-X-STREAM-INF"),function(e,t){for(var n=l(t),i=n.next();!i.done;i=n.next()){var r=i.value,a=md(r,"AUDIO");i=md(r,"VIDEO");var o=md(r,"SUBTITLES");if(r=Ud(e,r),o){var s=oi(si,r);e.l.set(o,s),lt(r,s)}a&&(o=ai("audio",r),e.l.set(a,o)),i&&(a=ai("video",r),e.l.set(i,a))}}(e,a),o=wd(n.Y,"EXT-X-SESSION-DATA"),s=l(o),u=s.next();!u.done;u=s.next())c=u.value,d=md(c,"DATA-ID"),f=md(c,"URI"),h=md(c,"LANGUAGE"),p=md(c,"VALUE"),g=(new Map).set("id",d),f&&g.set("uri",ii([e.L],[f])[0]),h&&g.set("language",h),p&&g.set("value",p),m=new Jr("sessiondata",g),e.D&&e.D.onEvent(m);return w(H,function(e,t){var n;return P(function(i){return 1==i.g?(t=t.filter(function(e){var t=md(e,"URI")||"";return"SUBTITLES"!=md(e,"TYPE")&&""!=t})).length?w(i,Bd(e,t[0]),2):i.v(2):(n=t.slice(1).map(function(t){return Bd(e,t)}),w(i,Promise.all(n),0))})}(e,r),2);case 2:return function(e,t){for(var n=Td(t,"CLOSED-CAPTIONS"),i=(n=l(n)).next();!i.done;i=n.next()){var r=i.value;i=Fd(r);var a=vd(r,"GROUP-ID");r=vd(r,"INSTREAM-ID"),e.I.get(a)||e.I.set(a,new Map),e.I.get(a).set(r,i)}}(e,r),w(H,function(e,t){var n,i,r;return P(function(a){return 1==a.g?(n=t.map(function(t){var n,i,r,a,o,s,u,c;return P(function(d){if(1==d.g)return n=md(t,"FRAME-RATE"),i=Number(md(t,"AVERAGE-BANDWIDTH"))||Number(vd(t,"BANDWIDTH")),r=md(t,"RESOLUTION"),a=l(r?r.split("x"):[null,null]),o=a.next().value,s=a.next().value,u=md(t,"VIDEO-RANGE"),w(d,function(e,t){var n,i,r,a,o,s,u,c,d,f,h,p,g,m;return P(function(v){if(1==v.g)return n=ui,i=Ud(e,t),r=md(t,"AUDIO"),a=md(t,"VIDEO"),s=(o=r||a)&&e.m.has(o)?e.m.get(o):[],u={audio:r?s:[],video:a?s:[]},d=!1,f=vd(t,"URI"),h=u.audio.find(function(e){return e&&e.Pc==f}),p=oi(n.Ra,i),(g=oi(n.eb,i))&&!p?c=n.eb:!s.length&&g&&p?(c=n.Ra,i=[[p,g].join()]):u.audio.length&&h?(c=n.eb,d=!0):c=u.video.length?n.eb:n.Ra,d?v.v(2):w(v,function(e,t,n,i){var r,a,o,s;return P(function(u){if(1==u.g){if(r=Yd(vd(t,"URI"),e.u),e.h.has(r))return u.return(e.h.get(r));var l=md(t,"CLOSED-CAPTIONS");return a="video"==i&&l&&"NONE"!=l?e.I.get(l):null,o=ai(i,n),w(u,Vd(e,r,o,i,"und",!1,null,null,a,null,!1,!1),2)}return null==(s=u.h)?u.return(null):e.h.has(r)?u.return(e.h.get(r)):(e.h.set(r,s),u.return(s))})}(e,t,i,c),3);if(2!=v.g&&(m=v.h),m)u[m.stream.type]=[m];else if(null===m)return v.return(null);return function(e){for(var t=(e=l(e.audio.concat(e.video))).next();!t.done;t=e.next())if(t=t.value){var n=t.stream.codecs.split(",");n=n.filter(function(e){return"mp4a.40.34"!=e}),t.stream.codecs=n.join(",")}}(u),v.return(u)})}(e,t),2);if(c=d.h){for(var f=d.return,h=c.audio,p=c.video,g=l(p),m=g.next();!m.done;m=g.next())(m=m.value.stream)&&(m.width=Number(o)||void 0,m.height=Number(s)||void 0,m.frameRate=Number(n)||void 0,m.hdr=u||void 0);for(g=e.o.disableAudio,h.length&&!g||(h=[null]),g=e.o.disableVideo,p.length&&!g||(p=[null]),g=[],h=l(h),m=h.next();!m.done;m=h.next()){m=m.value;for(var v=l(p),y=v.next();!y.done;y=v.next()){var b=y.value;y=m?m.stream:null;var T=b?b.stream:null,x=m?m.stream.drmInfos:null,S=b?b.stream.drmInfos:null;b=(b?b.Pc:"")+" - "+(m?m.Pc:""),y&&T&&x.length&&S.length&&!(0=n&&202!=n)return{uri:r||i,je:i,data:t,headers:e,fromCache:!!e["x-shaka-from-cache"]};r=null;try{r=pe(t)}catch(e){}throw new le(401==n||403==n?2:1,1,1001,i,n,r,e,a)}function sf(){}function uf(e,t,n,i){var r=new hf;ga(t.headers).forEach(function(e,t){r.append(t,e)});var a=new df,o={Td:!1,ve:!1};if(e=new qr(e=function(e,t,n,i,r,a){var o,s,u,l,c,d,f,h,p,g,m,v;return P(function(y){switch(y.g){case 1:return o=cf,s=ff,d=c=0,f=Date.now(),x(y,2),w(y,o(e,n),4);case 4:return u=y.h,h=u.clone().body.getReader(),g=(p=u.headers.get("Content-Length"))?parseInt(p,10):0,new s({start:function(e){!function t(){var n,i;return P(function(o){switch(o.g){case 1:return x(o,2),w(o,h.read(),4);case 4:n=o.h,E(o,3);break;case 2:return A(o),o.return();case 3:if(n.done){o.v(5);break}if(c+=n.value.byteLength,!a){o.v(5);break}return w(o,a(n.value),5);case 5:(100<(i=Date.now())-f||n.done)&&(r(i-f,c-d,g-c),d=c,f=i),n.done?e.close():(e.enqueue(n.value),t()),T(o)}})}()}}),w(y,u.arrayBuffer(),5);case 5:l=y.h,E(y,3);break;case 2:if(m=A(y),i.Td)throw new le(1,1,7001,e,t);if(i.ve)throw new le(1,1,1003,e,t);throw new le(1,1,1002,e,m,t);case 3:return v={},u.headers.forEach(function(e,t){v[t.trim()]=e}),y.return(of(v,l,u.status,e,u.url,t))}})}(e,n,{body:t.body||void 0,headers:r,method:t.method,signal:a.signal,credentials:t.allowCrossSiteCredentials?"include":void 0},o,i,t.streamDataCallback),function(){return o.Td=!0,a.abort(),Promise.resolve()}),t=t.retryParameters.timeout){var s=new Be(function(){o.ve=!0,a.abort()});s.V(t/1e3),e.finally(function(){s.stop()})}return e}function lf(){if(!e.ReadableStream)return!1;try{new ReadableStream({})}catch(e){return!1}return!(!e.fetch||!e.AbortController)}Ya.m3u8=function(){return new jd},Wa["application/x-mpegurl"]=function(){return new jd},Wa["application/vnd.apple.mpegurl"]=function(){return new jd},B("shaka.net.HttpFetchPlugin",sf),sf.isSupported=lf,sf.parse=uf;var cf=e.fetch,df=e.AbortController,ff=e.ReadableStream,hf=e.Headers;function pf(){}function gf(e,t,n,i){var r=new mf,a=Date.now(),o=0;return new qr(new Promise(function(s,u){for(var c in r.open(t.method,e,!0),r.responseType="arraybuffer",r.timeout=t.retryParameters.timeout,r.withCredentials=t.allowCrossSiteCredentials,r.onabort=function(){u(new le(1,1,7001,e,n))},r.onload=function(t){for(var i=(t=t.target).getAllResponseHeaders().trim().split("\r\n"),r={},a=(i=l(i)).next();!a.done;a=i.next())r[(a=a.value.split(": "))[0].toLowerCase()]=a.slice(1).join(": ");try{var o=of(r,t.response,t.status,e,t.responseURL,n);s(o)}catch(e){u(e)}},r.onerror=function(t){u(new le(1,1,1002,e,t,n))},r.ontimeout=function(){u(new le(1,1,1003,e,n))},r.onprogress=function(e){var t=Date.now();(100t,!s||!u){c.v(3);break}return w(c,r.updateManifestExpiration(n.key(),t),3);case 3:return k(c),w(c,i.destroy(),10);case 10:I(c,0);break;case 2:A(c),c.v(3)}})},Wa["application/x-offline-manifest"]=function(){return new Xf},B("shaka.offline.OfflineScheme",Wf),Wf.plugin=Yf,aa("offline",Yf),(i=th.prototype).destroy=function(){return this.J.destroy()},i.configure=function(e,t){return 2==arguments.length&&"string"==typeof e&&(e=us(e,t)),e.manifest&&e.manifest.dash&&"defaultPresentationDelay"in e.manifest.dash&&(xe("manifest.dash.defaultPresentationDelay configuration","Please Use manifest.defaultPresentationDelay instead."),e.manifest.defaultPresentationDelay=e.manifest.dash.defaultPresentationDelay,delete e.manifest.dash.defaultPresentationDelay),ds(this.o,e)},i.getConfiguration=function(){var e=cs();return ds(e,this.o,cs()),e},i.Vb=function(){return this.P},i.store=function(e,t,n){var i=this,r=this.getConfiguration(),a=new yf(this.P);this.Cd.push(a);var o=new qr(t=function(e,t,n,i,r,a){var o,s,u,c,d,f,h,p,g,m;return P(function(v){switch(v.g){case 1:return oh(),s=o=null,u=new Rf,d=c=null,x(v,2,3),w(v,i(),5);case 5:return o=v.h,w(v,function(e,t,n,i){var r,a,o,s,u;return P(function(l){if(1==l.g)return r=null,a=e.P,o={networkingEngine:a,filter:function(){return Promise.resolve()},makeTextStreamsForClosedCaptions:function(){},onTimelineRegionAdded:function(){},onEvent:function(){},onError:function(e){r=e},isLowLatencyMode:function(){return!1},isAutoLowLatencyMode:function(){return!1},enableLowLatencyMode:function(){}},n.configure(i.manifest),ah(e),w(l,n.start(t,o),2);if(3!=l.g)return s=l.h,ah(e),u=uh(s),w(l,Promise.all(Z(u,function(e){return e.createSegmentIndex()})),3);if(ah(e),r)throw r;return l.return(s)})}(e,t,o,r),6);case 6:if(f=v.h,ah(e),!(!f.presentationTimeline.Z()&&!f.presentationTimeline.mb()))throw new le(2,9,9005,t);return w(v,function(e,t,n,i){var r;return P(function(a){switch(a.g){case 1:return(r=new ya({Cb:e.P,onError:n,Ic:function(){},onExpirationUpdated:function(){},onEvent:function(){}})).configure(i.drm),w(a,function(e,t,n,i){return e.qa=!0,e.C=[],e.F=n,wa(e,t,!!i)}(r,t.variants,i.offline.usePersistentLicense,i.useMediaCapabilities),2);case 2:return w(a,Ta(r),3);case 3:return w(a,xa(r),4);case 4:return a.return(r)}})}(e,f,function(e){d=d||e},r),7);case 7:if(s=v.h,ah(e),d)throw d;return w(v,e.yc(f,s,r),8);case 8:return w(v,u.init(),9);case 9:return ah(e),w(v,function(e){var t=null;if(e.g.forEach(function(e,n){e.getCells().forEach(function(e,i){e.hasFixedKeySpace()||t||(t={path:{Ka:n,na:i},na:e})})}),t)return t;throw new le(2,9,9013,"Could not find a cell that supports add-operations")}(u),10);case 10:return c=v.h,ah(e),w(v,function(e,t,n,i,r,a,o,s){var u,c,d,f,h,p,g,m,v,y;return P(function(b){switch(b.g){case 1:return u=function(e,t,n){return{offlineUri:null,originalManifestUri:e,duration:t.presentationTimeline.getDuration(),size:0,expiration:1/0,tracks:t=Zf(t),appMetadata:n}}(r,i,a),c=o.offline.progressCallback,function(e,t,n){e.ge=t,e.fe=n}(s,function(e,t){u.size=t,c(u,e)},function(e,t){h&&o.offline.usePersistentLicense&&p==t&&Sa(n,"cenc",e)}),d=i.variants.some(function(e){var t=e.audio&&e.audio.encrypted;return e.video&&e.video.encrypted||t}),f=i.variants.some(function(e){return(e.video?e.video.drmInfos:[]).concat(e.audio?e.audio.drmInfos:[]).some(function(e){return e.initData&&e.initData.length})}),p=null,(h=d&&!f)&&(g=n.i,p=lh.get(g.keySystem)),S(b),v=m=function(e,t,n,i,r,a,o,s){for(var u=new function(){this.g={}},c=l(r.variants),d=c.next();!d.done;d=c.next()){var f=u,h=(d=d.value).audio,p=d.video;if(h&&!p&&(f.g[h.id]=h.bandwidth||d.bandwidth),!h&&p&&(f.g[p.id]=p.bandwidth||d.bandwidth),h&&p){var g=h.bandwidth||393216,m=p.bandwidth||d.bandwidth-g;0>=m&&(m=d.bandwidth),f.g[h.id]=g,f.g[p.id]=m}}for(c=l(r.textStreams),f=c.next();!f.done;f=c.next())u.g[f.value.id]=52;for(c=l(r.imageStreams),f=c.next();!f.done;f=c.next())f=f.value,u.g[f.id]=f.bandwidth||2048;for((f=new Map).set(null,Promise.resolve(null)),d=new Map,h=uh(r),c=new Map,h=l(h),p=h.next();!p.done;p=h.next())p=p.value,g=rh(e,t,n,u,r,p,s,f,d),c.set(p.id,g);for(e=l(r.variants),d=e.next();!d.done;d=e.next())(t=d.value).audio&&c.get(t.audio.id).variantIds.push(t.id),t.video&&c.get(t.video.id).variantIds.push(t.id);return e=Array.from(c.values()),s=s.offline.usePersistentLicense,(t=i.i)&&s&&(t.initData=[]),{creationTime:Date.now(),originalManifestUri:a,duration:r.presentationTimeline.getDuration(),size:0,expiration:i.Ub(),streams:e,sessionIds:s?Ia(i):[],drmInfo:t,appMetadata:o}}(e,s,t,n,i,r,a,o),w(b,function(e){return P(function(t){return 1==t.g?w(t,Promise.all(e.g.values()),2):t.return(e.Pb.h)})}(s),4);case 4:if(v.size=b.h,m.expiration=n.Ub(),y=Ia(n),m.sessionIds=o.offline.usePersistentLicense?y:[],d&&o.offline.usePersistentLicense&&!y.length)throw new le(2,9,9007);return b.return(m);case 2:return k(b),w(b,s.destroy(),5);case 5:I(b,0)}})}(e,c.na,s,f,t,n,r,a),11);case 11:if(h=v.h,ah(e),d)throw d;return w(v,c.na.addManifests([h]),12);case 12:return p=v.h,ah(e),g=new Hf("manifest",c.path.Ka,c.path.na,p[0]),v.return(Qf(g,h));case 3:return k(v),e.Nc=[],w(v,u.destroy(),13);case 13:if(!o){v.v(14);break}return w(v,o.stop(),14);case 14:if(!s){v.v(16);break}return w(v,s.destroy(),16);case 16:I(v,0);break;case 2:if(m=A(v),!c){v.v(18);break}return w(v,c.na.removeSegments(e.Nc,function(){}),18);case 18:throw d||m}})}(this,e,t||{},function(){var t;return P(function(a){return 1==a.g?w(a,qa(e,i.P,r.manifest.retryParameters,n||null),2):(t=a.h,a.return(Ce(t)))})},r,a),function(){return bf(a)});return o.finally(function(){lt(i.Cd,a)}),o.then=function(e){return xe("shaka.offline.Storage.store.then","Storage operations now return a shaka.util.AbortableOperation, rather than a promise. Please update to conform to this new API; you can use the |chain| method instead."),o.promise.then(e)},function(e,t){var n=t.promise;return e.bc.push(n),t.finally(function(){lt(e.bc,n)})}(this,o)},i.ef=function(){return xe("shaka.offline.Storage.getStoreInProgress","Multiple concurrent downloads are now supported."),!1},i.yc=function(e,t,n){var i,r,a,o,s,u,c,d,f,h,p,g,m,v,y,b,S,k,I,M,C,D,R,N,L;return P(function(P){switch(P.g){case 1:if(i={width:1/0,height:1/0},function(e,t,n){e.variants=e.variants.filter(function(e){return sr(e,t,n)})}(e,n.restrictions,i),!n.useMediaCapabilities){dr(e),lr(e,t),P.v(2);break}return w(P,cr(e,n.offline.usePersistentLicense),2);case 2:for(r=[],a=n.preferredAudioChannelCount,ar(e,a),o=l(e.variants),s=o.next();!s.done;s=o.next())u=s.value,r.push(yr(u));for(c=l(e.textStreams),d=c.next();!d.done;d=c.next())f=d.value,r.push(br(f));for(h=l(e.imageStreams),p=h.next();!p.done;p=h.next())g=p.value,r.push(wr(g));return w(P,n.offline.trackSelectionCallback(r),4);case 4:for(m=P.h,v=e.presentationTimeline.getDuration(),y=0,b=l(m),S=b.next();!S.done;S=b.next())k=S.value,I=k.bandwidth*v/8,y+=I;return x(P,5),w(P,n.offline.downloadSizeCallback(y),7);case 7:if(!P.h)throw new le(2,9,9014);E(P,6);break;case 5:if((M=A(P))instanceof le)throw M;throw new le(2,9,9015);case 6:for(C=new Set,D=new Set,R=new Set,N=l(m),S=N.next();!S.done;S=N.next())"variant"==(L=S.value).type&&C.add(L.id),"text"==L.type&&D.add(L.id),"image"==L.type&&R.add(L.id);e.variants=e.variants.filter(function(e){return C.has(e.id)}),e.textStreams=e.textStreams.filter(function(e){return D.has(e.id)}),e.imageStreams=e.imageStreams.filter(function(e){return R.has(e.id)}),function(e){e.variants.map(function(e){return e.video});var t=new Set(e.variants.map(function(e){return e.audio}));e=e.textStreams;for(var n=l(t),i=n.next();!i.done;i=n.next())for(var r=(i=l(t)).next();!r.done;r=i.next());for(t=l(e),n=t.next();!n.done;n=t.next())for(n=l(e),i=n.next();!i.done;i=n.next());}(e),T(P)}})},i.remove=function(e){return sh(this,function(e,t){var n,i,r,a,o,s;return P(function(u){switch(u.g){case 1:if(oh(),null==(n=Kf(t))||"manifest"!=n.g)throw new le(2,9,9004,t);return i=n,r=new Rf,S(u),w(u,r.init(),4);case 4:return w(u,Nf(r,i.Ka(),i.na()),5);case 5:return a=u.h,w(u,a.getManifests([i.key()]),6);case 6:return o=u.h,s=o[0],w(u,Promise.all([function(e,t,n){return P(function(i){return w(i,function(e,t,n,i){var r,a,o;return P(function(s){return 1==s.g?i.drmInfo?(r=function(e){var t=Array.from(e.g.keys());if(!t.length)throw new le(2,9,9e3,"No supported storage mechanisms found");return e.g.get(t[0]).getEmeSessionCell()}(n),a=i.sessionIds.map(function(e){return{sessionId:e,keySystem:i.drmInfo.keySystem,licenseUri:i.drmInfo.licenseServerUri,serverCertificate:i.drmInfo.serverCertificate,audioCapabilities:ih(i,!1),videoCapabilities:ih(i,!0)}}),w(s,$f(t,e,a),2)):s.return():3!=s.g?(o=s.h,w(s,r.remove(o),3)):w(s,r.add(a.filter(function(e){return!o.includes(e.sessionId)})),0)})}(e.P,e.o.drm,n,t),0)})}(e,s,r),function(e,t,n){function i(){}var r=function(e){for(var t=[],n=(e=l(e.streams)).next();!n.done;n=e.next())for(var i=(n=l(n.value.segments)).next();!i.done;i=n.next())null!=(i=i.value).initSegmentKey&&t.push(i.initSegmentKey),t.push(i.dataKey);return t}(n);return Qf(t,n),Promise.all([e.removeSegments(r,i),e.removeManifests([t.key()],i)])}(a,i,s)]),2);case 2:return k(u),w(u,r.destroy(),8);case 8:I(u,0)}})}(this,e))},i.Bf=function(){return sh(this,(e=this,P(function(f){switch(f.g){case 1:return oh(),t=e.P,n=e.o.drm,i=new Rf,r=!1,S(f),w(f,i.init(),4);case 4:a=[],function(e,t){e.g.forEach(function(e){t(e.getEmeSessionCell())})}(i,function(e){return a.push(e)}),o=l(a),s=o.next();case 5:if(s.done){f.v(2);break}return u=s.value,w(f,u.getAll(),8);case 8:return c=f.h,w(f,$f(n,t,c),9);case 9:return d=f.h,w(f,u.remove(d),10);case 10:d.length!=c.length&&(r=!0),s=o.next(),f.v(5);break;case 2:return k(f),w(f,i.destroy(),11);case 11:I(f,3);break;case 3:return f.return(!r)}})));var e,t,n,i,r,a,o,s,u,c,d},i.list=function(){return sh(this,P(function(i){switch(i.g){case 1:return oh(),e=[],t=new Rf,S(i),w(i,t.init(),4);case 4:return n=Promise.resolve(),function(e,t){e.g.forEach(function(e,n){e.getCells().forEach(function(e,i){t({Ka:n,na:i},e)})})}(t,function(t,i){n=n.then(function(){return P(function(n){if(1==n.g)return w(n,i.getAllManifests(),2);n.h.forEach(function(n,i){var r=Qf(new Hf("manifest",t.Ka,t.na,i),n);e.push(r)}),T(n)})})}),w(i,n,2);case 2:return k(i),w(i,t.destroy(),6);case 6:I(i,3);break;case 3:return i.return(e)}}));var e,t,n},B("shaka.offline.Storage",th),th.deleteAll=function(){var e;return P(function(t){return 1==t.g?(e=new Rf,S(t),w(t,function(e){var t,n;return P(function(i){return 1==i.g?(t=Array.from(e.g.values()),(n=0=t?(kh(),function(){var e=SourceBuffer.prototype.remove;SourceBuffer.prototype.remove=function(t,n){return e.call(this,t,n-.001)}}()):kh()):(We("Tizen 2")||We("Tizen 3")||We("Tizen 4"))&&function(){var e=MediaSource.isTypeSupported;MediaSource.isTypeSupported=function(t){return"opus"!=wi(t)&&e(t)}}()),e.MediaSource&&MediaSource.isTypeSupported('video/webm; codecs="vp9"')&&!MediaSource.isTypeSupported('video/webm; codecs="vp09.00.10.08"')&&function(){var e=MediaSource.isTypeSupported;We("Web0S")||(MediaSource.isTypeSupported=function(t){var n=t.split(/ *; */),i=n.findIndex(function(e){return e.startsWith("codecs=")});if(0>i)return e(t);var r=n[i].replace("codecs=","").replace(/"/g,"").split(/\s*,\s*/),a=r.findIndex(function(e){return e.startsWith("vp09")});return 0<=a&&(r[a]="vp9",n[i]='codecs="'+r.join(",")+'"',t=n.join("; ")),e(t)})}()}function kh(){var e=MediaSource.prototype.addSourceBuffer;MediaSource.prototype.addSourceBuffer=function(t){for(var n=[],i=0;i=t.data.length)return e;e=[];for(var n={},i=(t=l(t.data)).next();!i.done;n={kc:n.kc},i=t.next())n.kc=i.value,e.some(function(e){return function(t){return ie(t,e.kc)}}(n))||e.push(n.kc);return rt.apply(Qe,c(e))}(e.initData)),this.dispatchEvent(t)}}function qh(e,t){this.keySystem=e;for(var n=!1,i=l(t),r=i.next();!r.done;r=i.next()){var a={audioCapabilities:[],videoCapabilities:[],persistentState:"optional",distinctiveIdentifier:"optional",initDataTypes:(r=r.value).initDataTypes,sessionTypes:["temporary"],label:r.label},o=!1;if(r.audioCapabilities)for(var s=l(r.audioCapabilities),u=s.next();!u.done;u=s.next())(u=u.value).contentType&&(o=!0,MSMediaKeys.isTypeSupported(this.keySystem,u.contentType.split(";")[0])&&(a.audioCapabilities.push(u),n=!0));if(r.videoCapabilities)for(u=(s=l(r.videoCapabilities)).next();!u.done;u=s.next())(u=u.value).contentType&&(o=!0,MSMediaKeys.isTypeSupported(this.keySystem,u.contentType.split(";")[0])&&(a.videoCapabilities.push(u),n=!0));if(o||(n=MSMediaKeys.isTypeSupported(this.keySystem,"video/mp4")),"required"==r.persistentState&&(n=!1),n)return void(this.g=a)}throw(n=Error("Unsupported keySystem")).name="NotSupportedError",n.code=DOMException.NOT_SUPPORTED_ERR,n}function zh(e){var t=this.mediaKeys;return t&&t!=e&&Wh(t,null),delete this.mediaKeys,(this.mediaKeys=e)?Wh(e,this):Promise.resolve()}function Xh(e){this.g=new MSMediaKeys(e),this.h=new Ni}function Wh(e,t){if(e.h.ob(),!t)return Promise.resolve();e.h.A(t,"msneedkey",Gh);try{return io(t,HTMLMediaElement.HAVE_METADATA,e.h,function(){t.msSetMediaKeys(e.g)}),Promise.resolve()}catch(e){return Promise.reject(e)}}function Yh(e){Zr.call(this),this.j=null,this.l=e,this.i=this.g=null,this.h=new Ni,this.sessionId="",this.expiration=NaN,this.closed=new ci,this.keyStatuses=new Jh}function $h(e,t){var n=e.keyStatuses;n.size=null==t?0:1,n.g=t,n=new Jr("keystatuseschange"),e.dispatchEvent(n)}function Jh(){this.size=0,this.g=void 0}function Qh(){}function Zh(){!e.HTMLVideoElement||navigator.requestMediaKeySystemAccess&&MediaKeySystemAccess.prototype.getConfiguration||(navigator.requestMediaKeySystemAccess=ep,delete HTMLMediaElement.prototype.mediaKeys,HTMLMediaElement.prototype.mediaKeys=null,HTMLMediaElement.prototype.setMediaKeys=tp,e.MediaKeys=np,e.MediaKeySystemAccess=ip)}function ep(){return Promise.reject(Error("The key system specified is not supported."))}function tp(e){return null==e?Promise.resolve():Promise.reject(Error("MediaKeys not supported."))}function np(){throw new TypeError("Illegal constructor.")}function ip(){throw this.keySystem="",new TypeError("Illegal constructor.")}function rp(){}function ap(){if(!(!e.HTMLVideoElement||navigator.requestMediaKeySystemAccess&&MediaKeySystemAccess.prototype.getConfiguration)){if(HTMLMediaElement.prototype.webkitGenerateKeyRequest)vp="webkit";else if(!HTMLMediaElement.prototype.generateKeyRequest)return;navigator.requestMediaKeySystemAccess=sp,delete HTMLMediaElement.prototype.mediaKeys,HTMLMediaElement.prototype.mediaKeys=null,HTMLMediaElement.prototype.setMediaKeys=up,e.MediaKeys=cp,e.MediaKeySystemAccess=lp}}function op(e){return vp?vp+e.charAt(0).toUpperCase()+e.slice(1):e}function sp(e,t){try{var n=new lp(e,t);return Promise.resolve(n)}catch(e){return Promise.reject(e)}}function up(e){var t=this.mediaKeys;return t&&t!=e&&dp(t,null),delete this.mediaKeys,(this.mediaKeys=e)&&dp(e,this),Promise.resolve()}function lp(e,t){this.g=this.keySystem=e;var n=!1;"org.w3.clearkey"==e&&(this.g="webkit-org.w3.clearkey",n=!1);var i=!1,r=document.getElementsByTagName("video");r=r.length?r[0]:document.createElement("video");for(var a=l(t),o=a.next();!o.done;o=a.next()){var s={audioCapabilities:[],videoCapabilities:[],persistentState:"optional",distinctiveIdentifier:"optional",initDataTypes:(o=o.value).initDataTypes,sessionTypes:["temporary"],label:o.label},u=!1;if(o.audioCapabilities)for(var c=l(o.audioCapabilities),d=c.next();!d.done;d=c.next())(d=d.value).contentType&&(u=!0,r.canPlayType(d.contentType.split(";")[0],this.g)&&(s.audioCapabilities.push(d),i=!0));if(o.videoCapabilities)for(d=(c=l(o.videoCapabilities)).next();!d.done;d=c.next())(d=d.value).contentType&&(u=!0,r.canPlayType(d.contentType,this.g)&&(s.videoCapabilities.push(d),i=!0));if(u||(i=r.canPlayType("video/mp4",this.g)||r.canPlayType("video/webm",this.g)),"required"==o.persistentState&&(n?(s.persistentState="required",s.sessionTypes=["persistent-license"]):i=!1),i)return void(this.h=s)}throw n="Unsupported keySystem","org.w3.clearkey"!=e&&"com.widevine.alpha"!=e||(n="None of the requested configurations were supported."),(n=Error(n)).name="NotSupportedError",n.code=DOMException.NOT_SUPPORTED_ERR,n}function cp(e){this.l=e,this.g=null,this.h=new Ni,this.i=[],this.j=new Map}function dp(e,t){e.g=t,e.h.ob();var n=vp;t&&(e.h.A(t,n+"needkey",function(t){var n=new CustomEvent("encrypted");n.initDataType="cenc",n.initData=ae(t.initData),e.g.dispatchEvent(n)}),e.h.A(t,n+"keymessage",function(t){var n=fp(e,t.sessionId);n&&(t=new Jr("message",t=(new Map).set("messageType",null==n.keyStatuses.g?"licenserequest":"licenserenewal").set("message",t.message)),n.h&&(n.h.resolve(),n.h=null),n.dispatchEvent(t))}),e.h.A(t,n+"keyadded",function(t){(t=fp(e,t.sessionId))&&(gp(t,"usable"),t.g&&t.g.resolve(),t.g=null)}),e.h.A(t,n+"keyerror",function(t){var n=fp(e,t.sessionId);n&&n.handleError(t)}))}function fp(e,t){var n=e.j.get(t);return n||((n=e.i.shift())?(n.sessionId=t,e.j.set(t,n),n):null)}function hp(e,t,n){Zr.call(this),this.j=e,this.m=!1,this.g=this.h=null,this.i=t,this.l=n,this.sessionId="",this.expiration=NaN,this.closed=new ci,this.keyStatuses=new mp}function pp(e,t,n){if(e.m)return Promise.reject(Error("The session is already initialized."));e.m=!0;try{if("persistent-license"==e.l)if(n)var i=oe(ge("LOAD_SESSION|"+n));else{var r=ge("PERSISTENT|");i=rt(r,t)}else i=oe(t)}catch(e){return Promise.reject(e)}e.h=new ci;var a=op("generateKeyRequest");try{e.j[a](e.i,i)}catch(t){if("InvalidStateError"!=t.name)return e.h=null,Promise.reject(t);new Be(function(){try{e.j[a](e.i,i)}catch(t){e.h.reject(t),e.h=null}}).V(.01)}return e.h}function gp(e,t){var n=e.keyStatuses;n.size=null==t?0:1,n.g=t,n=new Jr("keystatuseschange"),e.dispatchEvent(n)}function mp(){this.size=0,this.g=void 0}wh.originalMcap=Sh,dh(Th,-1),ch.MediaSource=Eh,Eh.install=Ah,dh(Ah),ch.Orientation=Ih,Ih.install=Mh,m(Ch,Zr),Ch.prototype.lock=function(e){function t(e){return screen.lockOrientation?screen.lockOrientation(e):screen.mozLockOrientation?screen.mozLockOrientation(e):!!screen.msLockOrientation&&screen.msLockOrientation(e)}var n=!1;switch(e){case"natural":n=t("default");break;case"any":n=!0,this.unlock();break;default:n=t(e)}return n?Promise.resolve():((e=Error("screen.orientation.lock() is not available on this device")).name="NotSupportedError",e.code=DOMException.NOT_SUPPORTED_ERR,Promise.reject(e))},Ch.prototype.unlock=function(){screen.unlockOrientation?screen.unlockOrientation():screen.mozUnlockOrientation?screen.mozUnlockOrientation():screen.msUnlockOrientation&&screen.msUnlockOrientation()},dh(Mh),ch.PatchedMediaKeysApple=Dh,Dh.install=Rh,jh.prototype.createMediaKeys=function(){var e=new _h(this.keySystem);return Promise.resolve(e)},jh.prototype.getConfiguration=function(){return this.g},_h.prototype.createSession=function(e){if("temporary"!=(e=e||"temporary"))throw new TypeError("Session type "+e+" is unsupported on this platform.");return new Uh(this.g,e)},_h.prototype.setServerCertificate=function(){return Promise.resolve(!1)},m(Uh,Zr),(i=Uh.prototype).generateRequest=function(e,t){var n=this;this.g=new ci;try{var i=this.l.createSession("video/mp4",oe(t));this.j=i,this.sessionId=i.sessionId||"",this.h.A(this.j,"webkitkeymessage",function(e){n.g&&(n.g.resolve(),n.g=null),e=new Jr("message",e=(new Map).set("messageType",null==n.keyStatuses.g?"license-request":"license-renewal").set("message",ae(e.message))),n.dispatchEvent(e)}),this.h.A(i,"webkitkeyadded",function(){n.i&&(Fh(n,"usable"),n.i.resolve(),n.i=null)}),this.h.A(i,"webkitkeyerror",function(){var e=Error("EME PatchedMediaKeysApple key error");if(e.errorCode=n.j.error,null!=n.g)n.g.reject(e),n.g=null;else if(null!=n.i)n.i.reject(e),n.i=null;else switch(n.j.error.code){case WebKitMediaKeyError.MEDIA_KEYERR_OUTPUT:case WebKitMediaKeyError.MEDIA_KEYERR_HARDWARECHANGE:Fh(n,"output-not-allowed");break;default:Fh(n,"internal-error")}}),Fh(this,"status-pending")}catch(e){this.g.reject(e)}return this.g},i.load=function(){return Promise.reject(Error("MediaKeySession.load not yet supported"))},i.update=function(e){this.i=new ci;try{this.j.update(oe(e))}catch(e){this.i.reject(e)}return this.i},i.close=function(){try{this.j.close(),this.closed.resolve(),this.h.ob()}catch(e){this.closed.reject(e)}return this.closed},i.remove=function(){return Promise.reject(Error("MediaKeySession.remove is only applicable for persistent licenses, which are not supported on this platform"))},(i=Bh.prototype).forEach=function(e){this.g&&e(this.g,Ka.value())},i.get=function(e){if(this.has(e))return this.g},i.has=function(e){var t=Ka.value();return!(!this.g||!ie(e,t))},i.entries=function(){},i.keys=function(){},i.values=function(){},dh(Rh),ch.PatchedMediaKeysMs=Vh,Vh.install=Hh,qh.prototype.createMediaKeys=function(){var e=new Xh(this.keySystem);return Promise.resolve(e)},qh.prototype.getConfiguration=function(){return this.g},Xh.prototype.createSession=function(e){if("temporary"!=(e=e||"temporary"))throw new TypeError("Session type "+e+" is unsupported on this platform.");return new Yh(this.g,e)},Xh.prototype.setServerCertificate=function(){return Promise.resolve(!1)},m(Yh,Zr),(i=Yh.prototype).generateRequest=function(e,t){var n=this;this.g=new ci;try{this.j=this.l.createSession("video/mp4",oe(t),null),this.h.A(this.j,"mskeymessage",function(e){n.g&&(n.g.resolve(),n.g=null),e=new Jr("message",e=(new Map).set("messageType",null==n.keyStatuses.g?"license-request":"license-renewal").set("message",ae(e.message))),n.dispatchEvent(e)}),this.h.A(this.j,"mskeyadded",function(){n.g?($h(n,"usable"),n.g.resolve(),n.g=null):n.i&&($h(n,"usable"),n.i.resolve(),n.i=null)}),this.h.A(this.j,"mskeyerror",function(){var e=Error("EME PatchedMediaKeysMs key error");if(e.errorCode=n.j.error,null!=n.g)n.g.reject(e),n.g=null;else if(null!=n.i)n.i.reject(e),n.i=null;else switch(n.j.error.code){case MSMediaKeyError.MS_MEDIA_KEYERR_OUTPUT:case MSMediaKeyError.MS_MEDIA_KEYERR_HARDWARECHANGE:$h(n,"output-not-allowed");break;default:$h(n,"internal-error")}}),$h(this,"status-pending")}catch(e){this.g.reject(e)}return this.g},i.load=function(){return Promise.reject(Error("MediaKeySession.load not yet supported"))},i.update=function(e){this.i=new ci;try{this.j.update(oe(e))}catch(e){this.i.reject(e)}return this.i},i.close=function(){try{this.j.close(),this.closed.resolve(),this.h.ob()}catch(e){this.closed.reject(e)}return this.closed},i.remove=function(){return Promise.reject(Error("MediaKeySession.remove is only applicable for persistent licenses, which are not supported on this platform"))},(i=Jh.prototype).forEach=function(e){this.g&&e(this.g,Ka.value())},i.get=function(e){if(this.has(e))return this.g},i.has=function(e){var t=Ka.value();return!(!this.g||!ie(e,t))},i.entries=function(){},i.keys=function(){},i.values=function(){},dh(Hh),ch.PatchedMediaKeysNop=Qh,Qh.install=Zh,np.prototype.createSession=function(){},np.prototype.setServerCertificate=function(){},ip.prototype.getConfiguration=function(){},ip.prototype.createMediaKeys=function(){},dh(Zh,-10),ch.PatchedMediaKeysWebkit=rp,rp.install=ap,lp.prototype.createMediaKeys=function(){var e=new cp(this.g);return Promise.resolve(e)},lp.prototype.getConfiguration=function(){return this.h},cp.prototype.createSession=function(e){if("temporary"!=(e=e||"temporary")&&"persistent-license"!=e)throw new TypeError("Session type "+e+" is unsupported on this platform.");var t=this.g||document.createElement("video");return t.src||(t.src="about:blank"),e=new hp(t,this.l,e),this.i.push(e),e},cp.prototype.setServerCertificate=function(){return Promise.resolve(!1)},m(hp,Zr),(i=hp.prototype).handleError=function(e){var t=Error("EME v0.1b key error"),n=e.errorCode;n.systemCode=e.systemCode,t.errorCode=n,!e.sessionId&&this.h?(45==e.systemCode&&(t.message="Unsupported session type."),this.h.reject(t),this.h=null):e.sessionId&&this.g?(this.g.reject(t),this.g=null):(t=e.systemCode,e.errorCode.code==MediaKeyError.MEDIA_KEYERR_OUTPUT?gp(this,"output-restricted"):gp(this,1==t?"expired":"internal-error"))},i.generateRequest=function(e,t){return pp(this,t,null)},i.load=function(e){return"persistent-license"==this.l?pp(this,null,e):Promise.reject(Error("Not a persistent session."))},i.update=function(e){var t=new ci;return function e(t,n,i){if(t.g)t.g.then(function(){return e(t,n,i)}).catch(function(){return e(t,n,i)});else{if(t.g=n,"webkit-org.w3.clearkey"==t.i){var r=fe(i),a=JSON.parse(r);"oct"!=a.keys[0].kty&&(t.g.reject(Error("Response is not a valid JSON Web Key Set.")),t.g=null),r=tt(a.keys[0].k),a=tt(a.keys[0].kid)}else r=oe(i),a=null;var o=op("addKey");try{t.j[o](t.i,r,a,t.sessionId)}catch(e){t.g.reject(e),t.g=null}}}(this,t,e),t},i.close=function(){if("persistent-license"!=this.l){if(!this.sessionId)return this.closed.reject(Error("The session is not callable.")),this.closed;var e=op("cancelKeyRequest");try{this.j[e](this.i,this.sessionId)}catch(e){}}return this.closed.resolve(),this.closed},i.remove=function(){return"persistent-license"!=this.l?Promise.reject(Error("Not a persistent session.")):this.close()},(i=mp.prototype).forEach=function(e){this.g&&e(this.g,Ka.value())},i.get=function(e){if(this.has(e))return this.g},i.has=function(e){var t=Ka.value();return!(!this.g||!ie(e,t))},i.entries=function(){},i.keys=function(){},i.values=function(){};var vp="";function yp(){}function bp(){if(e.HTMLVideoElement){var t=HTMLVideoElement.prototype;t.requestPictureInPicture&&document.exitPictureInPicture||!t.webkitSupportsPresentationMode||(document.pictureInPictureEnabled=!0,document.pictureInPictureElement=null,t.requestPictureInPicture=Tp,Object.defineProperty(t,"disablePictureInPicture",{get:Sp,set:Ep,enumerable:!0,configurable:!0}),document.exitPictureInPicture=xp,document.addEventListener("webkitpresentationmodechanged",wp,!0))}}function wp(e){if("picture-in-picture"==(e=e.target).webkitPresentationMode){document.pictureInPictureElement=e;var t=new Event("enterpictureinpicture");e.dispatchEvent(t)}else document.pictureInPictureElement==e&&(document.pictureInPictureElement=null),t=new Event("leavepictureinpicture"),e.dispatchEvent(t)}function Tp(){return this.webkitSupportsPresentationMode("picture-in-picture")?(this.webkitSetPresentationMode("picture-in-picture"),document.pictureInPictureElement=this,Promise.resolve()):Promise.reject(Error("PiP not allowed by video element"))}function xp(){var e=document.pictureInPictureElement;return e?(e.webkitSetPresentationMode("inline"),document.pictureInPictureElement=null,Promise.resolve()):Promise.reject(Error("No picture in picture element found"))}function Sp(){return!!this.hasAttribute("disablePictureInPicture")||!this.webkitSupportsPresentationMode("picture-in-picture")}function Ep(e){e?this.setAttribute("disablePictureInPicture",""):this.removeAttribute("disablePictureInPicture")}function Ap(){}function kp(){navigator.storage&&navigator.storage.estimate||!navigator.webkitTemporaryStorage||!navigator.webkitTemporaryStorage.queryUsageAndQuota||("storage"in navigator||(navigator.storage={}),navigator.storage.estimate=Ip)}function Ip(){return new Promise(function(e,t){navigator.webkitTemporaryStorage.queryUsageAndQuota(function(t,n){e({usage:t,quota:n})},t)})}function Mp(){}function Cp(){if(e.HTMLMediaElement){var t=HTMLMediaElement.prototype.play;HTMLMediaElement.prototype.play=function(){var e=t.apply(this);return e&&e.catch(function(){}),e}}}function Dp(){}function Rp(){if(e.HTMLVideoElement){var t=HTMLVideoElement.prototype;!t.getVideoPlaybackQuality&&"webkitDroppedFrameCount"in t&&(t.getVideoPlaybackQuality=Np)}}function Np(){return{droppedVideoFrames:this.webkitDroppedFrameCount,totalVideoFrames:this.webkitDecodedFrameCount,corruptedVideoFrames:0,creationTime:NaN,totalFrameDelay:0}}function Pp(){}function Lp(){if(!e.VTTCue&&e.TextTrackCue){var t=null,n=TextTrackCue.length;if(3==n)t=jp;else if(6==n)t=_p;else{try{var i=!!jp(1,2,"")}catch(e){i=!1}i&&(t=jp)}t&&(e.VTTCue=function(e,n,i){return t(e,n,i)})}}function jp(t,n,i){return new e.TextTrackCue(t,n,i)}function _p(t,n,i){return new e.TextTrackCue(t+"-"+n+"-"+i,t,n,i)}function Op(){}dh(ap),ch.PiPWebkit=yp,yp.install=bp,dh(bp),ch.StorageEstimate=Ap,Ap.install=kp,dh(kp),ch.VideoPlayPromise=Mp,Mp.install=Cp,dh(Cp),ch.VideoPlaybackQuality=Dp,Dp.install=Rp,dh(Rp),ch.VTTCue=Pp,Pp.install=Lp,dh(Lp),Op.prototype.parseInit=function(){},Op.prototype.parseMedia=function(e,t){for(var n=null,i=[],r=fe(e).split(/\r?\n/),a=(r=l(r)).next();!a.done;a=r.next())if((a=a.value)&&!/^\s+$/.test(a)&&(a=Up.exec(a))){var o=Fp.exec(a[1]);a=new ft(o=60*parseInt(o[1],10)+parseFloat(o[2].replace(",",".")),t.segmentEnd?t.segmentEnd:o+2,a[2]),n&&(n.endTime=o,i.push(n)),n=a}return n&&i.push(n),i},B("shaka.text.LrcTextParser",Op),Op.prototype.parseMedia=Op.prototype.parseMedia,Op.prototype.parseInit=Op.prototype.parseInit;var Up=/^\[(\d{1,2}:\d{1,2}(?:[.,]\d{1,3})?)\](.*)/,Fp=/^(\d+):(\d{1,2}(?:[.,]\d{1,3})?)$/;function Bp(){}function Vp(e,t){for(var n=l(t.split(" ")),i=n.next();!i.done;i=n.next())switch(i.value){case"underline":e.textDecoration.includes("underline")||e.textDecoration.push("underline");break;case"noUnderline":e.textDecoration.includes("underline")&<(e.textDecoration,"underline");break;case"lineThrough":e.textDecoration.includes("lineThrough")||e.textDecoration.push("lineThrough");break;case"noLineThrough":e.textDecoration.includes("lineThrough")&<(e.textDecoration,"lineThrough");break;case"overline":e.textDecoration.includes("overline")||e.textDecoration.push("overline");break;case"noOverline":e.textDecoration.includes("overline")&<(e.textDecoration,"overline")}}function Hp(e,t,n,i,r){return r=void 0===r||r,(e=Gp(e,n,i))?e:r?Kp(t,n,i):null}function Kp(e,t,n){if(!e)return null;var i=zl(e,cg,n);return i||qp(e,t,n)}function Gp(e,t,n){var i=zl(e,cg,n);return i||qp(e,t,n)}function qp(e,t,n){e=zp(e,"style",t,"");for(var i=null,r=0;rn.length)return a;var o=e;for(e=null;o&&!(e=r?ql(o,r,t):o.getAttribute(t))&&(o=o.parentNode)instanceof Element;);if(t=e)for(r=(t=l(t.split(" "))).next();!r.done;r=t.next())for(r=r.value,o=(e=l(n)).next();!o.done;o=e.next())if(i+(o=o.value).getAttribute("xml:id")==r){a.push(o);break}return a}function Xp(e,t,n,i){return e=Wp(e,t),null==n?n=e.start:null!=e.start&&(n+=e.start),null==i?i=e.end:null!=e.start&&(i+=e.start),{start:n,end:i}}function Wp(e,t){var n=Yp(e.getAttribute("begin"),t),i=Yp(e.getAttribute("end"),t),r=Yp(e.getAttribute("dur"),t);return null==i&&null!=r&&(i=n+r),{start:n,end:i}}function Yp(e,t){var n=null;if(tg.test(e)){n=tg.exec(e);var i=Number(n[1]),r=Number(n[2]),a=Number(n[3]),o=Number(n[4]);n=(a+=(o+=(Number(n[5])||0)/t.h)/t.frameRate)+60*r+3600*i}else if(ng.test(e))n=$p(ng,e);else if(ig.test(e))n=$p(ig,e);else if(rg.test(e))n=rg.exec(e),n=Number(n[1])/t.frameRate;else if(ag.test(e))n=ag.exec(e),n=Number(n[1])/t.g;else if(og.test(e))n=$p(og,e);else if(e)throw new le(2,2,2001,"Could not parse cue time range in TTML");return n}function $p(e,t){var n=e.exec(t);return null==n||""==n[0]?null:(Number(n[4])||0)/1e3+(Number(n[3])||0)+60*(Number(n[2])||0)+3600*(Number(n[1])||0)}Ii["application/x-subtitle-lrc"]=function(){return new Op},Bp.prototype.parseInit=function(){},Bp.prototype.parseMedia=function(e,t){var n=fe(e),i=[],r=new DOMParser,a=null;if(""==n)return i;try{a=r.parseFromString(n,"text/xml")}catch(e){throw new le(2,2,2005,"Failed to parse TTML.")}if(a){if(n=a.getElementsByTagName("parsererror")[0])throw new le(2,2,2005,n.textContent);var o=a.getElementsByTagName("tt")[0];if(!o)throw new le(2,2,2005,"TTML does not contain tag.");if(!(a=o.getElementsByTagName("body")[0]))return[];var s=zl(o,lg,"frameRate"),u=zl(o,lg,"subFrameRate"),c=zl(o,lg,"frameRateMultiplier"),d=zl(o,lg,"tickRate"),f=zl(o,lg,"cellResolution");if(n=o.getAttribute("xml:space")||"default",r=zl(o,cg,"extent"),"default"!=n&&"preserve"!=n)throw new le(2,2,2005,"Invalid xml:space value: "+n);n="default"==n,s=new function(e,t,n,i){this.frameRate=Number(e)||30,this.h=Number(t)||1,this.g=Number(i),0==this.g&&(this.g=e?this.frameRate*this.h:1),n&&(e=/^(\d+) (\d+)$/g.exec(n))&&(this.frameRate*=Number(e[1])/Number(e[2]))}(s,u,c,d),f=f&&(f=/^(\d+) (\d+)$/.exec(f))?{columns:parseInt(f[1],10),rows:parseInt(f[2],10)}:null,u=(u=o.getElementsByTagName("metadata")[0])?function(e){return Array.from(e.childNodes).filter(function(e){return e instanceof Element})}(u):[],c=Array.from(o.getElementsByTagName("style")),d=[];for(var h=l(o=Array.from(o.getElementsByTagName("region"))),p=h.next();!p.done;p=h.next()){var g=p.value;p=new Ct;var m=g.getAttribute("xml:id");if(m){p.id=m;var v,y,b=null;r&&(b=Jp.exec(r)||eg.exec(r)),m=b?Number(b[1]):null,b=b?Number(b[2]):null,(v=Kp(g,c,"extent"))&&(null!=(v=(y=Jp.exec(v))||eg.exec(v))&&(p.width=Number(v[1]),p.height=Number(v[2]),y||(null!=m&&(p.width=100*p.width/m),null!=b&&(p.height=100*p.height/b)),p.widthUnits=y||null!=m?Dt:0,p.heightUnits=y||null!=b?Dt:0)),(g=Kp(g,c,"origin"))&&(null!=(v=(y=Jp.exec(g))||eg.exec(g))&&(p.viewportAnchorX=Number(v[1]),p.viewportAnchorY=Number(v[2]),y||(null!=b&&(p.viewportAnchorY=100*p.viewportAnchorY/b),null!=m&&(p.viewportAnchorX=100*p.viewportAnchorX/m)),p.viewportAnchorUnits=y||null!=m?Dt:0))}else p=null;p&&d.push(p)}if(Kl(a,"p").length)throw new le(2,2,2001,"

can only be inside

in TTML");for(h=(r=l(Kl(a,"div"))).next();!h.done;h=r.next())if(Kl(h.value,"span").length)throw new le(2,2,2001," can only be inside

in TTML");(a=function e(t,n,i,r,a,o,s,u,c,d,f){var h=t.parentNode;if(t.nodeType==Node.COMMENT_NODE)return null;if(t.nodeType==Node.TEXT_NODE){if(!f)return null;var p=document.createElement("span");p.textContent=t.textContent}else p=t;for(var g=null,m=l(dg),v=m.next();!v.done&&!(g=zp(p,"backgroundImage",r,"#",v.value)[0]);v=m.next());m=f;("p"==t.nodeName||g)&&(f=!0);u="default"==(p.getAttribute("xml:space")||(u?"default":"preserve"));v=Array.from(p.childNodes).every(function(e){return e.nodeType==Node.TEXT_NODE});t=[];if(!v)for(var y=l(p.childNodes),b=y.next();!b.done;b=y.next())(b=e(b.value,n,i,r,a,o,s,u,c,p,f))&&t.push(b);r=null!=d;y=/\S/.test(p.textContent);var w=p.hasAttribute("begin")||p.hasAttribute("end")||p.hasAttribute("dur");if(!(w||y||"br"==p.tagName||0!=t.length||r&&!u))return null;b=Wp(p,i);y=b.start;for(b=b.end;h&&h.nodeType==Node.ELEMENT_NODE&&"tt"!=h.tagName;)b=Xp(h,i,y,b),y=b.start,b=b.end,h=h.parentNode;null==y&&(y=0);y+=n;b=null==b?1/0:b+n;if(!w&&0"+(e=function(e){for(var t=[],n=-1,i="",r=0;r",r);if(a<=r)return e;a=e.substring(r+1,a);var o=t.pop();if(!a||!o)return e;if(o===a)i+="/"+a+">";else{if(!o.startsWith("c.")||"c"!==a)return e;i+="/"+o+">"}r+=a.length+1}else"<"===e[r]?n=r+1:">"===e[r]&&0","span");if(i){var r=[];if(1==(i=i.childNodes).length){var a=i[0];if(a.nodeType==Node.TEXT_NODE||a.nodeType==Node.CDATA_SECTION_NODE)return void(t.payload=e)}for(i=(e=l(i)).next();!i.done;i=e.next())vg(i.value,t,r,n);t.nestedCues=r}else t.payload=e}function mg(e,t){return e&&0>8&255)+","+(e>>16&255)+","+(e>>24&255^255)/255+")":null}function Cg(e){return 3600*((e=jg.exec(e))[1]?parseInt(e[1].replace(":",""),10):0)+60*parseInt(e[2],10)+parseFloat(e[3])}Ii["application/ttml+xml"]=function(){return new Bp},fg.prototype.parseInit=function(e){var t=!1;if((new De).box("moov",Re).box("trak",Re).box("mdia",Re).box("minf",Re).box("stbl",Re).T("stsd",Ne).box("stpp",function(e){t=!0,e.parser.stop()}).parse(e),!t)throw new le(2,2,2007)},fg.prototype.parseMedia=function(e,t){var n=this,i=!1,r=[];if((new De).box("mdat",Pe(function(e){i=!0,r=r.concat(n.s.parseMedia(e,t))})).parse(e,!1),!i)throw new le(2,2,2007);return r},B("shaka.text.Mp4TtmlParser",fg),fg.prototype.parseMedia=fg.prototype.parseMedia,fg.prototype.parseInit=fg.prototype.parseInit,Ii['application/mp4; codecs="stpp"']=function(){return new fg},Ii['application/mp4; codecs="stpp.ttml"']=function(){return new fg},Ii['application/mp4; codecs="stpp.ttml.im1t"']=function(){return new fg},Ii['application/mp4; codecs="stpp.TTML.im1t"']=function(){return new fg},hg.prototype.parseInit=function(){},hg.prototype.parseMedia=function(e,t){var n=fe(e),i=(n=n.replace(/\r\n|\r(?=[^\n]|$)/gm,"\n")).split(/\n{2,}/m);if(!/^WEBVTT($|[ \t\n])/m.test(i[0]))throw new le(2,2,2e3);if(n=t.periodStart,i[0].includes("X-TIMESTAMP-MAP")){var r=i[0].match(/LOCAL:((?:(\d{1,}):)?(\d{2}):(\d{2})\.(\d{3}))/m),a=i[0].match(/MPEGTS:(\d+)/m);if(r&&a){if(null==(n=bg(new Ed(r[1]))))throw new le(2,2,2e3);for(a=Number(a[1]),r=t.segmentStart;95443.7176888889<=r;)r-=95443.7176888889,a+=8589934592;n=t.periodStart+a/9e4-n}}a=[];for(var o=(r=l(i[0].split("\n"))).next();!o.done;o=r.next())if(o=o.value,/^Region:/.test(o)){o=new Ed(o);var s=new Ct;Id(o),Ad(o);for(var u=Id(o);u;){var c=s,d=u;(u=/^id=(.*)$/.exec(d))?c.id=u[1]:(u=/^width=(\d{1,2}|100)%$/.exec(d))?c.width=Number(u[1]):(u=/^lines=(\d+)$/.exec(d))?(c.height=Number(u[1]),c.heightUnits=2):(u=/^regionanchor=(\d{1,2}|100)%,(\d{1,2}|100)%$/.exec(d))?(c.regionAnchorX=Number(u[1]),c.regionAnchorY=Number(u[2])):(u=/^viewportanchor=(\d{1,2}|100)%,(\d{1,2}|100)%$/.exec(d))?(c.viewportAnchorX=Number(u[1]),c.viewportAnchorY=Number(u[2])):/^scroll=up$/.exec(d)&&(c.scroll="up"),Ad(o),u=Id(o)}a.push(s)}for(pg(r=new Map),o=[],s=(i=l(i.slice(1))).next();!s.done;s=i.next()){if((1!=(s=s.value.split("\n")).length||s[0])&&!/^NOTE($|[ \t])/.test(s[0])&&"STYLE"==s[0]&&s[1].includes("::cue")){c="global",(u=s[1].match(/\((.*)\)/))&&(c=u.pop()),u=s.slice(2,-1),s[1].includes("}")&&(d=/\{(.*?)\}/.exec(s[1]))&&(u=d[1].split(";")),d=new ft(0,0,"");for(var f=!1,h=0;h { + const channelId = e.target.attributes["data-cid"].value; + e.target.disabled = true; + + let xhr = new XMLHttpRequest(); + xhr.open("GET", "/Account/Subscribe?channel=" + channelId, false) + xhr.send() + + e.target.disabled = false; + if (xhr.status !== 200) + alert("You need to login to subscribe to a channel") + + if (xhr.responseText === "true") { + e.target.innerText = "Subscribed"; + e.target.classList.add("subscribed") + } else { + e.target.innerText = "Subscribe"; + e.target.classList.remove("subscribed") + } +} + +if (subscribeButtons.length > 0) { + let xhr = new XMLHttpRequest(); + xhr.open("GET", "/Account/SubscriptionsJson", false) + xhr.send() + + let subscribedChannels = JSON.parse(xhr.responseText); + + for (let i = 0; i < subscribeButtons.length; i++) { + let button = subscribeButtons[i]; + if (subscribedChannels.includes(button.attributes["data-cid"].value)) { + button.innerText = "Subscribed"; + button.classList.add("subscribed") + } else { + button.innerText = "Subscribe"; + button.classList.remove("subscribed") + } + + button.onclick = subscribeToChannel; + button.style.display = "" + } +} \ No newline at end of file diff --git a/core/LightTube/wwwroot/tampermonkey.js b/core/LightTube/wwwroot/tampermonkey.js new file mode 100644 index 00000000..70507784 --- /dev/null +++ b/core/LightTube/wwwroot/tampermonkey.js @@ -0,0 +1,41 @@ +// ==UserScript== +// @name LightTube Redirect Button +// @namespace http://youtube.com +// @version 0.1 +// @description Adds a redirect button to the YouTube watch page to redirect to LightTube +// @match https://www.youtube.com/* +// @require http://code.jquery.com/jquery-latest.js +// ==/UserScript== + +(function () { + "use strict"; + + const createLtButton = () => { + let ltButton = document.createElement("button"); + ltButton.onclick = () => { + ltButton.innerHTML = "Loading proxy, please wait..."; + ltButton.disabled = true; + window.location = "https://lighttube.herokuapp.com/watch" + window.location.search; + }; + ltButton.innerHTML = "Proxy (lighttube)"; + ltButton.id = "lighttube-button"; + return ltButton; + }; + + let ltButton = createLtButton(); + + // Add button whenever you can + setInterval(() => { + if (window.location.pathname === "/watch" && !document.getElementById("lighttube-button") && document.getElementById("sponsor-button")) { + console.log("Inserted button!"); + document.getElementById("sponsor-button").parentElement.insertBefore(ltButton, document.getElementById("sponsor-button")); + } + }, 1000); + + // Ping lighttube so it stays awake + setInterval(() => { + fetch("https://lighttube.herokuapp.com/").then(() => {}) + }, 30000); + + console.log("Pog!"); +})();