diff --git a/src/main/java/cz/kamma/xtreamplayer/XtreamPlayerApplication.java b/src/main/java/cz/kamma/xtreamplayer/XtreamPlayerApplication.java index aae7a90..50a797c 100644 --- a/src/main/java/cz/kamma/xtreamplayer/XtreamPlayerApplication.java +++ b/src/main/java/cz/kamma/xtreamplayer/XtreamPlayerApplication.java @@ -338,7 +338,11 @@ public final class XtreamPlayerApplication { String streamUrl; String directUrl = query.getOrDefault("url", "").trim(); if (!directUrl.isBlank()) { - if (!directUrl.startsWith("http://") && !directUrl.startsWith("https://")) { + String lowerUrl = directUrl.toLowerCase(Locale.ROOT); + if (!lowerUrl.startsWith("http://") + && !lowerUrl.startsWith("https://") + && !lowerUrl.startsWith("rtsp://") + && !lowerUrl.startsWith("rtsps://")) { writeJson(exchange, 400, errorJson("Unsupported URL protocol.")); return; } @@ -817,8 +821,13 @@ public final class XtreamPlayerApplication { List attemptErrors = new ArrayList<>(); for (URI candidate : attempts) { try { + String incomingRange = firstNonBlank( + exchange.getRequestHeaders().getFirst("Range"), + "bytes=0-" + ); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(candidate) .GET() + .timeout(Duration.ofSeconds(60)) .header("User-Agent", firstNonBlank( exchange.getRequestHeaders().getFirst("User-Agent"), DEFAULT_BROWSER_UA @@ -826,12 +835,16 @@ public final class XtreamPlayerApplication { .header("Accept", firstNonBlank( exchange.getRequestHeaders().getFirst("Accept"), "*/*" + )) + .header("Range", incomingRange) + .header("Accept-Encoding", firstNonBlank( + exchange.getRequestHeaders().getFirst("Accept-Encoding"), + "identity" )); - copyRequestHeaderIfPresent(exchange, requestBuilder, "Range"); copyRequestHeaderIfPresent(exchange, requestBuilder, "If-Range"); - copyRequestHeaderIfPresent(exchange, requestBuilder, "Accept-Encoding"); copyRequestHeaderIfPresent(exchange, requestBuilder, "Cache-Control"); copyRequestHeaderIfPresent(exchange, requestBuilder, "Pragma"); + copyRequestHeaderIfPresent(exchange, requestBuilder, "Origin"); String referer = resolveRefererForCandidate(exchange, candidate, sourceUrl); if (!referer.isBlank()) { requestBuilder.header("Referer", referer); diff --git a/src/main/resources/web/assets/app.js b/src/main/resources/web/assets/app.js index 4b1a985..90da8aa 100644 --- a/src/main/resources/web/assets/app.js +++ b/src/main/resources/web/assets/app.js @@ -310,6 +310,10 @@ if (!name || !url) { return; } + if (!isSupportedCustomUrl(url)) { + setSettingsMessage("Custom stream URL must start with http://, https://, rtsp://, or rtsps://", "err"); + return; + } state.customStreams.push({ id: String(Date.now()), name, @@ -1748,6 +1752,15 @@ setSubtitleStatus("No subtitle loaded.", false); scheduleEmbeddedSubtitleScan(); + if (isRtspUrl(playbackUrl)) { + state.currentStreamInfo.playbackEngine = "external player (RTSP)"; + state.currentStreamInfo.resolution = "n/a"; + state.currentStreamInfo.duration = "n/a"; + renderStreamInfo(); + setSettingsMessage("RTSP is not supported in browser player. Use Open in system player.", "err"); + return; + } + if (isLikelyHls(playbackUrl) && shouldUseHlsJs()) { state.currentStreamInfo.playbackEngine = "hls.js"; renderStreamInfo(); @@ -1820,6 +1833,9 @@ if (!url) { return url; } + if (isRtspUrl(url)) { + return url; + } try { const pageIsHttps = window.location.protocol === "https:"; const target = new URL(url, window.location.href); @@ -1832,6 +1848,19 @@ return url; } + function isRtspUrl(urlRaw) { + const value = String(urlRaw || "").trim().toLowerCase(); + return value.startsWith("rtsp://") || value.startsWith("rtsps://"); + } + + function isSupportedCustomUrl(urlRaw) { + const value = String(urlRaw || "").trim().toLowerCase(); + return value.startsWith("http://") + || value.startsWith("https://") + || value.startsWith("rtsp://") + || value.startsWith("rtsps://"); + } + function resetPlayerElement() { disposeHls(); el.player.pause(); diff --git a/src/main/resources/web/index.html b/src/main/resources/web/index.html index e9bb6f6..42a57e9 100644 --- a/src/main/resources/web/index.html +++ b/src/main/resources/web/index.html @@ -129,7 +129,7 @@