aboutsummaryrefslogtreecommitdiffstats
path: root/src/client/players/Youtube.hx
diff options
context:
space:
mode:
authorRblSb <msrblsb@gmail.com>2024-04-28 07:23:25 +0300
committerRblSb <msrblsb@gmail.com>2024-04-28 21:51:50 +0300
commit9d844bbf3ac6be327325b13a91a6b33f73c49c1d (patch)
tree52108f2300ca84decf33a1e7b3552e81166ba5ac /src/client/players/Youtube.hx
parent8679f8edcb6d2f3142db30848c640aed6fe883b8 (diff)
Raw youtube fallback for unavailable videos
Also: - fix `tryLocalIp` replacement (NAT workaround) - improve proxy headers a bit - use json2object fork for better generated diffs
Diffstat (limited to 'src/client/players/Youtube.hx')
-rw-r--r--src/client/players/Youtube.hx69
1 files changed, 47 insertions, 22 deletions
diff --git a/src/client/players/Youtube.hx b/src/client/players/Youtube.hx
index a728012..5308b63 100644
--- a/src/client/players/Youtube.hx
+++ b/src/client/players/Youtube.hx
@@ -10,15 +10,11 @@ import js.Browser.document;
import js.html.Element;
import js.youtube.Youtube as YtInit;
import js.youtube.YoutubePlayer;
+import utils.YoutubeUtils;
using StringTools;
class Youtube implements IPlayer {
- final matchId = ~/youtube\.com.*v=([A-z0-9_-]+)/;
- final matchShort = ~/youtu\.be\/([A-z0-9_-]+)/;
- final matchShorts = ~/youtube\.com\/shorts\/([A-z0-9_-]+)/;
- final matchEmbed = ~/youtube\.com\/embed\/([A-z0-9_-]+)/;
- final matchPlaylist = ~/youtube\.com.*list=([A-z0-9_-]+)/;
final videosUrl = "https://www.googleapis.com/youtube/v3/videos";
final playlistUrl = "https://www.googleapis.com/youtube/v3/playlistItems";
final urlTitleDuration = "?part=snippet,contentDetails&fields=items(snippet/title,contentDetails/duration)";
@@ -41,25 +37,12 @@ class Youtube implements IPlayer {
return extractVideoId(url) != "" || extractPlaylistId(url) != "";
}
- public function extractVideoId(url:String):String {
- if (matchId.match(url)) {
- return matchId.matched(1);
- }
- if (matchShort.match(url)) {
- return matchShort.matched(1);
- }
- if (matchShorts.match(url)) {
- return matchShorts.matched(1);
- }
- if (matchEmbed.match(url)) {
- return matchEmbed.matched(1);
- }
- return "";
+ public function extractVideoId(url:String) {
+ return YoutubeUtils.extractVideoId(url);
}
- function extractPlaylistId(url:String):String {
- if (!matchPlaylist.match(url)) return "";
- return matchPlaylist.matched(1);
+ public function extractPlaylistId(url:String) {
+ return YoutubeUtils.extractPlaylistId(url);
}
final matchHours = ~/([0-9]+)H/;
@@ -256,11 +239,53 @@ class Youtube implements IPlayer {
},
onPlaybackRateChange: e -> {
player.onRateChange();
+ },
+ onError: e -> {
+ // TODO message error codes
+ trace('Error ${e.data}');
+ rawSourceFallback(item.url);
}
}
});
}
+ function rawSourceFallback(url:String):Void {
+ JsApi.once(GetYoutubeVideoInfo, event -> {
+ final data = event.getYoutubeVideoInfo;
+ final info = data.response;
+ final format = getBestStreamFormat(info) ?? {
+ trace("format not found in response info:");
+ trace(info);
+ return;
+ };
+ final item = player.getCurrentItem();
+ item.url = format.url;
+ player.refresh();
+ });
+ main.send({
+ type: GetYoutubeVideoInfo,
+ getYoutubeVideoInfo: {
+ url: url
+ }
+ });
+ }
+
+ function getBestStreamFormat(info:YouTubeVideoInfo):Null<YoutubeVideoFormat> {
+ info.formats ??= [];
+ info.adaptiveFormats ??= [];
+ final formats = info.adaptiveFormats.concat(info.formats);
+ final qPriority = [1080, 720, 480, 360, 240];
+ for (q in qPriority) {
+ final quality = '${q}p';
+ for (format in formats) {
+ if (format.audioQuality == null) continue; // no sound
+ if (format.width == null) continue; // no video
+ if (format.qualityLabel == quality) return format;
+ }
+ }
+ return null;
+ }
+
public function removeVideo():Void {
if (video == null) return;
isLoaded = false;
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage