diff options
| author | RblSb <msrblsb@gmail.com> | 2025-11-13 13:43:56 +0300 |
|---|---|---|
| committer | RblSb <msrblsb@gmail.com> | 2025-11-13 23:59:57 +0300 |
| commit | c1d1be00c7cace0544c3c6cd152e8c3287b976c4 (patch) | |
| tree | 416b4534a84ee81032cb2c310167c97c900248f9 /src/server | |
| parent | ee3eddc6b80565f6bb458a1fd8f3a83fdd37d554 (diff) | |
Support yt-dlp with js runtimes
Also adds server version for standalone clients.
Remember to update `RblSb/ytdlp-nodejs` if you use this feature.
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/Main.hx | 34 | ||||
| -rw-r--r-- | src/server/cache/YoutubeCache.hx | 42 |
2 files changed, 51 insertions, 25 deletions
diff --git a/src/server/Main.hx b/src/server/Main.hx index e67fbcb..8b9ade1 100644 --- a/src/server/Main.hx +++ b/src/server/Main.hx @@ -6,6 +6,7 @@ import Types.FlashbackItem; import Types.Message; import Types.Permission; import Types.PlayerType; +import Types.ServerConfig; import Types.UserList; import Types.VideoItem; import Types.WsEvent; @@ -26,6 +27,7 @@ import json2object.JsonParser; import server.cache.Cache; import sys.FileSystem; import sys.io.File; +import utils.macro.Macro; private typedef MainOptions = { loadState:Bool @@ -34,6 +36,7 @@ private typedef MainOptions = { class Main { public static inline var MIN_PASSWORD_LENGTH = 4; public static inline var MAX_PASSWORD_LENGTH = 50; + static inline var SERVER_VERSION = 2; static inline var VIDEO_START_MAX_DELAY = 3000; static inline var VIDEO_SKIP_DELAY = 1000; static inline var FLASHBACKS_COUNT = 50; @@ -44,7 +47,7 @@ class Main { public final userDir:String; public final logsDir:String; - public final config:Config; + public final config:ServerConfig; public final isNoState:Bool; final verbose:Bool; @@ -120,6 +123,12 @@ class Main { exit(); }); + config = loadUserConfig(); + config.serverVersion = SERVER_VERSION; + config.isVerbose = verbose; + userList = loadUsers(); + config.salt = generateConfigSalt(userList); + logger = new Logger(logsDir, 10, verbose); consoleInput = new ConsoleInput(this); consoleInput.initConsoleInput(); @@ -127,11 +136,8 @@ class Main { if (cache.isYtReady) playersCacheSupport.push(YoutubeType); initIntergationHandlers(); loadState(); - config = loadUserConfig(); cache.setStorageLimit(cast config.cacheStorageLimitGiB * 1024 * 1024 * 1024); - userList = loadUsers(); - config.isVerbose = verbose; - config.salt = generateConfigSalt(); + if (config.localNetworkOnly) localIp = "127.0.0.1"; else localIp = Utils.getLocalIp(); globalIp = localIp; @@ -235,7 +241,7 @@ class Main { }; } - function getSslConfig(config:Config):Null<{key:String, cert:String}> { + function getSslConfig(config:ServerConfig):Null<{key:String, cert:String}> { final c = config; if (c.sslKeyPemPath.length == 0 && c.sslCertPemPath.length == 0) return null; final hasBoth = FileSystem.exists(c.sslKeyPemPath) @@ -264,12 +270,12 @@ class Main { process.exit(); } - function generateConfigSalt():String { - userList.salt ??= Sha256.encode('${Math.random()}'); - return userList.salt; + function generateConfigSalt(users:UserList):String { + users.salt ??= Sha256.encode('${Math.random()}'); + return users.salt; } - function loadUserConfig():Config { + function loadUserConfig():ServerConfig { final config = getUserConfig(); inline function getPermissions(type:Permission):Array<Permission> { return Reflect.field(config.permissions, cast type); @@ -289,12 +295,12 @@ class Main { return config; } - function getUserConfig():Config { - final config:Config = Json.parse(File.getContent('$rootDir/default-config.json')); + function getUserConfig():ServerConfig { + final config:ServerConfig = Json.parse(File.getContent('$rootDir/default-config.json')); if (isNoState) return config; final customPath = '$userDir/config.json'; if (!FileSystem.exists(customPath)) return config; - final customConfig:Config = Json.parse(File.getContent(customPath)); + final customConfig:ServerConfig = Json.parse(File.getContent(customPath)); for (field in Reflect.fields(customConfig)) { if (Reflect.field(config, field) == null) { trace('Warning: config field "$field" is unknown'); @@ -563,7 +569,7 @@ class Main { type: Connected, connected: { uuid: client.uuid, - config: config, + config: Macro.getTypedObject(config, Config), history: messages, isUnknownClient: true, clientName: client.name, diff --git a/src/server/cache/YoutubeCache.hx b/src/server/cache/YoutubeCache.hx index c7053f9..0618d00 100644 --- a/src/server/cache/YoutubeCache.hx +++ b/src/server/cache/YoutubeCache.hx @@ -1,6 +1,6 @@ package server.cache; -import haxe.Json; +import haxe.io.Path; import js.lib.Promise; import js.node.ChildProcess; import sys.FileSystem; @@ -30,7 +30,8 @@ class YoutubeCache { } public function checkUpdate():Void { - ytDlp.execAsync("-U", { + ytDlp.execAsync("", { + updateTo: main.config.ytDlp.channel, onData: d -> { trace(d); } @@ -136,36 +137,51 @@ class YoutubeCache { } if (!checkEnoughSpace(getTotalFormatsSize() * 2)) return; - final formatIds = if (videoFormat.format_id == audioFormat.format_id) { + final isMuxed = videoFormat.format_id == audioFormat.format_id; + final formatIds = if (isMuxed) { videoFormat.format_id; } else { '${videoFormat.format_id}+${audioFormat.format_id}'; } - var totalSize = getTotalFormatsSize().limitMin(10); + final totalSize = getTotalFormatsSize().limitMin(10); var videoSizeRatio = (videoFormat.filesize ?? 0).limitMin(8) / totalSize; var audioSizeRatio = (audioFormat.filesize ?? 0).limitMin(2) / totalSize; - var isVideoFormatDownloading = true; + if (isMuxed) { + videoSizeRatio = 1; + audioSizeRatio = 0; + } + trace(formatIds, toMibString(totalSize), videoSizeRatio.toFixed(), audioSizeRatio.toFixed()); + + var videoRatioCache = 0.0; + var audioRatioCache = 0.0; final dlVideo:Promise<String> = ytDlp.downloadAsync(url, { format: formatIds, output: '${cache.cacheDir}/$inVideoName', remuxVideo: "mp4", + additionalOptions: ["--no-js-runtimes", "--js-runtimes", main.config.ytDlp.jsRuntime], + // verbose: true, cookies: useCookies ? getCookiesPathOrNull() : null, forceIpv4: true, socketTimeout: 2, extractorRetries: 0, onProgress: p -> { final isFinished = p.status == "finished"; + if (isFinished) { + final filename = Path.withoutDirectory(p.filename); + trace('$filename format file downloaded'); + } var ratio = if (isFinished) { 1; } else { (p.downloaded / p.total).clamp(0, 1); } - if (isVideoFormatDownloading) { - ratio = ratio * videoSizeRatio; - } else { - ratio = videoSizeRatio + ratio * audioSizeRatio; - } - if (isFinished) isVideoFormatDownloading = false; + + final isVideo = p.filename.contains('f${videoFormat.format_id}'); + if (isVideo) videoRatioCache = ratio; + else audioRatioCache = ratio; + + ratio = videoRatioCache * videoSizeRatio + audioRatioCache * audioSizeRatio; + main.sendByName(clientName, { type: Progress, progress: { @@ -249,6 +265,10 @@ class YoutubeCache { return format.format_note ?? '${resolution}p'; } + inline function toMibString(bytes:Int):String { + return '${(bytes / 1024 / 1024).toFixed()} MiB'; + } + function log(clientName:String, msg:String):Void { cache.logByName(clientName, msg); } |
