From d9ca7beaa9494cf34590853901cf8be44e243775 Mon Sep 17 00:00:00 2001 From: RblSb Date: Thu, 16 Jan 2025 03:07:31 +0300 Subject: Cache on server feature Server will download video from supported players and add as raw video to playlist (only youtube is supported for now). Cache for YT player is available after installing optional dependencies, see readme. For cache size see `cacheStorageLimitGiB ` in config. There is also minor ux improvement, latest checkbox states will be keeped in local storage now. --- src/client/players/Iframe.hx | 7 +++++- src/client/players/Raw.hx | 5 ++++ src/client/players/Youtube.hx | 55 ++++++++++++------------------------------- 3 files changed, 26 insertions(+), 41 deletions(-) (limited to 'src/client/players') diff --git a/src/client/players/Iframe.hx b/src/client/players/Iframe.hx index 56cf319..8a2e06e 100644 --- a/src/client/players/Iframe.hx +++ b/src/client/players/Iframe.hx @@ -1,5 +1,6 @@ package client.players; +import Types.PlayerType; import Types.VideoData; import Types.VideoDataRequest; import Types.VideoItem; @@ -18,13 +19,17 @@ class Iframe implements IPlayer { this.player = player; } + public function getPlayerType():PlayerType { + return IframeType; + } + public function isSupportedLink(url:String):Bool { return true; } public function getVideoData(data:VideoDataRequest, callback:(data:VideoData) -> Void):Void { final iframe = document.createDivElement(); - iframe.innerHTML = data.url; + iframe.innerHTML = data.url.trim(); if (isValidIframe(iframe)) { callback({duration: 99 * 60 * 60}); } else { diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx index 5c5b7a4..7e5e50c 100644 --- a/src/client/players/Raw.hx +++ b/src/client/players/Raw.hx @@ -1,5 +1,6 @@ package client.players; +import Types.PlayerType; import Types.VideoData; import Types.VideoDataRequest; import Types.VideoItem; @@ -30,6 +31,10 @@ class Raw implements IPlayer { this.player = player; } + public function getPlayerType():PlayerType { + return RawType; + } + public function isSupportedLink(url:String):Bool { return true; } diff --git a/src/client/players/Youtube.hx b/src/client/players/Youtube.hx index 3ad9030..5a8921a 100644 --- a/src/client/players/Youtube.hx +++ b/src/client/players/Youtube.hx @@ -1,5 +1,6 @@ package client.players; +import Types.PlayerType; import Types.VideoData; import Types.VideoDataRequest; import Types.VideoItem; @@ -23,7 +24,6 @@ class Youtube implements IPlayer { var apiKey:String; var video:Element; var youtube:YoutubePlayer; - var tempYoutube:YoutubePlayer; var isLoaded = false; public function new(main:Main, player:Player) { @@ -31,6 +31,10 @@ class Youtube implements IPlayer { this.player = player; } + public function getPlayerType():PlayerType { + return YoutubeType; + } + public function isSupportedLink(url:String):Bool { return extractVideoId(url) != "" || extractPlaylistId(url) != ""; } @@ -43,6 +47,10 @@ class Youtube implements IPlayer { return YoutubeUtils.extractPlaylistId(url); } + public function isPlaylistUrl(url:String):Bool { + return extractVideoId(url) == "" && extractPlaylistId(url) != ""; + } + final matchHours = ~/([0-9]+)H/; final matchMinutes = ~/([0-9]+)M/; final matchSeconds = ~/([0-9]+)S/; @@ -93,7 +101,7 @@ class Youtube implements IPlayer { url: '', - isIframe: true + playerType: IframeType }); continue; } @@ -168,6 +176,7 @@ class Youtube implements IPlayer { final video = document.createDivElement(); video.id = "temp-videoplayer"; Utils.prepend(playerEl, video); + var tempYoutube:YoutubePlayer = null; tempYoutube = new YoutubePlayer(video.id, { videoId: extractVideoId(url), playerVars: { @@ -181,12 +190,14 @@ class Youtube implements IPlayer { callback({ duration: tempYoutube.getDuration() }); + tempYoutube.destroy(); }, onError: e -> { // TODO message error codes trace('Error ${e.data}'); if (playerEl.contains(video)) playerEl.removeChild(video); callback({duration: 0}); + tempYoutube.destroy(); } } }); @@ -243,49 +254,13 @@ class Youtube implements IPlayer { onError: e -> { // TODO message error codes trace('Error ${e.data}'); - final item = player.getCurrentItem() ?? return; - rawSourceFallback(item.url); + // final item = player.getCurrentItem() ?? return; + // 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; - }; - player.changeVideoSrc(format.url); - }); - main.send({ - type: GetYoutubeVideoInfo, - getYoutubeVideoInfo: { - url: url - } - }); - } - - function getBestStreamFormat(info:YouTubeVideoInfo):Null { - info.formats ??= []; - info.adaptiveFormats ??= []; - final formats = info.adaptiveFormats.concat(info.formats); - trace(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; -- cgit v1.2.3